From 342cb792b9d54af247c2514252cfaebf855e4da1 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 16 Jun 2022 01:18:31 +0200 Subject: [PATCH 1/3] use Dalamud's ContextMenu (but doesn't work atm?) --- .../Configuration/PluginConfigurationUI.cs | 8 +- PlayerTags/Data/PluginData.cs | 2 +- .../Features/CustomTagsContextMenuFeature.cs | 126 ++-- .../GameInterface/ContextMenus/ContextMenu.cs | 646 ------------------ .../ContextMenus/ContextMenuItem.cs | 53 -- .../ContextMenus/ContextMenuItemIndicator.cs | 21 - .../ContextMenus/ContextMenuOpenedArgs.cs | 62 -- .../ContextMenus/ContextMenuOpenedDelegate.cs | 8 - .../ContextMenus/ContextMenuReaderWriter.cs | 526 -------------- .../ContextMenus/CustomContextMenuItem.cs | 36 - .../CustomContextMenuItemSelectedArgs.cs | 29 - .../CustomContextMenuItemSelectedDelegate.cs | 8 - .../FFXIV/Client/UI/AddonContextMenu.cs | 14 - .../FFXIV/Client/UI/AddonInterface.cs | 11 - .../FFXIV/Client/UI/Agent/AgentContext.cs | 20 - .../Client/UI/Agent/AgentContextInterface.cs | 15 - .../Client/UI/Agent/AgentContextMenuItems.cs | 15 - .../Client/UI/Agent/AgentInventoryContext.cs | 24 - .../ContextMenus/GameContextMenuItem.cs | 36 - .../ContextMenus/GameObjectContext.cs | 45 -- .../ContextMenus/InventoryItemContext.cs | 36 - .../ContextMenus/OpenSubContextMenuItem.cs | 37 - PlayerTags/PlayerTags.csproj | 2 +- PlayerTags/PluginServices.cs | 1 + 24 files changed, 67 insertions(+), 1714 deletions(-) delete mode 100644 PlayerTags/GameInterface/ContextMenus/ContextMenu.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/ContextMenuItem.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/ContextMenuItemIndicator.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/ContextMenuOpenedArgs.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/ContextMenuOpenedDelegate.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/ContextMenuReaderWriter.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/CustomContextMenuItem.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/CustomContextMenuItemSelectedArgs.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/CustomContextMenuItemSelectedDelegate.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/AddonContextMenu.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/AddonInterface.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentContext.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentContextInterface.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentContextMenuItems.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentInventoryContext.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/GameContextMenuItem.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/GameObjectContext.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/InventoryItemContext.cs delete mode 100644 PlayerTags/GameInterface/ContextMenus/OpenSubContextMenuItem.cs diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index ac14b1a..48fdab5 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -41,6 +41,8 @@ namespace PlayerTags.Configuration return; } + ImGui.SetNextWindowSize(new Vector2(400, 500), ImGuiCond.FirstUseEver); + if (ImGui.Begin(Strings.Loc_Static_PluginName, ref m_PluginConfiguration.IsVisible)) { ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1, 0.8f, 0.5f, 1)); @@ -53,9 +55,9 @@ namespace PlayerTags.Configuration { if (ImGui.BeginTabItem(Strings.Loc_Static_General)) { - //ImGui.Spacing(); - //ImGui.Spacing(); - //DrawCheckbox(nameof(m_PluginConfiguration.IsCustomTagsContextMenuEnabled), true, ref m_PluginConfiguration.IsCustomTagsContextMenuEnabled, () => m_PluginConfiguration.Save(m_PluginData)); + ImGui.Spacing(); + ImGui.Spacing(); + DrawCheckbox(nameof(m_PluginConfiguration.IsCustomTagsContextMenuEnabled), true, ref m_PluginConfiguration.IsCustomTagsContextMenuEnabled, () => m_PluginConfiguration.Save(m_PluginData)); ImGui.Spacing(); diff --git a/PlayerTags/Data/PluginData.cs b/PlayerTags/Data/PluginData.cs index 1adac08..62cd204 100644 --- a/PlayerTags/Data/PluginData.cs +++ b/PlayerTags/Data/PluginData.cs @@ -1,9 +1,9 @@ using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Party; +using Dalamud.Game.Gui.ContextMenus; using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Logging; using PlayerTags.Configuration; -using PlayerTags.GameInterface.ContextMenus; using PlayerTags.PluginStrings; using System; using System.Collections.Generic; diff --git a/PlayerTags/Features/CustomTagsContextMenuFeature.cs b/PlayerTags/Features/CustomTagsContextMenuFeature.cs index 23d832e..0f5db26 100644 --- a/PlayerTags/Features/CustomTagsContextMenuFeature.cs +++ b/PlayerTags/Features/CustomTagsContextMenuFeature.cs @@ -1,7 +1,8 @@ -using Dalamud.Logging; +using Dalamud.Game.Gui.ContextMenus; +using Dalamud.Game.Text.SeStringHandling; +using Dalamud.Logging; using PlayerTags.Configuration; using PlayerTags.Data; -using PlayerTags.GameInterface.ContextMenus; using PlayerTags.Resources; using System; using System.Collections.Generic; @@ -32,84 +33,75 @@ namespace PlayerTags.Features private PluginConfiguration m_PluginConfiguration; private PluginData m_PluginData; - - //private ContextMenu? m_ContextMenu; + private ContextMenu? m_ContextMenu; public CustomTagsContextMenuFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) { m_PluginConfiguration = pluginConfiguration; m_PluginData = pluginData; - - //m_ContextMenu = new ContextMenu(); - //if (!m_ContextMenu.IsValid) - //{ - // m_ContextMenu = null; - //} - //if (m_ContextMenu != null) - //{ - // m_ContextMenu.ContextMenuOpened += ContextMenuHooks_ContextMenuOpened; - //} + m_ContextMenu = new ContextMenu(); + + if (m_PluginConfiguration.IsCustomTagsContextMenuEnabled) + { + m_ContextMenu.ContextMenuOpened += ContextMenuHooks_ContextMenuOpened; + PluginServices.GameGui.Enable(); + } } public void Dispose() { - //if (m_ContextMenu != null) - //{ - // m_ContextMenu.ContextMenuOpened -= ContextMenuHooks_ContextMenuOpened; - - // m_ContextMenu.Dispose(); - // m_ContextMenu = null; - //} + if (m_ContextMenu != null) + { + m_ContextMenu.ContextMenuOpened -= ContextMenuHooks_ContextMenuOpened; + ((IDisposable)m_ContextMenu).Dispose(); + m_ContextMenu = null; + } } - //private void ContextMenuHooks_ContextMenuOpened(ContextMenuOpenedArgs contextMenuOpenedArgs) - //{ - // if (!m_PluginConfiguration.IsCustomTagsContextMenuEnabled - // || !SupportedAddonNames.Contains(contextMenuOpenedArgs.ParentAddonName)) - // { - // return; - // } + private void ContextMenuHooks_ContextMenuOpened(ContextMenuOpenedArgs contextMenuOpenedArgs) + { + if (!m_PluginConfiguration.IsCustomTagsContextMenuEnabled + || !SupportedAddonNames.Contains(contextMenuOpenedArgs.ParentAddonName)) + { + return; + } - // Identity? identity = m_PluginData.GetIdentity(contextMenuOpenedArgs); - // if (identity != null) - // { - // var notAddedTags = m_PluginData.CustomTags.Where(customTag => !identity.CustomTagIds.Contains(customTag.CustomId.Value)); - // if (notAddedTags.Any()) - // { - // contextMenuOpenedArgs.Items.Add(new OpenSubContextMenuItem(Strings.Loc_Static_ContextMenu_AddTag, (subContextMenuOpenedArgs => - // { - // List newContextMenuItems = new List(); - // foreach (var notAddedTag in notAddedTags) - // { - // newContextMenuItems.Add(new CustomContextMenuItem(notAddedTag.Text.Value, (args => - // { - // m_PluginData.AddCustomTagToIdentity(notAddedTag, identity); - // m_PluginConfiguration.Save(m_PluginData); - // }))); - // } - // subContextMenuOpenedArgs.Items.InsertRange(0, newContextMenuItems); - // }))); - // } + Identity? identity = m_PluginData.GetIdentity(contextMenuOpenedArgs); + if (identity != null) + { + var notAddedTags = m_PluginData.CustomTags.Where(customTag => !identity.CustomTagIds.Contains(customTag.CustomId.Value)); + if (notAddedTags.Any()) + { + contextMenuOpenedArgs.AddCustomSubMenu(Strings.Loc_Static_ContextMenu_AddTag, subContextMenuOpenedArgs => + { + foreach (var notAddedTag in notAddedTags) + { + subContextMenuOpenedArgs.AddCustomItem(notAddedTag.Text.Value, args => + { + m_PluginData.AddCustomTagToIdentity(notAddedTag, identity); + m_PluginConfiguration.Save(m_PluginData); + }); + } + }); + } - // var addedTags = m_PluginData.CustomTags.Where(customTag => identity.CustomTagIds.Contains(customTag.CustomId.Value)); - // if (addedTags.Any()) - // { - // contextMenuOpenedArgs.Items.Add(new OpenSubContextMenuItem(Strings.Loc_Static_ContextMenu_RemoveTag, (subContextMenuOpenedArgs => - // { - // List newContextMenuItems = new List(); - // foreach (var addedTag in addedTags) - // { - // newContextMenuItems.Add(new CustomContextMenuItem(addedTag.Text.Value, (args => - // { - // m_PluginData.RemoveCustomTagFromIdentity(addedTag, identity); - // m_PluginConfiguration.Save(m_PluginData); - // }))); - // } - // subContextMenuOpenedArgs.Items.InsertRange(0, newContextMenuItems); - // }))); - // } - // } - //} + var addedTags = m_PluginData.CustomTags.Where(customTag => identity.CustomTagIds.Contains(customTag.CustomId.Value)); + if (addedTags.Any()) + { + contextMenuOpenedArgs.AddCustomSubMenu(Strings.Loc_Static_ContextMenu_RemoveTag, subContextMenuOpenedArgs => + { + foreach (var addedTag in addedTags) + { + subContextMenuOpenedArgs.AddCustomItem(addedTag.Text.Value, args => + { + m_PluginData.RemoveCustomTagFromIdentity(addedTag, identity); + m_PluginConfiguration.Save(m_PluginData); + }); + } + }); + } + } + } } } diff --git a/PlayerTags/GameInterface/ContextMenus/ContextMenu.cs b/PlayerTags/GameInterface/ContextMenus/ContextMenu.cs deleted file mode 100644 index b32bae1..0000000 --- a/PlayerTags/GameInterface/ContextMenus/ContextMenu.cs +++ /dev/null @@ -1,646 +0,0 @@ -using Dalamud.Game; -using Dalamud.Game.Text.SeStringHandling; -using Dalamud.Hooking; -using Dalamud.Logging; -using FFXIVClientStructs.FFXIV.Client.Game; -using FFXIVClientStructs.FFXIV.Client.UI; -using FFXIVClientStructs.FFXIV.Client.UI.Agent; -using FFXIVClientStructs.FFXIV.Component.GUI; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; - -namespace PlayerTags.GameInterface.ContextMenus -{ - internal unsafe delegate void AtkValueChangeTypeDelegate_Unmanaged(AtkValue* thisPtr, FFXIVClientStructs.FFXIV.Component.GUI.ValueType type); - internal unsafe delegate void AtkValueSetStringDelegate_Unmanaged(AtkValue* thisPtr, byte* bytes); - - /// - /// Provides an interface to modify context menus. - /// - public class ContextMenu : IDisposable - { - private class PluginAddressResolver : BaseAddressResolver - { - private const string c_AtkValueChangeType = "E8 ?? ?? ?? ?? 45 84 F6 48 8D 4C 24"; - public IntPtr? AtkValueChangeTypePtr { get; private set; } - - private const string c_AtkValueSetString = "E8 ?? ?? ?? ?? 41 03 ED"; - public IntPtr? AtkValueSetStringPtr { get; private set; } - - private const string c_GetAddonById = "E8 ?? ?? ?? ?? 8B 6B 20"; - public IntPtr? GetAddonByIdPtr { get; private set; } - - private const string c_OpenSubContextMenu = "E8 ?? ?? ?? ?? 44 39 A3 ?? ?? ?? ?? 0F 86"; - public IntPtr? OpenSubContextMenuPtr { get; private set; } - - private const string c_ContextMenuOpening = "E8 ?? ?? ?? ?? 0F B7 C0 48 83 C4 60"; - public IntPtr? ContextMenuOpeningPtr { get; private set; } - - private const string c_ContextMenuOpened = "48 8B C4 57 41 56 41 57 48 81 EC"; - public IntPtr? ContextMenuOpenedPtr { get; private set; } - - private const string c_ContextMenuItemSelected = "48 89 5C 24 ?? 55 57 41 56 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 44 24 ?? 80 B9"; - public IntPtr? ContextMenuItemSelectedPtr { get; private set; } - - private const string c_SubContextMenuOpening = "E8 ?? ?? ?? ?? 44 39 A3 ?? ?? ?? ?? 0F 84"; - public IntPtr? SubContextMenuOpeningPtr { get; private set; } - - private const string c_SubContextMenuOpened = "48 8B C4 57 41 55 41 56 48 81 EC"; - public IntPtr? SubContextMenuOpenedPtr { get; private set; } - - protected override void Setup64Bit(SigScanner scanner) - { - if (scanner.TryScanText(c_AtkValueChangeType, out var atkValueChangeTypePtr)) - { - AtkValueChangeTypePtr = atkValueChangeTypePtr; - } - - if (scanner.TryScanText(c_AtkValueSetString, out var atkValueSetStringPtr)) - { - AtkValueSetStringPtr = atkValueSetStringPtr; - } - - if (scanner.TryScanText(c_GetAddonById, out var getAddonByIdPtr)) - { - GetAddonByIdPtr = getAddonByIdPtr; - } - - if (scanner.TryScanText(c_OpenSubContextMenu, out var openSubContextMenuPtr)) - { - OpenSubContextMenuPtr = openSubContextMenuPtr; - } - - if (scanner.TryScanText(c_ContextMenuOpening, out var someOpenAddonThingPtr)) - { - ContextMenuOpeningPtr = someOpenAddonThingPtr; - } - - if (scanner.TryScanText(c_ContextMenuOpened, out var contextMenuOpenedPtr)) - { - ContextMenuOpenedPtr = contextMenuOpenedPtr; - } - - if (scanner.TryScanText(c_ContextMenuItemSelected, out var contextMenuItemSelectedPtr)) - { - ContextMenuItemSelectedPtr = contextMenuItemSelectedPtr; - } - - if (scanner.TryScanText(c_SubContextMenuOpening, out var subContextMenuOpening)) - { - SubContextMenuOpeningPtr = subContextMenuOpening; - } - - if (scanner.TryScanText(c_SubContextMenuOpened, out var titleScreenContextMenuOpenedPtr)) - { - SubContextMenuOpenedPtr = titleScreenContextMenuOpenedPtr; - } - } - } - - private readonly AtkValueChangeTypeDelegate_Unmanaged? m_AtkValueChangeType; - private readonly AtkValueSetStringDelegate_Unmanaged? m_AtkValueSetString; - - private unsafe delegate AddonInterface* GetAddonByIdDelegate_Unmanaged(RaptureAtkUnitManager* raptureAtkUnitManager, ushort id); - private readonly GetAddonByIdDelegate_Unmanaged? m_GetAddonById; - - private unsafe delegate bool OpenSubContextMenuDelegate_Unmanaged(AgentContext* agentContext); - private readonly OpenSubContextMenuDelegate_Unmanaged? m_OpenSubContextMenu; - - private unsafe delegate IntPtr ContextMenuOpeningDelegate_Unmanaged(IntPtr a1, IntPtr a2, IntPtr a3, uint a4, IntPtr a5, AgentContextInterface* agentContextInterface, IntPtr a7, ushort a8); - private Hook? m_ContextMenuOpeningHook; - - private unsafe delegate bool ContextMenuOpenedDelegate_Unmanaged(AddonContextMenu* addonContextMenu, int menuSize, AtkValue* atkValueArgs); - private Hook? m_ContextMenuOpenedHook; - private Hook? m_SubContextMenuOpenedHook; - - private unsafe delegate bool ContextMenuItemSelectedDelegate_Unmanaged(AddonContextMenu* addonContextMenu, int selectedIndex, byte a3); - private Hook? m_ContextMenuItemSelectedHook; - - private unsafe delegate bool SubContextMenuOpeningDelegate_Unmanaged(AgentContext* agentContext); - private Hook? m_SubContextMenuOpeningHook; - - private PluginAddressResolver m_PluginAddressResolver; - - private const int MaxContextMenuItemsPerContextMenu = 32; - - private unsafe AgentContextInterface* m_CurrentAgentContextInterface; - private IntPtr m_CurrentSubContextMenuTitle; - - private OpenSubContextMenuItem? m_SelectedOpenSubContextMenuItem; - private ContextMenuOpenedArgs? m_CurrentContextMenuOpenedArgs; - - /// - /// Occurs when a context menu is opened by the game. - /// - public event ContextMenuOpenedDelegate? ContextMenuOpened; - - /// - /// Whether the required hooks are in place and this instance is valid. - /// - public bool IsValid - { - get - { - if (!m_PluginAddressResolver.AtkValueChangeTypePtr.HasValue - || !m_PluginAddressResolver.AtkValueSetStringPtr.HasValue - || !m_PluginAddressResolver.GetAddonByIdPtr.HasValue - || !m_PluginAddressResolver.OpenSubContextMenuPtr.HasValue - || !m_PluginAddressResolver.ContextMenuOpeningPtr.HasValue - || !m_PluginAddressResolver.ContextMenuOpenedPtr.HasValue - || !m_PluginAddressResolver.ContextMenuItemSelectedPtr.HasValue - || !m_PluginAddressResolver.SubContextMenuOpeningPtr.HasValue - || !m_PluginAddressResolver.SubContextMenuOpenedPtr.HasValue - ) - { - return false; - } - - return true; - } - } - - public ContextMenu() - { - m_PluginAddressResolver = new PluginAddressResolver(); - m_PluginAddressResolver.Setup(); - if (!IsValid) - { - return; - } - - if (m_PluginAddressResolver.AtkValueChangeTypePtr.HasValue) - { - m_AtkValueChangeType = Marshal.GetDelegateForFunctionPointer(m_PluginAddressResolver.AtkValueChangeTypePtr.Value); - } - - if (m_PluginAddressResolver.AtkValueSetStringPtr.HasValue) - { - m_AtkValueSetString = Marshal.GetDelegateForFunctionPointer(m_PluginAddressResolver.AtkValueSetStringPtr.Value); - } - - if (m_PluginAddressResolver.GetAddonByIdPtr.HasValue) - { - m_GetAddonById = Marshal.GetDelegateForFunctionPointer(m_PluginAddressResolver.GetAddonByIdPtr.Value); - } - - if (m_PluginAddressResolver.OpenSubContextMenuPtr.HasValue) - { - m_OpenSubContextMenu = Marshal.GetDelegateForFunctionPointer(m_PluginAddressResolver.OpenSubContextMenuPtr.Value); - } - - if (m_PluginAddressResolver.ContextMenuOpeningPtr.HasValue) - { - unsafe - { - m_ContextMenuOpeningHook = new Hook(m_PluginAddressResolver.ContextMenuOpeningPtr.Value, ContextMenuOpeningDetour); - } - m_ContextMenuOpeningHook?.Enable(); - } - - if (m_PluginAddressResolver.ContextMenuOpenedPtr.HasValue) - { - unsafe - { - m_ContextMenuOpenedHook = new Hook(m_PluginAddressResolver.ContextMenuOpenedPtr.Value, ContextMenuOpenedDetour); - } - m_ContextMenuOpenedHook?.Enable(); - } - - if (m_PluginAddressResolver.ContextMenuItemSelectedPtr.HasValue) - { - unsafe - { - m_ContextMenuItemSelectedHook = new Hook(m_PluginAddressResolver.ContextMenuItemSelectedPtr.Value, ContextMenuItemSelectedDetour); - } - m_ContextMenuItemSelectedHook?.Enable(); - } - - if (m_PluginAddressResolver.SubContextMenuOpeningPtr.HasValue) - { - unsafe - { - m_SubContextMenuOpeningHook = new Hook(m_PluginAddressResolver.SubContextMenuOpeningPtr.Value, SubContextMenuOpeningDetour); - } - m_SubContextMenuOpeningHook?.Enable(); - } - - if (m_PluginAddressResolver.SubContextMenuOpenedPtr.HasValue) - { - unsafe - { - m_SubContextMenuOpenedHook = new Hook(m_PluginAddressResolver.SubContextMenuOpenedPtr.Value, SubContextMenuOpenedDetour); - } - m_SubContextMenuOpenedHook?.Enable(); - } - } - - public void Dispose() - { - m_SubContextMenuOpeningHook?.Disable(); - m_ContextMenuItemSelectedHook?.Disable(); - m_SubContextMenuOpenedHook?.Disable(); - m_ContextMenuOpenedHook?.Disable(); - m_ContextMenuOpeningHook?.Disable(); - } - - private unsafe IntPtr ContextMenuOpeningDetour(IntPtr a1, IntPtr a2, IntPtr a3, uint a4, IntPtr a5, AgentContextInterface* agentContextInterface, IntPtr a7, ushort a8) - { - m_CurrentAgentContextInterface = agentContextInterface; - return m_ContextMenuOpeningHook!.Original(a1, a2, a3, a4, a5, agentContextInterface, a7, a8); - } - - private unsafe bool ContextMenuOpenedDetour(AddonContextMenu* addonContextMenu, int atkValueCount, AtkValue* atkValues) - { - if (m_ContextMenuOpenedHook == null) - { - return false; - } - - try - { - ContextMenuOpenedImplementation(addonContextMenu, ref atkValueCount, ref atkValues); - } - catch (Exception ex) - { - PluginLog.Error(ex, "ContextMenuOpenedDetour"); - } - - return m_ContextMenuOpenedHook.Original(addonContextMenu, atkValueCount, atkValues); - } - - private unsafe void ContextMenuOpenedImplementation(AddonContextMenu* addonContextMenu, ref int atkValueCount, ref AtkValue* atkValues) - { - if (m_AtkValueChangeType == null - || m_AtkValueSetString == null - || ContextMenuOpened == null - || m_CurrentAgentContextInterface == null) - { - return; - } - - ContextMenuReaderWriter contextMenuReaderWriter = new ContextMenuReaderWriter(m_CurrentAgentContextInterface, atkValueCount, atkValues); - - // Check for a title. - string? title = null; - if (m_SelectedOpenSubContextMenuItem != null) - { - title = m_SelectedOpenSubContextMenuItem.Name.TextValue; - - // Write the custom title - var titleAtkValue = &atkValues[1]; - fixed (byte* TtlePtr = m_SelectedOpenSubContextMenuItem.Name.Encode().NullTerminate()) - { - m_AtkValueSetString(titleAtkValue, TtlePtr); - } - } - else if (contextMenuReaderWriter.Title != null) - { - title = contextMenuReaderWriter.Title.TextValue; - } - - // Determine which event to raise. - ContextMenuOpenedDelegate contextMenuOpenedDelegate = ContextMenuOpened; - if (m_SelectedOpenSubContextMenuItem is OpenSubContextMenuItem openSubContextMenuItem) - { - contextMenuOpenedDelegate = openSubContextMenuItem.Opened; - } - - // Get the existing items from the game. - // TODO: For inventory sub context menus, we take only the last item -- the return item. - // This is because we're doing a hack to spawn a Second Tier sub context menu and then appropriating it. - var contextMenuItems = contextMenuReaderWriter.Read(); - if (IsInventoryContext(m_CurrentAgentContextInterface) && m_SelectedOpenSubContextMenuItem != null) - { - contextMenuItems = contextMenuItems.TakeLast(1).ToArray(); - } - - int beforeHashCode = GetContextMenuItemsHashCode(contextMenuItems); - - // Raise the event and get the context menu changes. - m_CurrentContextMenuOpenedArgs = NotifyContextMenuOpened(addonContextMenu, m_CurrentAgentContextInterface, title, contextMenuOpenedDelegate, contextMenuItems); - if (m_CurrentContextMenuOpenedArgs == null) - { - return; - } - - int afterHashCode = GetContextMenuItemsHashCode(m_CurrentContextMenuOpenedArgs.Items); - - PluginLog.Warning($"{beforeHashCode}={afterHashCode}"); - - // Only write to memory if the items were actually changed. - if (beforeHashCode != afterHashCode) - { - // Write the new changes. - contextMenuReaderWriter.Write(m_CurrentContextMenuOpenedArgs.Items, m_AtkValueChangeType, m_AtkValueSetString); - - // Update the addon. - atkValueCount = *(&addonContextMenu->AtkValuesCount) = (ushort)contextMenuReaderWriter.AtkValueCount; - atkValues = *(&addonContextMenu->AtkValues) = contextMenuReaderWriter.AtkValues; - } - } - - private unsafe bool SubContextMenuOpeningDetour(AgentContext* agentContext) - { - if (m_SubContextMenuOpeningHook == null) - { - return false; - } - - if (SubContextMenuOpeningImplementation(agentContext)) - { - return true; - } - - return m_SubContextMenuOpeningHook.Original(agentContext); - } - - private unsafe bool SubContextMenuOpeningImplementation(AgentContext* agentContext) - { - if (m_OpenSubContextMenu == null - || m_AtkValueChangeType == null - || m_AtkValueSetString == null - || !(m_SelectedOpenSubContextMenuItem is OpenSubContextMenuItem)) - { - return false; - } - - // The important things to make this work are: - // 1. Allocate a temporary sub context menu title. The value doesn't matter, we'll set it later. - // 2. Context menu item count must equal 1 to tell the game there is enough space for the "< Return" item. - // 3. Atk value count must equal the index of the first context menu item. - // This is enough to keep the base data, but excludes the context menu item data. - // We want to exclude context menu item data in this function because the game sometimes includes garbage items which can cause problems. - // After this function, the game adds the "< Return" item, and THEN we add our own items after that. - - m_OpenSubContextMenu(agentContext); - - // Allocate a new 1 byte title. This is required for the game to render the titled context menu style. - // The actual value doesn't matter at this point, we'll set it later. - GameInterfaceHelper.GameFree(ref m_CurrentSubContextMenuTitle, (ulong)IntPtr.Size); - m_CurrentSubContextMenuTitle = GameInterfaceHelper.GameUIAllocate(1); - *(&(&agentContext->AgentContextInterface)->SubContextMenuTitle) = (byte*)m_CurrentSubContextMenuTitle; - *(byte*)m_CurrentSubContextMenuTitle = 0; - - // Expect at least 1 context menu item. - (&agentContext->Items->AtkValues)[0].UInt = 1; - - // Expect a title. This isn't needed by the game, it's needed by ContextMenuReaderWriter which uses this to check if it's a context menu - m_AtkValueChangeType(&(&agentContext->Items->AtkValues)[1], FFXIVClientStructs.FFXIV.Component.GUI.ValueType.String); - (&agentContext->Items->AtkValues)[1].String = (byte*)0; - - ContextMenuReaderWriter contextMenuReaderWriter = new ContextMenuReaderWriter(&agentContext->AgentContextInterface, agentContext->Items->AtkValueCount, &agentContext->Items->AtkValues); - *(&agentContext->Items->AtkValueCount) = (ushort)contextMenuReaderWriter.FirstContextMenuItemIndex; - - return true; - } - - private unsafe bool SubContextMenuOpenedDetour(AddonContextMenu* addonContextMenu, int atkValueCount, AtkValue* atkValues) - { - if (m_SubContextMenuOpenedHook == null) - { - return false; - } - - try - { - SubContextMenuOpenedImplementation(addonContextMenu, ref atkValueCount, ref atkValues); - } - catch (Exception ex) - { - PluginLog.Error(ex, "SubContextMenuOpenedDetour"); - } - - return m_SubContextMenuOpenedHook.Original(addonContextMenu, atkValueCount, atkValues); - } - - private unsafe void SubContextMenuOpenedImplementation(AddonContextMenu* addonContextMenu, ref int atkValueCount, ref AtkValue* atkValues) - { - ContextMenuOpenedImplementation(addonContextMenu, ref atkValueCount, ref atkValues); - } - - private int GetContextMenuItemsHashCode(IEnumerable contextMenuItems) - { - unchecked - { - int hash = 17; - foreach (var item in contextMenuItems) - { - hash = hash * 23 + item.GetHashCode(); - } - return hash; - } - } - - private unsafe ContextMenuOpenedArgs? NotifyContextMenuOpened(AddonContextMenu* addonContextMenu, AgentContextInterface* agentContextInterface, string? title, ContextMenuOpenedDelegate contextMenuOpenedDelegate, IEnumerable initialContextMenuItems) - { - var parentAddonName = GetParentAddonName(&addonContextMenu->AddonInterface); - - InventoryItemContext? inventoryItemContext = null; - GameObjectContext? gameObjectContext = null; - if (IsInventoryContext(agentContextInterface)) - { - var agentInventoryContext = (AgentInventoryContext*)agentContextInterface; - inventoryItemContext = new InventoryItemContext(agentInventoryContext->InventoryItemId, agentInventoryContext->InventoryItemCount, agentInventoryContext->InventoryItemIsHighQuality); - } - else - { - var agentContext = (AgentContext*)agentContextInterface; - - uint? id = agentContext->GameObjectId; - if (id == 0) - { - id = null; - } - - ulong? contentId = agentContext->GameObjectContentId; - if (contentId == 0) - { - contentId = null; - } - - string? name; - unsafe - { - name = GameInterfaceHelper.ReadSeString((IntPtr)agentContext->GameObjectName.StringPtr).TextValue; - if (string.IsNullOrEmpty(name)) - { - name = null; - } - } - - ushort? worldId = agentContext->GameObjectWorldId; - if (worldId == 0) - { - worldId = null; - } - - if (id != null - || contentId != null - || name != null - || worldId != null) - { - gameObjectContext = new GameObjectContext(id, contentId, name, worldId); - } - } - - // Temporarily remove the < Return item, for UX we should enforce that it is always last in the list. - var lastContextMenuItem = initialContextMenuItems.LastOrDefault(); - if (lastContextMenuItem is GameContextMenuItem gameContextMenuItem && gameContextMenuItem.SelectedAction == 102) - { - initialContextMenuItems = initialContextMenuItems.SkipLast(1); - } - - var contextMenuOpenedArgs = new ContextMenuOpenedArgs((IntPtr)addonContextMenu, (IntPtr)agentContextInterface, parentAddonName, initialContextMenuItems) - { - Title = title, - InventoryItemContext = inventoryItemContext, - GameObjectContext = gameObjectContext - }; - - try - { - contextMenuOpenedDelegate.Invoke(contextMenuOpenedArgs); - } - catch (Exception ex) - { - PluginLog.LogError(ex, "NotifyContextMenuOpened"); - return null; - } - - // Readd the < Return item - if (lastContextMenuItem is GameContextMenuItem gameContextMenuItem1 && gameContextMenuItem1.SelectedAction == 102) - { - contextMenuOpenedArgs.Items.Add(lastContextMenuItem); - } - - foreach (var contextMenuItem in contextMenuOpenedArgs.Items.ToArray()) - { - // TODO: Game doesn't support nested sub context menus, but we might be able to. - if (contextMenuItem is OpenSubContextMenuItem && contextMenuOpenedArgs.Title != null) - { - contextMenuOpenedArgs.Items.Remove(contextMenuItem); - PluginLog.Warning($"Context menu '{contextMenuOpenedArgs.Title}' item '{contextMenuItem}' has been removed because nested sub context menus are not supported."); - } - } - - if (contextMenuOpenedArgs.Items.Count > MaxContextMenuItemsPerContextMenu) - { - PluginLog.LogWarning($"Context menu requesting {contextMenuOpenedArgs.Items.Count} of max {MaxContextMenuItemsPerContextMenu} items. Resizing list to compensate."); - contextMenuOpenedArgs.Items.RemoveRange(MaxContextMenuItemsPerContextMenu, contextMenuOpenedArgs.Items.Count - MaxContextMenuItemsPerContextMenu); - } - - return contextMenuOpenedArgs; - } - - private unsafe bool ContextMenuItemSelectedDetour(AddonContextMenu* addonContextMenu, int selectedIndex, byte a3) - { - if (m_ContextMenuItemSelectedHook == null) - { - return false; - } - - try - { - ContextMenuItemSelectedImplementation(addonContextMenu, selectedIndex); - } - catch (Exception ex) - { - PluginLog.Error(ex, "ContextMenuItemSelectedDetour"); - } - - return m_ContextMenuItemSelectedHook.Original(addonContextMenu, selectedIndex, a3); - } - - private unsafe void ContextMenuItemSelectedImplementation(AddonContextMenu* addonContextMenu, int selectedIndex) - { - if (m_CurrentContextMenuOpenedArgs == null || selectedIndex == -1) - { - m_CurrentContextMenuOpenedArgs = null; - m_SelectedOpenSubContextMenuItem = null; - return; - } - - // Read the selected item directly from the game - ContextMenuReaderWriter contextMenuReaderWriter = new ContextMenuReaderWriter(m_CurrentAgentContextInterface, addonContextMenu->AtkValuesCount, addonContextMenu->AtkValues); - var gameContextMenuItems = contextMenuReaderWriter.Read(); - var gameSelectedItem = gameContextMenuItems.ElementAtOrDefault(selectedIndex); - - // This should be impossible - if (gameSelectedItem == null) - { - m_CurrentContextMenuOpenedArgs = null; - m_SelectedOpenSubContextMenuItem = null; - return; - } - - // Match it with the items we already know about based on its name. - // We can get into a state where we have a game item we don't recognize when another plugin has added one. - var selectedItem = m_CurrentContextMenuOpenedArgs.Items.FirstOrDefault(item => item.Name.Encode().SequenceEqual(gameSelectedItem.Name.Encode())); - - m_SelectedOpenSubContextMenuItem = null; - if (selectedItem is CustomContextMenuItem customContextMenuItem) - { - try - { - var customContextMenuItemSelectedArgs = new CustomContextMenuItemSelectedArgs(m_CurrentContextMenuOpenedArgs, customContextMenuItem); - customContextMenuItem.ItemSelected(customContextMenuItemSelectedArgs); - } - catch (Exception ex) - { - PluginLog.LogError(ex, "ContextMenuItemSelectedImplementation"); - } - } - else if (selectedItem is OpenSubContextMenuItem openSubContextMenuItem) - { - m_SelectedOpenSubContextMenuItem = openSubContextMenuItem; - } - - m_CurrentContextMenuOpenedArgs = null; - } - - private unsafe string? GetParentAddonName(AddonInterface* addonInterface) - { - if (m_GetAddonById == null) - { - return null; - } - - var parentAddonId = addonInterface->ParentAddonId; - if (parentAddonId == 0) - { - return null; - } - - var atkStage = AtkStage.GetSingleton(); - var parentAddon = m_GetAddonById(atkStage->RaptureAtkUnitManager, parentAddonId); - return GameInterfaceHelper.ReadString((IntPtr)(&parentAddon->Name)); - } - - private unsafe bool IsInventoryContext(AgentContextInterface* agentContextInterface) - { - if (agentContextInterface == AgentInventoryContext.Instance()) - { - return true; - } - - return false; - } - - private unsafe AddonInterface* GetAddonFromAgent(AgentInterface* agentInterface) - { - if (m_GetAddonById == null) - { - return null; - } - - if (agentInterface->AddonId == 0) - { - return null; - } - - return m_GetAddonById(AtkStage.GetSingleton()->RaptureAtkUnitManager, (ushort)agentInterface->AddonId); - } - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/ContextMenuItem.cs b/PlayerTags/GameInterface/ContextMenus/ContextMenuItem.cs deleted file mode 100644 index 779e9ac..0000000 --- a/PlayerTags/GameInterface/ContextMenus/ContextMenuItem.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Dalamud.Game.Text.SeStringHandling; -using System; -using System.Numerics; - -namespace PlayerTags.GameInterface.ContextMenus -{ - /// - /// An item in a context menu. - /// - public abstract class ContextMenuItem - { - /// - /// The name of the item. - /// - public SeString Name { get; set; } - - /// - /// Whether the item is enabled. When enabled, an item is selectable. - /// - public bool IsEnabled { get; set; } = true; - - /// - /// The indicator of the item. - /// - public ContextMenuItemIndicator Indicator { get; set; } = ContextMenuItemIndicator.None; - - /// - /// Initializes a new instance of the class. - /// - /// The name of the item. - public ContextMenuItem(SeString name) - { - Name = name; - } - - public override string ToString() - { - return Name.ToString(); - } - - public override int GetHashCode() - { - unchecked - { - int hash = 17; - hash = hash * 23 + new BigInteger(Name.Encode()).GetHashCode(); - hash = hash * 23 + IsEnabled.GetHashCode(); - hash = hash * 23 + ((int)Indicator).GetHashCode(); - return hash; - } - } - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/ContextMenuItemIndicator.cs b/PlayerTags/GameInterface/ContextMenus/ContextMenuItemIndicator.cs deleted file mode 100644 index 4fac0bf..0000000 --- a/PlayerTags/GameInterface/ContextMenus/ContextMenuItemIndicator.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace PlayerTags.GameInterface.ContextMenus -{ - /// - /// An indicator displayed on a context menu item. - /// - public enum ContextMenuItemIndicator - { - /// - /// The item has no indicator. - /// - None, - /// - /// The item has a previous indicator. - /// - Previous, - /// - /// The item has a next indicator. - /// - Next - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/ContextMenuOpenedArgs.cs b/PlayerTags/GameInterface/ContextMenus/ContextMenuOpenedArgs.cs deleted file mode 100644 index 51abe36..0000000 --- a/PlayerTags/GameInterface/ContextMenus/ContextMenuOpenedArgs.cs +++ /dev/null @@ -1,62 +0,0 @@ -using Dalamud.Game.Text.SeStringHandling; -using System; -using System.Collections.Generic; - -namespace PlayerTags.GameInterface.ContextMenus -{ - /// - /// Provides data for methods. - /// - public class ContextMenuOpenedArgs - { - /// - /// The addon associated with the context menu. - /// - public IntPtr Addon { get; } - - /// - /// The agent associated with the context menu. - /// - public IntPtr Agent { get; } - - /// - /// The the name of the parent addon associated with the context menu. - /// - public string? ParentAddonName { get; } - - /// - /// The title of the context menu. - /// - public string? Title { get; init; } - - /// - /// The items in the context menu. - /// - public List Items { get; } - - /// - /// The game object context associated with the context menu. - /// - public GameObjectContext? GameObjectContext { get; init; } - - /// - /// The item context associated with the context menu. - /// - public InventoryItemContext? InventoryItemContext { get; init; } - - /// - /// Initializes a new instance of the class. - /// - /// The addon associated with the context menu. - /// The agent associated with the context menu. - /// The the name of the parent addon associated with the context menu. - /// The items in the context menu. - public ContextMenuOpenedArgs(IntPtr addon, IntPtr agent, string? parentAddonName, IEnumerable items) - { - Addon = addon; - Agent = agent; - ParentAddonName = parentAddonName; - Items = new List(items); - } - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/ContextMenuOpenedDelegate.cs b/PlayerTags/GameInterface/ContextMenus/ContextMenuOpenedDelegate.cs deleted file mode 100644 index c6a22de..0000000 --- a/PlayerTags/GameInterface/ContextMenus/ContextMenuOpenedDelegate.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace PlayerTags.GameInterface.ContextMenus -{ - /// - /// Represents the method the event. - /// - /// The data associated with the event. - public delegate void ContextMenuOpenedDelegate(ContextMenuOpenedArgs args); -} diff --git a/PlayerTags/GameInterface/ContextMenus/ContextMenuReaderWriter.cs b/PlayerTags/GameInterface/ContextMenus/ContextMenuReaderWriter.cs deleted file mode 100644 index cd0b200..0000000 --- a/PlayerTags/GameInterface/ContextMenus/ContextMenuReaderWriter.cs +++ /dev/null @@ -1,526 +0,0 @@ -using Dalamud.Game.Text.SeStringHandling; -using Dalamud.Logging; -using FFXIVClientStructs.FFXIV.Client.UI.Agent; -using FFXIVClientStructs.FFXIV.Component.GUI; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using System.Runtime.InteropServices; - -namespace PlayerTags.GameInterface.ContextMenus -{ - internal unsafe class ContextMenuReaderWriter - { - private enum SubContextMenuStructLayout - { - Main, - Alternate - } - - private AgentContextInterface* m_AgentContextInterface; - - private int m_AtkValueCount; - public int AtkValueCount - { - get { return m_AtkValueCount; } - } - - private AtkValue* m_AtkValues; - public AtkValue* AtkValues - { - get { return m_AtkValues; } - } - - public int ContextMenuItemCount - { - get { return m_AtkValues[0].Int; } - } - - public bool HasTitle - { - get - { - bool isStringType = - (int)m_AtkValues[1].Type == 8 - || (int)m_AtkValues[1].Type == 38 - || m_AtkValues[1].Type == FFXIVClientStructs.FFXIV.Component.GUI.ValueType.String; - - return isStringType; - } - } - - public SeString? Title - { - get - { - if (HasTitle) - { - GameInterfaceHelper.TryReadSeString((IntPtr)(&m_AtkValues[1])->String, out var str); - return str; - } - - return null; - } - } - - public int HasPreviousIndicatorFlagsIndex - { - get - { - if (HasTitle) - { - return 6; - } - - return 2; - } - } - - public int HasNextIndicatorFlagsIndex - { - get - { - if (HasTitle) - { - return 5; - } - - return 3; - } - } - - public int FirstContextMenuItemIndex - { - get - { - if (HasTitle) - { - return 8; - } - - return 7; - } - } - - public int NameIndexOffset - { - get - { - if (HasTitle && StructLayout == SubContextMenuStructLayout.Alternate) - { - return 1; - } - - return 0; - } - } - - public int IsDisabledIndexOffset - { - get - { - if (HasTitle && StructLayout == SubContextMenuStructLayout.Alternate) - { - return 2; - } - - return ContextMenuItemCount; - } - } - - /// - /// 0x14000000 | action - /// - public int? MaskedActionIndexOffset - { - get - { - if (HasTitle && StructLayout == SubContextMenuStructLayout.Alternate) - { - return 3; - } - - return null; - } - } - - public int SequentialAtkValuesPerContextMenuItem - { - get - { - if (HasTitle && StructLayout == SubContextMenuStructLayout.Alternate) - { - return 4; - } - - return 1; - } - } - - public int TotalDesiredAtkValuesPerContextMenuItem - { - get - { - if (HasTitle && StructLayout == SubContextMenuStructLayout.Alternate) - { - return 4; - } - - return 2; - } - } - - public Vector2? Position - { - get - { - if (HasTitle) - { - return new Vector2(m_AtkValues[2].Int, m_AtkValues[3].Int); - } - - return null; - } - } - - public unsafe bool IsInventoryContext - { - get - { - if ((IntPtr)m_AgentContextInterface == (IntPtr)AgentInventoryContext.Instance()) - { - return true; - } - - return false; - } - } - - private SubContextMenuStructLayout? StructLayout - { - get - { - if (HasTitle) - { - if (m_AtkValues[7].Int == 8) - { - return SubContextMenuStructLayout.Alternate; - } - else if (m_AtkValues[7].Int == 1) - { - return SubContextMenuStructLayout.Main; - } - } - - return null; - } - } - - public byte NoopAction - { - get - { - if (IsInventoryContext) - { - return 0xff; - } - else - { - return 0x67; - } - } - } - - public byte OpenSubContextMenuAction - { - get - { - if (IsInventoryContext) - { - // This is actually the action to open the Second Tier context menu and we just hack around it - return 0x31; - } - else - { - return 0x66; - } - } - } - - public byte? FirstUnhandledAction - { - get - { - if (StructLayout != null && StructLayout == SubContextMenuStructLayout.Alternate) - { - return 0x68; - } - - return null; - } - } - - public ContextMenuReaderWriter(AgentContextInterface* agentContextInterface, int atkValueCount, AtkValue* atkValues) - { - PluginLog.Warning($"{(IntPtr)atkValues:X}"); - - m_AgentContextInterface = agentContextInterface; - m_AtkValueCount = atkValueCount; - m_AtkValues = atkValues; - } - - public GameContextMenuItem[] Read() - { - List gameContextMenuItems = new List(); - for (var contextMenuItemIndex = 0; contextMenuItemIndex < ContextMenuItemCount; contextMenuItemIndex++) - { - var contextMenuItemAtkValueBaseIndex = FirstContextMenuItemIndex + (contextMenuItemIndex * SequentialAtkValuesPerContextMenuItem); - - // Get the name - var nameAtkValue = &m_AtkValues[contextMenuItemAtkValueBaseIndex + NameIndexOffset]; - if (nameAtkValue->Type == 0) - { - continue; - } - var name = GameInterfaceHelper.ReadSeString((IntPtr)nameAtkValue->String); - - // Get the enabled state. Note that SE stores this as IsDisabled, NOT IsEnabled (those heathens) - var isEnabled = true; - bool isDisabledDefined = FirstContextMenuItemIndex + ContextMenuItemCount < AtkValueCount; - if (isDisabledDefined) - { - var isDisabledAtkValue = &m_AtkValues[contextMenuItemAtkValueBaseIndex + IsDisabledIndexOffset]; - isEnabled = isDisabledAtkValue->Int == 0; - } - - // Get the action - byte action = 0; - if (IsInventoryContext) - { - var actions = &((AgentInventoryContext*)m_AgentContextInterface)->Actions; - action = *(actions + contextMenuItemAtkValueBaseIndex); - } - else if (StructLayout != null && StructLayout.Value == SubContextMenuStructLayout.Alternate) - { - var redButtonActions = &((AgentContext*)m_AgentContextInterface)->Items->RedButtonActions; - action = (byte)*(redButtonActions + contextMenuItemIndex); - } - else - { - var actions = &((AgentContext*)m_AgentContextInterface)->Items->Actions; - action = *(actions + contextMenuItemAtkValueBaseIndex); - } - - // Get the has previous indicator flag - var hasPreviousIndicatorFlagsAtkValue = &m_AtkValues[HasPreviousIndicatorFlagsIndex]; - var hasPreviousIndicator = HasFlag(hasPreviousIndicatorFlagsAtkValue->UInt, contextMenuItemIndex); - - // Get the has next indicator flag - var hasNextIndicatorlagsAtkValue = &m_AtkValues[HasNextIndicatorFlagsIndex]; - var hasNextIndicator = HasFlag(hasNextIndicatorlagsAtkValue->UInt, contextMenuItemIndex); - - ContextMenuItemIndicator indicator = ContextMenuItemIndicator.None; - if (hasPreviousIndicator) - { - indicator = ContextMenuItemIndicator.Previous; - } - else if (hasNextIndicator) - { - indicator = ContextMenuItemIndicator.Next; - } - - var gameContextMenuItem = new GameContextMenuItem(name, action) - { - IsEnabled = isEnabled, - Indicator = indicator - }; - - gameContextMenuItems.Add(gameContextMenuItem); - } - - return gameContextMenuItems.ToArray(); - } - - public unsafe void Write(IEnumerable contextMenuItems, AtkValueChangeTypeDelegate_Unmanaged atkValueChangeType, AtkValueSetStringDelegate_Unmanaged atkValueSetString, bool allowReallocate = true) - { - if (allowReallocate) - { - var newAtkValuesCount = FirstContextMenuItemIndex + (contextMenuItems.Count() * TotalDesiredAtkValuesPerContextMenuItem); - - // Allocate the new array. We have to do a little dance with the first 8 bytes which represents the array count - const int arrayCountSize = 8; - var newAtkValuesArraySize = arrayCountSize + Marshal.SizeOf() * newAtkValuesCount; - var newAtkValuesArray = GameInterfaceHelper.GameUIAllocate((ulong)newAtkValuesArraySize); - if (newAtkValuesArray == IntPtr.Zero) - { - return; - } - - var newAtkValues = (AtkValue*)(newAtkValuesArray + arrayCountSize); - - // Zero the memory, then copy the atk values up to the first context menu item atk value - Marshal.Copy(new byte[newAtkValuesArraySize], 0, newAtkValuesArray, newAtkValuesArraySize); - Buffer.MemoryCopy(m_AtkValues, newAtkValues, newAtkValuesArraySize - arrayCountSize, (long)sizeof(AtkValue) * FirstContextMenuItemIndex); - - // Free the old array - IntPtr oldArray = (IntPtr)m_AtkValues - arrayCountSize; - ulong oldArrayCount = *(ulong*)oldArray; - ulong oldArraySize = arrayCountSize + ((ulong)sizeof(AtkValue) * oldArrayCount); - GameInterfaceHelper.GameFree(ref oldArray, oldArraySize); - - // Set the array count - *(ulong*)newAtkValuesArray = (ulong)newAtkValuesCount; - - m_AtkValueCount = newAtkValuesCount; - m_AtkValues = newAtkValues; - } - - // Set the context menu item count - const int contextMenuItemCountAtkValueIndex = 0; - var contextMenuItemCountAtkValue = &m_AtkValues[contextMenuItemCountAtkValueIndex]; - contextMenuItemCountAtkValue->UInt = (uint)contextMenuItems.Count(); - - // Clear the previous arrow flags - var hasPreviousIndicatorAtkValue = &m_AtkValues[HasPreviousIndicatorFlagsIndex]; - hasPreviousIndicatorAtkValue->UInt = 0; - - // Clear the next arrow flags - var hasNextIndiactorFlagsAtkValue = &m_AtkValues[HasNextIndicatorFlagsIndex]; - hasNextIndiactorFlagsAtkValue->UInt = 0; - - for (int contextMenuItemIndex = 0; contextMenuItemIndex < contextMenuItems.Count(); ++contextMenuItemIndex) - { - var contextMenuItem = contextMenuItems.ElementAt(contextMenuItemIndex); - - var contextMenuItemAtkValueBaseIndex = FirstContextMenuItemIndex + (contextMenuItemIndex * SequentialAtkValuesPerContextMenuItem); - - // Set the name - var nameAtkValue = &m_AtkValues[contextMenuItemAtkValueBaseIndex + NameIndexOffset]; - atkValueChangeType(nameAtkValue, FFXIVClientStructs.FFXIV.Component.GUI.ValueType.String); - fixed (byte* nameBytesPtr = contextMenuItem.Name.Encode().NullTerminate()) - { - atkValueSetString(nameAtkValue, nameBytesPtr); - } - - // Set the enabled state. Note that SE stores this as IsDisabled, NOT IsEnabled (those heathens) - var disabledAtkValue = &m_AtkValues[contextMenuItemAtkValueBaseIndex + IsDisabledIndexOffset]; - atkValueChangeType(disabledAtkValue, FFXIVClientStructs.FFXIV.Component.GUI.ValueType.Int); - disabledAtkValue->Int = contextMenuItem.IsEnabled ? 0 : 1; - - // Set the action - byte action = 0; - if (contextMenuItem is GameContextMenuItem gameContextMenuItem) - { - action = gameContextMenuItem.SelectedAction; - } - else if (contextMenuItem is CustomContextMenuItem customContextMenuItem) - { - action = NoopAction; - } - else if (contextMenuItem is OpenSubContextMenuItem openSubContextMenuItem) - { - action = OpenSubContextMenuAction; - } - - if (IsInventoryContext) - { - var actions = &((AgentInventoryContext*)m_AgentContextInterface)->Actions; - *(actions + FirstContextMenuItemIndex + contextMenuItemIndex) = action; - } - else if (StructLayout != null && StructLayout.Value == SubContextMenuStructLayout.Alternate && FirstUnhandledAction != null) - { - // Some weird placeholder goes here - var actions = &((AgentContext*)m_AgentContextInterface)->Items->Actions; - *(actions + FirstContextMenuItemIndex + contextMenuItemIndex) = (byte)(FirstUnhandledAction.Value + contextMenuItemIndex); - - // Make sure there's one of these function pointers for every item. - // The function needs to be the same, so we just copy the first one into every index. - var unkFunctionPointers = &((AgentContext*)m_AgentContextInterface)->Items->UnkFunctionPointers; - *(unkFunctionPointers + FirstContextMenuItemIndex + contextMenuItemIndex) = *(unkFunctionPointers + FirstContextMenuItemIndex); - - // The real action goes here - var redButtonActions = &((AgentContext*)m_AgentContextInterface)->Items->RedButtonActions; - *(redButtonActions + contextMenuItemIndex) = action; - } - else - { - var actions = &((AgentContext*)m_AgentContextInterface)->Items->Actions; - *(actions + FirstContextMenuItemIndex + contextMenuItemIndex) = action; - } - - if (contextMenuItem.Indicator == ContextMenuItemIndicator.Previous) - { - SetFlag(ref hasPreviousIndicatorAtkValue->UInt, contextMenuItemIndex, true); - } - else if (contextMenuItem.Indicator == ContextMenuItemIndicator.Next) - { - SetFlag(ref hasNextIndiactorFlagsAtkValue->UInt, contextMenuItemIndex, true); - } - } - } - - private bool HasFlag(uint mask, int itemIndex) - { - return (mask & (1 << itemIndex)) > 0; - } - - private void SetFlag(ref uint mask, int itemIndex, bool value) - { - mask &= ~((uint)1 << itemIndex); - - if (value) - { - mask |= (uint)(1 << itemIndex); - } - } - - public void Log() - { - Log(m_AtkValueCount, m_AtkValues); - } - - public static void Log(int atkValueCount, AtkValue* atkValues) - { - PluginLog.Debug($"ContextMenuReader.Log"); - - for (int atkValueIndex = 0; atkValueIndex < atkValueCount; ++atkValueIndex) - { - var atkValue = &atkValues[atkValueIndex]; - - object? value = null; - if (atkValue->Type == FFXIVClientStructs.FFXIV.Component.GUI.ValueType.Int) - { - value = atkValue->Int; - } - else if (atkValue->Type == FFXIVClientStructs.FFXIV.Component.GUI.ValueType.Bool) - { - value = atkValue->Byte; - } - else if (atkValue->Type == FFXIVClientStructs.FFXIV.Component.GUI.ValueType.UInt) - { - value = atkValue->UInt; - } - else if (atkValue->Type == FFXIVClientStructs.FFXIV.Component.GUI.ValueType.Float) - { - value = atkValue->Float; - } - else if (atkValue->Type == FFXIVClientStructs.FFXIV.Component.GUI.ValueType.String - || (int)atkValue->Type == 38 - || (int)atkValue->Type == 8) - { - if (GameInterfaceHelper.TryReadSeString((IntPtr)atkValue->String, out var str)) - { - value = str; - } - } - else - { - value = $"{(IntPtr)atkValue->String:X}"; - } - - PluginLog.Debug($"atkValues[{atkValueIndex}]={(IntPtr)atkValue:X} {atkValue->Type}={value}"); - } - } - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItem.cs b/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItem.cs deleted file mode 100644 index f7cf303..0000000 --- a/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItem.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Dalamud.Game.Text.SeStringHandling; - -namespace PlayerTags.GameInterface.ContextMenus -{ - /// - /// An item in a context menu with a user defined action. - /// - public class CustomContextMenuItem : ContextMenuItem - { - /// - /// The action that will be called when the item is selected. - /// - public CustomContextMenuItemSelectedDelegate ItemSelected { get; } - - /// - /// Initializes a new instance of the class. - /// - /// The name of the item. - /// The action that will be called when the item is selected. - internal CustomContextMenuItem(SeString name, CustomContextMenuItemSelectedDelegate itemSelected) - : base(name) - { - ItemSelected = itemSelected; - } - - public override int GetHashCode() - { - unchecked - { - int hash = base.GetHashCode(); - hash = hash * 23 + ItemSelected.GetHashCode(); - return hash; - } - } - } -} \ No newline at end of file diff --git a/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItemSelectedArgs.cs b/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItemSelectedArgs.cs deleted file mode 100644 index 75ba640..0000000 --- a/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItemSelectedArgs.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace PlayerTags.GameInterface.ContextMenus -{ - /// - /// Provides data for methods. - /// - public class CustomContextMenuItemSelectedArgs - { - /// - /// The currently opened context menu. - /// - public ContextMenuOpenedArgs ContextMenuOpenedArgs { get; init; } - - /// - /// The selected item within the currently opened context menu. - /// - public CustomContextMenuItem SelectedItem { get; init; } - - /// - /// Initializes a new instance of the class. - /// - /// The currently opened context menu. - /// The selected item within the currently opened context menu. - public CustomContextMenuItemSelectedArgs(ContextMenuOpenedArgs contextMenuOpenedArgs, CustomContextMenuItem selectedItem) - { - ContextMenuOpenedArgs = contextMenuOpenedArgs; - SelectedItem = selectedItem; - } - } -} \ No newline at end of file diff --git a/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItemSelectedDelegate.cs b/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItemSelectedDelegate.cs deleted file mode 100644 index 53fc6c3..0000000 --- a/PlayerTags/GameInterface/ContextMenus/CustomContextMenuItemSelectedDelegate.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace PlayerTags.GameInterface.ContextMenus -{ - /// - /// Represents the method that handles when a is selected. - /// - /// The data associated with the selected . - public delegate void CustomContextMenuItemSelectedDelegate(CustomContextMenuItemSelectedArgs args); -} diff --git a/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/AddonContextMenu.cs b/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/AddonContextMenu.cs deleted file mode 100644 index 96787b8..0000000 --- a/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/AddonContextMenu.cs +++ /dev/null @@ -1,14 +0,0 @@ -using FFXIVClientStructs.FFXIV.Component.GUI; -using System.Runtime.InteropServices; - -namespace FFXIVClientStructs.FFXIV.Client.UI -{ - [StructLayout(LayoutKind.Explicit)] - public struct AddonContextMenu - { - [FieldOffset(0x0)] public unsafe AddonInterface AddonInterface; - [FieldOffset(0x160)] public unsafe AtkValue* AtkValues; - [FieldOffset(0x1CA)] public ushort AtkValuesCount; - [FieldOffset(0x690)] public bool IsInitialMenu; - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/AddonInterface.cs b/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/AddonInterface.cs deleted file mode 100644 index 44e5e1e..0000000 --- a/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/AddonInterface.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Runtime.InteropServices; - -namespace FFXIVClientStructs.FFXIV.Client.UI -{ - [StructLayout(LayoutKind.Explicit)] - public unsafe struct AddonInterface - { - [FieldOffset(0x8)] public byte Name; - [FieldOffset(0x1D2)] public ushort ParentAddonId; - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentContext.cs b/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentContext.cs deleted file mode 100644 index a34c8ca..0000000 --- a/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentContext.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FFXIVClientStructs.FFXIV.Client.System.String; -using FFXIVClientStructs.FFXIV.Component.GUI; -using System.Runtime.InteropServices; - -namespace FFXIVClientStructs.FFXIV.Client.UI.Agent -{ - [StructLayout(LayoutKind.Explicit)] - public unsafe struct AgentContext - { - public static AgentContext* Instance() => (AgentContext*)System.Framework.Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.Context); - - [FieldOffset(0x0)] public AgentInterface AgentInterface; - [FieldOffset(0x0)] public AgentContextInterface AgentContextInterface; - [FieldOffset(0xD18)] public unsafe AgentContextMenuItems* Items; - [FieldOffset(0xE08)] public Utf8String GameObjectName; - [FieldOffset(0xEE0)] public ulong GameObjectContentId; - [FieldOffset(0xEF0)] public uint GameObjectId; - [FieldOffset(0xF00)] public ushort GameObjectWorldId; - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentContextInterface.cs b/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentContextInterface.cs deleted file mode 100644 index 29895a6..0000000 --- a/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentContextInterface.cs +++ /dev/null @@ -1,15 +0,0 @@ -using FFXIVClientStructs.FFXIV.Component.GUI; -using System.Runtime.InteropServices; - -namespace FFXIVClientStructs.FFXIV.Client.UI.Agent -{ - [StructLayout(LayoutKind.Explicit)] - public unsafe struct AgentContextInterface - { - [FieldOffset(0x0)] public AgentInterface AgentInterface; - [FieldOffset(0x670)] public unsafe byte SelectedIndex; - [FieldOffset(0x690)] public byte* Unk1; - [FieldOffset(0xD08)] public byte* SubContextMenuTitle; - [FieldOffset(0x1740)] public bool IsSubContextMenu; - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentContextMenuItems.cs b/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentContextMenuItems.cs deleted file mode 100644 index 6b2e10b..0000000 --- a/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentContextMenuItems.cs +++ /dev/null @@ -1,15 +0,0 @@ -using FFXIVClientStructs.FFXIV.Component.GUI; -using System.Runtime.InteropServices; - -namespace FFXIVClientStructs.FFXIV.Client.UI.Agent -{ - [StructLayout(LayoutKind.Explicit)] - public struct AgentContextMenuItems - { - [FieldOffset(0x0)] public ushort AtkValueCount; - [FieldOffset(0x8)] public AtkValue AtkValues; - [FieldOffset(0x428)] public byte Actions; - [FieldOffset(0x450)] public ulong UnkFunctionPointers; - [FieldOffset(0x598)] public ulong RedButtonActions; - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentInventoryContext.cs b/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentInventoryContext.cs deleted file mode 100644 index a1134cf..0000000 --- a/PlayerTags/GameInterface/ContextMenus/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentInventoryContext.cs +++ /dev/null @@ -1,24 +0,0 @@ -using FFXIVClientStructs.FFXIV.Component.GUI; -using System.Runtime.InteropServices; - -namespace FFXIVClientStructs.FFXIV.Client.UI.Agent -{ - [StructLayout(LayoutKind.Explicit)] - public unsafe struct AgentInventoryContext - { - public static AgentInventoryContext* Instance() => (AgentInventoryContext*)System.Framework.Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.InventoryContext); - - [FieldOffset(0x0)] public AgentInterface AgentInterface; - [FieldOffset(0x0)] public AgentContextInterface AgentContextInterface; - [FieldOffset(0x2C)] public uint FirstContextMenuItemAtkValueIndex; - [FieldOffset(0x30)] public uint ContextMenuItemCount; - [FieldOffset(0x38)] public AtkValue AtkValues; - [FieldOffset(0x558)] public unsafe byte Actions; - [FieldOffset(0x5A8)] public uint UnkFlags; - [FieldOffset(0x5B0)] public uint PositionX; - [FieldOffset(0x5B4)] public uint PositionY; - [FieldOffset(0x5F8)] public uint InventoryItemId; - [FieldOffset(0x5FC)] public uint InventoryItemCount; - [FieldOffset(0x604)] public bool InventoryItemIsHighQuality; - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/GameContextMenuItem.cs b/PlayerTags/GameInterface/ContextMenus/GameContextMenuItem.cs deleted file mode 100644 index 49805d3..0000000 --- a/PlayerTags/GameInterface/ContextMenus/GameContextMenuItem.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Dalamud.Game.Text.SeStringHandling; - -namespace PlayerTags.GameInterface.ContextMenus -{ - /// - /// An item in a context menu that with a specific game action. - /// - public class GameContextMenuItem : ContextMenuItem - { - /// - /// The game action that will be handled when the item is selected. - /// - public byte SelectedAction { get; } - - /// - /// Initializes a new instance of the class. - /// - /// The name of the item. - /// The game action that will be handled when the item is selected. - public GameContextMenuItem(SeString name, byte selectedAction) - : base(name) - { - SelectedAction = selectedAction; - } - - public override int GetHashCode() - { - unchecked - { - int hash = base.GetHashCode(); - hash = hash * 23 + SelectedAction; - return hash; - } - } - } -} \ No newline at end of file diff --git a/PlayerTags/GameInterface/ContextMenus/GameObjectContext.cs b/PlayerTags/GameInterface/ContextMenus/GameObjectContext.cs deleted file mode 100644 index c7e7318..0000000 --- a/PlayerTags/GameInterface/ContextMenus/GameObjectContext.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Dalamud.Game.Text.SeStringHandling; - -namespace PlayerTags.GameInterface.ContextMenus -{ - /// - /// Provides game object context to a context menu. - /// - public class GameObjectContext - { - /// - /// The id of the game object. - /// - public uint? Id { get; } - - /// - /// The content id of the game object. - /// - public ulong? ContentId { get; } - - /// - /// The name of the game object. - /// - public string? Name { get; } - - /// - /// The world id of the game object. - /// - public ushort? WorldId { get; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the game object. - /// The lower content id of the game object. - /// The name of the game object. - /// The world id of the game object. - public GameObjectContext(uint? id, ulong? contentId, string? name, ushort? worldId) - { - Id = id; - ContentId = contentId; - Name = name; - WorldId = worldId; - } - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/InventoryItemContext.cs b/PlayerTags/GameInterface/ContextMenus/InventoryItemContext.cs deleted file mode 100644 index f9d6ce2..0000000 --- a/PlayerTags/GameInterface/ContextMenus/InventoryItemContext.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace PlayerTags.GameInterface.ContextMenus -{ - /// - /// Provides inventory item context to a context menu. - /// - public class InventoryItemContext - { - /// - /// The id of the item. - /// - public uint Id { get; } - - /// - /// The count of the item in the stack. - /// - public uint Count { get; } - - /// - /// Whether the item is high quality. - /// - public bool IsHighQuality { get; } - - /// - /// Initializes a new instance of the class. - /// - /// The id of the item. - /// The count of the item in the stack. - /// Whether the item is high quality. - public InventoryItemContext(uint id, uint count, bool isHighQuality) - { - Id = id; - Count = count; - IsHighQuality = isHighQuality; - } - } -} diff --git a/PlayerTags/GameInterface/ContextMenus/OpenSubContextMenuItem.cs b/PlayerTags/GameInterface/ContextMenus/OpenSubContextMenuItem.cs deleted file mode 100644 index a3549e6..0000000 --- a/PlayerTags/GameInterface/ContextMenus/OpenSubContextMenuItem.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Dalamud.Game.Text.SeStringHandling; - -namespace PlayerTags.GameInterface.ContextMenus -{ - /// - /// An item in a context menu that can open a sub context menu. - /// - public class OpenSubContextMenuItem : ContextMenuItem - { - /// - /// The action that will be called when the item is selected. - /// - public ContextMenuOpenedDelegate Opened { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The name of the item. - /// The action that will be called when the item is selected. - internal OpenSubContextMenuItem(SeString name, ContextMenuOpenedDelegate opened) - : base(name) - { - Opened = opened; - Indicator = ContextMenuItemIndicator.Next; - } - - public override int GetHashCode() - { - unchecked - { - int hash = base.GetHashCode(); - hash = hash * 23 + Opened.GetHashCode(); - return hash; - } - } - } -} \ No newline at end of file diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index e5dc305..dd3985a 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -5,7 +5,7 @@ - net5.0-windows + net5.0-windows7 x64 enable latest diff --git a/PlayerTags/PluginServices.cs b/PlayerTags/PluginServices.cs index 7728766..36902ee 100644 --- a/PlayerTags/PluginServices.cs +++ b/PlayerTags/PluginServices.cs @@ -5,6 +5,7 @@ using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Party; using Dalamud.Game.Command; using Dalamud.Game.Gui; +using Dalamud.Game.Gui.ContextMenus; using Dalamud.IoC; using Dalamud.Plugin; From 7e28f028d10067a7f6e7a15bdbab9371bc5951d0 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 16 Jun 2022 14:54:37 +0200 Subject: [PATCH 2/3] use Dalamug.ContextMenu --- .../Configuration/PluginConfigurationUI.cs | 3 +- PlayerTags/Data/PluginData.cs | 13 ++-- .../Features/CustomTagsContextMenuFeature.cs | 66 +++++++++++-------- PlayerTags/PlayerTags.csproj | 1 + 4 files changed, 47 insertions(+), 36 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index 48fdab5..8c2bc9c 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -27,6 +27,7 @@ namespace PlayerTags.Configuration private PluginData m_PluginData; private InheritableValue? m_ColorPickerPopupDataContext; + public static int asdfasdfasdf = 0; public PluginConfigurationUI(PluginConfiguration config, PluginData pluginData) { @@ -43,7 +44,7 @@ namespace PlayerTags.Configuration ImGui.SetNextWindowSize(new Vector2(400, 500), ImGuiCond.FirstUseEver); - if (ImGui.Begin(Strings.Loc_Static_PluginName, ref m_PluginConfiguration.IsVisible)) + if (ImGui.Begin(Strings.Loc_Static_PluginName + asdfasdfasdf.ToString(), ref m_PluginConfiguration.IsVisible)) { ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1, 0.8f, 0.5f, 1)); ImGui.TextWrapped(Strings.Loc_Static_WarningMessage); diff --git a/PlayerTags/Data/PluginData.cs b/PlayerTags/Data/PluginData.cs index 62cd204..3ceeeec 100644 --- a/PlayerTags/Data/PluginData.cs +++ b/PlayerTags/Data/PluginData.cs @@ -1,4 +1,5 @@ -using Dalamud.Game.ClientState.Objects.SubKinds; +using Dalamud.ContextMenu; +using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Party; using Dalamud.Game.Gui.ContextMenus; using Dalamud.Game.Text.SeStringHandling.Payloads; @@ -278,16 +279,16 @@ namespace PlayerTags.Data }; } - public Identity? GetIdentity(ContextMenuOpenedArgs contextMenuOpenedArgs) + public Identity? GetIdentity(GameObjectContextMenuOpenArgs contextMenuOpenedArgs) { - if (contextMenuOpenedArgs.GameObjectContext == null - || contextMenuOpenedArgs.GameObjectContext.Name == null - || contextMenuOpenedArgs.GameObjectContext.WorldId == null) + if (!string.IsNullOrEmpty(contextMenuOpenedArgs.Text?.TextValue) + || contextMenuOpenedArgs.ObjectWorld != 0 + || contextMenuOpenedArgs.ObjectWorld != 65535) { return null; } - return GetIdentity(contextMenuOpenedArgs.GameObjectContext.Name, contextMenuOpenedArgs.GameObjectContext.WorldId); + return GetIdentity(contextMenuOpenedArgs.Text?.TextValue ?? string.Empty, contextMenuOpenedArgs.ObjectWorld); } public Identity GetIdentity(PlayerCharacter playerCharacter) diff --git a/PlayerTags/Features/CustomTagsContextMenuFeature.cs b/PlayerTags/Features/CustomTagsContextMenuFeature.cs index 0f5db26..b0bd28d 100644 --- a/PlayerTags/Features/CustomTagsContextMenuFeature.cs +++ b/PlayerTags/Features/CustomTagsContextMenuFeature.cs @@ -1,4 +1,4 @@ -using Dalamud.Game.Gui.ContextMenus; +using Dalamud.ContextMenu; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Logging; using PlayerTags.Configuration; @@ -33,72 +33,80 @@ namespace PlayerTags.Features private PluginConfiguration m_PluginConfiguration; private PluginData m_PluginData; - private ContextMenu? m_ContextMenu; + private DalamudContextMenuBase? m_ContextMenu; public CustomTagsContextMenuFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) { m_PluginConfiguration = pluginConfiguration; m_PluginData = pluginData; - m_ContextMenu = new ContextMenu(); - - if (m_PluginConfiguration.IsCustomTagsContextMenuEnabled) - { - m_ContextMenu.ContextMenuOpened += ContextMenuHooks_ContextMenuOpened; - PluginServices.GameGui.Enable(); - } + m_ContextMenu = new DalamudContextMenuBase(); + m_ContextMenu.Functions.ContextMenu.OnOpenGameObjectContextMenu += ContextMenuHooks_ContextMenuOpened; + PluginConfigurationUI.asdfasdfasdf = 1; } public void Dispose() { if (m_ContextMenu != null) { - m_ContextMenu.ContextMenuOpened -= ContextMenuHooks_ContextMenuOpened; + m_ContextMenu.Functions.ContextMenu.OnOpenGameObjectContextMenu -= ContextMenuHooks_ContextMenuOpened; ((IDisposable)m_ContextMenu).Dispose(); m_ContextMenu = null; } } - private void ContextMenuHooks_ContextMenuOpened(ContextMenuOpenedArgs contextMenuOpenedArgs) + private void ContextMenuHooks_ContextMenuOpened(GameObjectContextMenuOpenArgs contextMenuOpenedArgs) { + PluginConfigurationUI.asdfasdfasdf = 2; if (!m_PluginConfiguration.IsCustomTagsContextMenuEnabled || !SupportedAddonNames.Contains(contextMenuOpenedArgs.ParentAddonName)) { return; } + PluginConfigurationUI.asdfasdfasdf = 3; Identity? identity = m_PluginData.GetIdentity(contextMenuOpenedArgs); + PluginConfigurationUI.asdfasdfasdf = 4; if (identity != null) { + PluginConfigurationUI.asdfasdfasdf = 5; var notAddedTags = m_PluginData.CustomTags.Where(customTag => !identity.CustomTagIds.Contains(customTag.CustomId.Value)); if (notAddedTags.Any()) { - contextMenuOpenedArgs.AddCustomSubMenu(Strings.Loc_Static_ContextMenu_AddTag, subContextMenuOpenedArgs => + contextMenuOpenedArgs.AddCustomItem( + new GameObjectContextMenuItem(Strings.Loc_Static_ContextMenu_AddTag, subContextMenuOpenedArgs => { - foreach (var notAddedTag in notAddedTags) - { - subContextMenuOpenedArgs.AddCustomItem(notAddedTag.Text.Value, args => - { - m_PluginData.AddCustomTagToIdentity(notAddedTag, identity); - m_PluginConfiguration.Save(m_PluginData); - }); - } + //foreach (var notAddedTag in notAddedTags) + //{ + // subContextMenuOpenedArgs.AddCustomItem(notAddedTag.Text.Value, args => + // { + // m_PluginData.AddCustomTagToIdentity(notAddedTag, identity); + // m_PluginConfiguration.Save(m_PluginData); + // }); + //} + }) + { + IsSubMenu = true }); } var addedTags = m_PluginData.CustomTags.Where(customTag => identity.CustomTagIds.Contains(customTag.CustomId.Value)); if (addedTags.Any()) { - contextMenuOpenedArgs.AddCustomSubMenu(Strings.Loc_Static_ContextMenu_RemoveTag, subContextMenuOpenedArgs => + contextMenuOpenedArgs.AddCustomItem( + new GameObjectContextMenuItem(Strings.Loc_Static_ContextMenu_RemoveTag, subContextMenuOpenedArgs => { - foreach (var addedTag in addedTags) - { - subContextMenuOpenedArgs.AddCustomItem(addedTag.Text.Value, args => - { - m_PluginData.RemoveCustomTagFromIdentity(addedTag, identity); - m_PluginConfiguration.Save(m_PluginData); - }); - } + //foreach (var addedTag in addedTags) + //{ + // subContextMenuOpenedArgs.AddCustomItem(addedTag.Text.Value, args => + // { + // m_PluginData.RemoveCustomTagFromIdentity(addedTag, identity); + // m_PluginConfiguration.Save(m_PluginData); + // }); + //} + }) + { + IsSubMenu = true }); } } diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index dd3985a..0854610 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -20,6 +20,7 @@ + $(DalamudLibPath)FFXIVClientStructs.dll From 08ddc9a440c764a829c23eeb2d439a1591d4043c Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 17 Jun 2022 12:43:08 +0200 Subject: [PATCH 3/3] plish up & don't use sub items in context menu --- .../Configuration/PluginConfigurationUI.cs | 3 +- PlayerTags/Data/PluginData.cs | 7 +- .../Features/CustomTagsContextMenuFeature.cs | 64 ++-- PlayerTags/Resources/Strings.Designer.cs | 336 +++++++++--------- PlayerTags/Resources/Strings.resx | 26 +- 5 files changed, 200 insertions(+), 236 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index 8c2bc9c..48fdab5 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -27,7 +27,6 @@ namespace PlayerTags.Configuration private PluginData m_PluginData; private InheritableValue? m_ColorPickerPopupDataContext; - public static int asdfasdfasdf = 0; public PluginConfigurationUI(PluginConfiguration config, PluginData pluginData) { @@ -44,7 +43,7 @@ namespace PlayerTags.Configuration ImGui.SetNextWindowSize(new Vector2(400, 500), ImGuiCond.FirstUseEver); - if (ImGui.Begin(Strings.Loc_Static_PluginName + asdfasdfasdf.ToString(), ref m_PluginConfiguration.IsVisible)) + if (ImGui.Begin(Strings.Loc_Static_PluginName, ref m_PluginConfiguration.IsVisible)) { ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1, 0.8f, 0.5f, 1)); ImGui.TextWrapped(Strings.Loc_Static_WarningMessage); diff --git a/PlayerTags/Data/PluginData.cs b/PlayerTags/Data/PluginData.cs index 3ceeeec..de76ea9 100644 --- a/PlayerTags/Data/PluginData.cs +++ b/PlayerTags/Data/PluginData.cs @@ -281,13 +281,12 @@ namespace PlayerTags.Data public Identity? GetIdentity(GameObjectContextMenuOpenArgs contextMenuOpenedArgs) { - if (!string.IsNullOrEmpty(contextMenuOpenedArgs.Text?.TextValue) - || contextMenuOpenedArgs.ObjectWorld != 0 - || contextMenuOpenedArgs.ObjectWorld != 65535) + if (string.IsNullOrEmpty(contextMenuOpenedArgs.Text?.TextValue) + || contextMenuOpenedArgs.ObjectWorld == 0 + || contextMenuOpenedArgs.ObjectWorld == 65535) { return null; } - return GetIdentity(contextMenuOpenedArgs.Text?.TextValue ?? string.Empty, contextMenuOpenedArgs.ObjectWorld); } diff --git a/PlayerTags/Features/CustomTagsContextMenuFeature.cs b/PlayerTags/Features/CustomTagsContextMenuFeature.cs index b0bd28d..afea808 100644 --- a/PlayerTags/Features/CustomTagsContextMenuFeature.cs +++ b/PlayerTags/Features/CustomTagsContextMenuFeature.cs @@ -42,7 +42,6 @@ namespace PlayerTags.Features m_ContextMenu = new DalamudContextMenuBase(); m_ContextMenu.Functions.ContextMenu.OnOpenGameObjectContextMenu += ContextMenuHooks_ContextMenuOpened; - PluginConfigurationUI.asdfasdfasdf = 1; } public void Dispose() @@ -57,57 +56,44 @@ namespace PlayerTags.Features private void ContextMenuHooks_ContextMenuOpened(GameObjectContextMenuOpenArgs contextMenuOpenedArgs) { - PluginConfigurationUI.asdfasdfasdf = 2; if (!m_PluginConfiguration.IsCustomTagsContextMenuEnabled || !SupportedAddonNames.Contains(contextMenuOpenedArgs.ParentAddonName)) { return; } - PluginConfigurationUI.asdfasdfasdf = 3; Identity? identity = m_PluginData.GetIdentity(contextMenuOpenedArgs); - PluginConfigurationUI.asdfasdfasdf = 4; if (identity != null) { - PluginConfigurationUI.asdfasdfasdf = 5; - var notAddedTags = m_PluginData.CustomTags.Where(customTag => !identity.CustomTagIds.Contains(customTag.CustomId.Value)); - if (notAddedTags.Any()) + var allTags = new Dictionary(); + foreach (var customTag in m_PluginData.CustomTags) { - contextMenuOpenedArgs.AddCustomItem( - new GameObjectContextMenuItem(Strings.Loc_Static_ContextMenu_AddTag, subContextMenuOpenedArgs => - { - //foreach (var notAddedTag in notAddedTags) - //{ - // subContextMenuOpenedArgs.AddCustomItem(notAddedTag.Text.Value, args => - // { - // m_PluginData.AddCustomTagToIdentity(notAddedTag, identity); - // m_PluginConfiguration.Save(m_PluginData); - // }); - //} - }) - { - IsSubMenu = true - }); + var isAdded = identity.CustomTagIds.Contains(customTag.CustomId.Value); + allTags.Add(customTag, isAdded); } - - var addedTags = m_PluginData.CustomTags.Where(customTag => identity.CustomTagIds.Contains(customTag.CustomId.Value)); - if (addedTags.Any()) + + var sortedTags = allTags.OrderBy(n => n.Value); + foreach (var tag in sortedTags) { + string menuItemText; + if (tag.Value) + menuItemText = Strings.Loc_Static_ContextMenu_RemoveTag; + else + menuItemText = Strings.Loc_Static_ContextMenu_AddTag; + menuItemText = string.Format(menuItemText, tag.Key.Text.Value); + contextMenuOpenedArgs.AddCustomItem( - new GameObjectContextMenuItem(Strings.Loc_Static_ContextMenu_RemoveTag, subContextMenuOpenedArgs => - { - //foreach (var addedTag in addedTags) - //{ - // subContextMenuOpenedArgs.AddCustomItem(addedTag.Text.Value, args => - // { - // m_PluginData.RemoveCustomTagFromIdentity(addedTag, identity); - // m_PluginConfiguration.Save(m_PluginData); - // }); - //} - }) - { - IsSubMenu = true - }); + new GameObjectContextMenuItem(menuItemText, openedEventArgs => + { + if (tag.Value) + m_PluginData.RemoveCustomTagFromIdentity(tag.Key, identity); + else + m_PluginData.AddCustomTagToIdentity(tag.Key, identity); + m_PluginConfiguration.Save(m_PluginData); + }) + { + IsSubMenu = false + }); } } } diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index 54be4e6..24f48a9 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. // //------------------------------------------------------------------------------ @@ -13,12 +13,12 @@ namespace PlayerTags.Resources { /// - /// A strongly-typed resource class, for looking up localized strings, etc. + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -33,7 +33,7 @@ namespace PlayerTags.Resources { } /// - /// Returns the cached ResourceManager instance used by this class. + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ namespace PlayerTags.Resources { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] public static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Activity properties. + /// Sucht eine lokalisierte Zeichenfolge, die Activity properties ähnelt. /// public static string Loc_ActivityCategory { get { @@ -70,7 +70,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Custom. + /// Sucht eine lokalisierte Zeichenfolge, die Custom ähnelt. /// public static string Loc_AllCustomTags { get { @@ -79,7 +79,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Roles. + /// Sucht eine lokalisierte Zeichenfolge, die Roles ähnelt. /// public static string Loc_AllRoleTags { get { @@ -88,7 +88,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to All. + /// Sucht eine lokalisierte Zeichenfolge, die All ähnelt. /// public static string Loc_AllTags { get { @@ -97,7 +97,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Custom id. + /// Sucht eine lokalisierte Zeichenfolge, die Custom id ähnelt. /// public static string Loc_CustomId { get { @@ -106,7 +106,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Custom. + /// Sucht eine lokalisierte Zeichenfolge, die Custom ähnelt. /// public static string Loc_CustomTags { get { @@ -115,7 +115,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Melee. + /// Sucht eine lokalisierte Zeichenfolge, die Melee ähnelt. /// public static string Loc_DpsRole_Melee { get { @@ -124,7 +124,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Ranged. + /// Sucht eine lokalisierte Zeichenfolge, die Ranged ähnelt. /// public static string Loc_DpsRole_Ranged { get { @@ -133,7 +133,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Add to players. + /// Sucht eine lokalisierte Zeichenfolge, die Add to players ähnelt. /// public static string Loc_GameObjectNamesToApplyTo { get { @@ -142,7 +142,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to A list of players to add tags to, separated by commas or semi-colons. E.g. "Cloud Strife, Tifa Lockhart".. + /// Sucht eine lokalisierte Zeichenfolge, die A list of players to add tags to, separated by commas or semi-colons. E.g. "Cloud Strife, Tifa Lockhart". ähnelt. /// public static string Loc_GameObjectNamesToApplyTo_Description { get { @@ -151,7 +151,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to General properties. + /// Sucht eine lokalisierte Zeichenfolge, die General properties ähnelt. /// public static string Loc_GeneralCategory { get { @@ -160,7 +160,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Icon. + /// Sucht eine lokalisierte Zeichenfolge, die Icon ähnelt. /// public static string Loc_Icon { get { @@ -169,7 +169,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The icon that will be displayed.. + /// Sucht eine lokalisierte Zeichenfolge, die The icon that will be displayed. ähnelt. /// public static string Loc_Icon_Description { get { @@ -178,7 +178,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Icon properties. + /// Sucht eine lokalisierte Zeichenfolge, die Icon properties ähnelt. /// public static string Loc_IconCategory { get { @@ -187,7 +187,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Apply tags to all chat messages. + /// Sucht eine lokalisierte Zeichenfolge, die Apply tags to all chat messages ähnelt. /// public static string Loc_IsApplyTagsToAllChatMessagesEnabled { get { @@ -196,7 +196,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Applies tags to all chat messages, including non-social messages.. + /// Sucht eine lokalisierte Zeichenfolge, die Applies tags to all chat messages, including non-social messages. ähnelt. /// public static string Loc_IsApplyTagsToAllChatMessagesEnabled_Description { get { @@ -205,7 +205,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Context menu integration. + /// Sucht eine lokalisierte Zeichenfolge, die Context menu integration ähnelt. /// public static string Loc_IsCustomTagsContextMenuEnabled { get { @@ -214,7 +214,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Options will be available in context menus for adding and removing custom tags from players.. + /// Sucht eine lokalisierte Zeichenfolge, die Options will be available in context menus for adding and removing custom tags from players. ähnelt. /// public static string Loc_IsCustomTagsContextMenuEnabled_Description { get { @@ -223,7 +223,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Enabled. + /// Sucht eine lokalisierte Zeichenfolge, die Enabled ähnelt. /// public static string Loc_IsEnabled { get { @@ -232,7 +232,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Enable the value of this override.. + /// Sucht eine lokalisierte Zeichenfolge, die Enable the value of this override. ähnelt. /// public static string Loc_IsEnabled_Description { get { @@ -241,7 +241,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Expanded. + /// Sucht eine lokalisierte Zeichenfolge, die Expanded ähnelt. /// public static string Loc_IsExpanded { get { @@ -250,7 +250,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show in chat. + /// Sucht eine lokalisierte Zeichenfolge, die Show in chat ähnelt. /// public static string Loc_IsIconVisibleInChat { get { @@ -259,7 +259,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the icon will be shown in chat.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the icon will be shown in chat. ähnelt. /// public static string Loc_IsIconVisibleInChat_Description { get { @@ -268,7 +268,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show in nameplates. + /// Sucht eine lokalisierte Zeichenfolge, die Show in nameplates ähnelt. /// public static string Loc_IsIconVisibleInNameplates { get { @@ -277,7 +277,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the icon will be shown in nameplates.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the icon will be shown in nameplates. ähnelt. /// public static string Loc_IsIconVisibleInNameplates_Description { get { @@ -286,7 +286,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Apply tags to self in chat. + /// Sucht eine lokalisierte Zeichenfolge, die Apply tags to self in chat ähnelt. /// public static string Loc_IsLinkSelfInChatEnabled { get { @@ -295,7 +295,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Attempts to link your chat name to your character, allowing tags to be applied to self in chat.. + /// Sucht eine lokalisierte Zeichenfolge, die Attempts to link your chat name to your character, allowing tags to be applied to self in chat. ähnelt. /// public static string Loc_IsLinkSelfInChatEnabled_Description { get { @@ -304,7 +304,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Randomly generate player names. + /// Sucht eine lokalisierte Zeichenfolge, die Randomly generate player names ähnelt. /// public static string Loc_IsPlayerNameRandomlyGenerated { get { @@ -313,7 +313,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Replace every player's name with a randomly generated one.. + /// Sucht eine lokalisierte Zeichenfolge, die Replace every player's name with a randomly generated one. ähnelt. /// public static string Loc_IsPlayerNameRandomlyGenerated_Description { get { @@ -322,7 +322,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show alliance members. + /// Sucht eine lokalisierte Zeichenfolge, die Show alliance members ähnelt. /// public static string Loc_IsPlayersTabAllianceVisible { get { @@ -331,7 +331,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show alliance members in the players list.. + /// Sucht eine lokalisierte Zeichenfolge, die Show alliance members in the players list. ähnelt. /// public static string Loc_IsPlayersTabAllianceVisible_Description { get { @@ -340,7 +340,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show enemies. + /// Sucht eine lokalisierte Zeichenfolge, die Show enemies ähnelt. /// public static string Loc_IsPlayersTabEnemiesVisible { get { @@ -349,7 +349,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show enemies in the players list.. + /// Sucht eine lokalisierte Zeichenfolge, die Show enemies in the players list. ähnelt. /// public static string Loc_IsPlayersTabEnemiesVisible_Description { get { @@ -358,7 +358,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show friends. + /// Sucht eine lokalisierte Zeichenfolge, die Show friends ähnelt. /// public static string Loc_IsPlayersTabFriendsVisible { get { @@ -367,7 +367,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show friends in the players list.. + /// Sucht eine lokalisierte Zeichenfolge, die Show friends in the players list. ähnelt. /// public static string Loc_IsPlayersTabFriendsVisible_Description { get { @@ -376,7 +376,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Order by proximity. + /// Sucht eine lokalisierte Zeichenfolge, die Order by proximity ähnelt. /// public static string Loc_IsPlayersTabOrderedByProximity { get { @@ -385,7 +385,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Players that are closer to you will be ordered towards the top.. + /// Sucht eine lokalisierte Zeichenfolge, die Players that are closer to you will be ordered towards the top. ähnelt. /// public static string Loc_IsPlayersTabOrderedByProximity_Description { get { @@ -394,7 +394,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show others. + /// Sucht eine lokalisierte Zeichenfolge, die Show others ähnelt. /// public static string Loc_IsPlayersTabOthersVisible { get { @@ -403,7 +403,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show others in the players list.. + /// Sucht eine lokalisierte Zeichenfolge, die Show others in the players list. ähnelt. /// public static string Loc_IsPlayersTabOthersVisible_Description { get { @@ -412,7 +412,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show party members. + /// Sucht eine lokalisierte Zeichenfolge, die Show party members ähnelt. /// public static string Loc_IsPlayersTabPartyVisible { get { @@ -421,7 +421,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show party members in the players list.. + /// Sucht eine lokalisierte Zeichenfolge, die Show party members in the players list. ähnelt. /// public static string Loc_IsPlayersTabPartyVisible_Description { get { @@ -430,7 +430,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show self. + /// Sucht eine lokalisierte Zeichenfolge, die Show self ähnelt. /// public static string Loc_IsPlayersTabSelfVisible { get { @@ -439,7 +439,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show yourself in the players list.. + /// Sucht eine lokalisierte Zeichenfolge, die Show yourself in the players list. ähnelt. /// public static string Loc_IsPlayersTabSelfVisible_Description { get { @@ -448,7 +448,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Selected. + /// Sucht eine lokalisierte Zeichenfolge, die Selected ähnelt. /// public static string Loc_IsSelected { get { @@ -457,7 +457,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show inherited properties. + /// Sucht eine lokalisierte Zeichenfolge, die Show inherited properties ähnelt. /// public static string Loc_IsShowInheritedPropertiesEnabled { get { @@ -466,7 +466,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Properties inherited from parent nodes will be shown in the editor.. + /// Sucht eine lokalisierte Zeichenfolge, die Properties inherited from parent nodes will be shown in the editor. ähnelt. /// public static string Loc_IsShowInheritedPropertiesEnabled_Description { get { @@ -475,7 +475,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Apply color to chat name. + /// Sucht eine lokalisierte Zeichenfolge, die Apply color to chat name ähnelt. /// public static string Loc_IsTextColorAppliedToChatName { get { @@ -484,7 +484,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the color will be applied to the name in chat.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the color will be applied to the name in chat. ähnelt. /// public static string Loc_IsTextColorAppliedToChatName_Description { get { @@ -493,7 +493,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Apply color to nameplate free company. + /// Sucht eine lokalisierte Zeichenfolge, die Apply color to nameplate free company ähnelt. /// public static string Loc_IsTextColorAppliedToNameplateFreeCompany { get { @@ -502,7 +502,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the color will be applied to the free company in nameplates.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the color will be applied to the free company in nameplates. ähnelt. /// public static string Loc_IsTextColorAppliedToNameplateFreeCompany_Description { get { @@ -511,7 +511,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Apply color to nameplate name. + /// Sucht eine lokalisierte Zeichenfolge, die Apply color to nameplate name ähnelt. /// public static string Loc_IsTextColorAppliedToNameplateName { get { @@ -520,7 +520,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the color will be applied to the name in nameplates.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the color will be applied to the name in nameplates. ähnelt. /// public static string Loc_IsTextColorAppliedToNameplateName_Description { get { @@ -529,7 +529,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Apply color to nameplate title. + /// Sucht eine lokalisierte Zeichenfolge, die Apply color to nameplate title ähnelt. /// public static string Loc_IsTextColorAppliedToNameplateTitle { get { @@ -538,7 +538,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the color will be applied to title in nameplates.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the color will be applied to title in nameplates. ähnelt. /// public static string Loc_IsTextColorAppliedToNameplateTitle_Description { get { @@ -547,7 +547,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Italic. + /// Sucht eine lokalisierte Zeichenfolge, die Italic ähnelt. /// public static string Loc_IsTextItalic { get { @@ -556,7 +556,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the text will be italic.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the text will be italic. ähnelt. /// public static string Loc_IsTextItalic_Description { get { @@ -565,7 +565,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show in chat. + /// Sucht eine lokalisierte Zeichenfolge, die Show in chat ähnelt. /// public static string Loc_IsTextVisibleInChat { get { @@ -574,7 +574,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the text will be shown in chat.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the text will be shown in chat. ähnelt. /// public static string Loc_IsTextVisibleInChat_Description { get { @@ -583,7 +583,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show in nameplates. + /// Sucht eine lokalisierte Zeichenfolge, die Show in nameplates ähnelt. /// public static string Loc_IsTextVisibleInNameplates { get { @@ -592,7 +592,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the text will be shown in nameplates.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the text will be shown in nameplates. ähnelt. /// public static string Loc_IsTextVisibleInNameplates_Description { get { @@ -601,7 +601,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show for alliance members. + /// Sucht eine lokalisierte Zeichenfolge, die Show for alliance members ähnelt. /// public static string Loc_IsVisibleForAlliancePlayers { get { @@ -610,7 +610,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the tag should be visible for alliance members who are not in the current party.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the tag should be visible for alliance members who are not in the current party. ähnelt. /// public static string Loc_IsVisibleForAlliancePlayers_Description { get { @@ -619,7 +619,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show for enemies. + /// Sucht eine lokalisierte Zeichenfolge, die Show for enemies ähnelt. /// public static string Loc_IsVisibleForEnemyPlayers { get { @@ -628,7 +628,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the tag should be visible for enemies in pvp.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the tag should be visible for enemies in pvp. ähnelt. /// public static string Loc_IsVisibleForEnemyPlayers_Description { get { @@ -637,7 +637,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show for friends. + /// Sucht eine lokalisierte Zeichenfolge, die Show for friends ähnelt. /// public static string Loc_IsVisibleForFriendPlayers { get { @@ -646,7 +646,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the tag should be visible for friends.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the tag should be visible for friends. ähnelt. /// public static string Loc_IsVisibleForFriendPlayers_Description { get { @@ -655,7 +655,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show for others. + /// Sucht eine lokalisierte Zeichenfolge, die Show for others ähnelt. /// public static string Loc_IsVisibleForOtherPlayers { get { @@ -664,7 +664,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the tag should be visible for players in other circumstances for which there is no specific option.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the tag should be visible for players in other circumstances for which there is no specific option. ähnelt. /// public static string Loc_IsVisibleForOtherPlayers_Description { get { @@ -673,7 +673,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show for party members. + /// Sucht eine lokalisierte Zeichenfolge, die Show for party members ähnelt. /// public static string Loc_IsVisibleForPartyPlayers { get { @@ -682,7 +682,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the tag should be visible for party members.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the tag should be visible for party members. ähnelt. /// public static string Loc_IsVisibleForPartyPlayers_Description { get { @@ -691,7 +691,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show for self. + /// Sucht eine lokalisierte Zeichenfolge, die Show for self ähnelt. /// public static string Loc_IsVisibleForSelf { get { @@ -700,7 +700,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the tag should be visible for the local player.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the tag should be visible for the local player. ähnelt. /// public static string Loc_IsVisibleForSelf_Description { get { @@ -709,7 +709,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show elsewhere. + /// Sucht eine lokalisierte Zeichenfolge, die Show elsewhere ähnelt. /// public static string Loc_IsVisibleInOverworld { get { @@ -718,7 +718,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the tag should be visible in other circumstances for which there is no specific option.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the tag should be visible in other circumstances for which there is no specific option. ähnelt. /// public static string Loc_IsVisibleInOverworld_Description { get { @@ -727,7 +727,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show in pve duties. + /// Sucht eine lokalisierte Zeichenfolge, die Show in pve duties ähnelt. /// public static string Loc_IsVisibleInPveDuties { get { @@ -736,7 +736,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the tag should be visible in pve duties.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the tag should be visible in pve duties. ähnelt. /// public static string Loc_IsVisibleInPveDuties_Description { get { @@ -745,7 +745,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Show in pvp duties. + /// Sucht eine lokalisierte Zeichenfolge, die Show in pvp duties ähnelt. /// public static string Loc_IsVisibleInPvpDuties { get { @@ -754,7 +754,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Whether the tag should be visible in pvp duties.. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the tag should be visible in pvp duties. ähnelt. /// public static string Loc_IsVisibleInPvpDuties_Description { get { @@ -763,7 +763,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Hand. + /// Sucht eine lokalisierte Zeichenfolge, die Hand ähnelt. /// public static string Loc_LandHandRole_Hand { get { @@ -772,7 +772,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Land. + /// Sucht eine lokalisierte Zeichenfolge, die Land ähnelt. /// public static string Loc_LandHandRole_Land { get { @@ -781,7 +781,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Free company. + /// Sucht eine lokalisierte Zeichenfolge, die Free company ähnelt. /// public static string Loc_NameplateElement_FreeCompany { get { @@ -790,7 +790,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The free company element on nameplates.. + /// Sucht eine lokalisierte Zeichenfolge, die The free company element on nameplates. ähnelt. /// public static string Loc_NameplateElement_FreeCompany_Description { get { @@ -799,7 +799,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Name. + /// Sucht eine lokalisierte Zeichenfolge, die Name ähnelt. /// public static string Loc_NameplateElement_Name { get { @@ -808,7 +808,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The name element on nameplates.. + /// Sucht eine lokalisierte Zeichenfolge, die The name element on nameplates. ähnelt. /// public static string Loc_NameplateElement_Name_Description { get { @@ -817,7 +817,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Title. + /// Sucht eine lokalisierte Zeichenfolge, die Title ähnelt. /// public static string Loc_NameplateElement_Title { get { @@ -826,7 +826,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The title element on nameplates.. + /// Sucht eine lokalisierte Zeichenfolge, die The title element on nameplates. ähnelt. /// public static string Loc_NameplateElement_Title_Description { get { @@ -835,7 +835,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Free company visibility. + /// Sucht eine lokalisierte Zeichenfolge, die Free company visibility ähnelt. /// public static string Loc_NameplateFreeCompanyVisibility { get { @@ -844,7 +844,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Default. + /// Sucht eine lokalisierte Zeichenfolge, die Default ähnelt. /// public static string Loc_NameplateFreeCompanyVisibility_Default { get { @@ -853,7 +853,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The free company on nameplates will only be visible when the character is in a free company.. + /// Sucht eine lokalisierte Zeichenfolge, die The free company on nameplates will only be visible when the character is in a free company. ähnelt. /// public static string Loc_NameplateFreeCompanyVisibility_Default_Description { get { @@ -862,7 +862,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Never visible. + /// Sucht eine lokalisierte Zeichenfolge, die Never visible ähnelt. /// public static string Loc_NameplateFreeCompanyVisibility_Never { get { @@ -871,7 +871,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The free company on nameplates will never be visible.. + /// Sucht eine lokalisierte Zeichenfolge, die The free company on nameplates will never be visible. ähnelt. /// public static string Loc_NameplateFreeCompanyVisibility_Never_Description { get { @@ -880,7 +880,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Title position. + /// Sucht eine lokalisierte Zeichenfolge, die Title position ähnelt. /// public static string Loc_NameplateTitlePosition { get { @@ -889,7 +889,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Always above name. + /// Sucht eine lokalisierte Zeichenfolge, die Always above name ähnelt. /// public static string Loc_NameplateTitlePosition_AlwaysAboveName { get { @@ -898,7 +898,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The title on nameplates will always be positioned above the name.. + /// Sucht eine lokalisierte Zeichenfolge, die The title on nameplates will always be positioned above the name. ähnelt. /// public static string Loc_NameplateTitlePosition_AlwaysAboveName_Description { get { @@ -907,7 +907,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Always below name. + /// Sucht eine lokalisierte Zeichenfolge, die Always below name ähnelt. /// public static string Loc_NameplateTitlePosition_AlwaysBelowName { get { @@ -916,7 +916,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The title on nameplates will always be positioned below the name.. + /// Sucht eine lokalisierte Zeichenfolge, die The title on nameplates will always be positioned below the name. ähnelt. /// public static string Loc_NameplateTitlePosition_AlwaysBelowName_Description { get { @@ -925,7 +925,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Default. + /// Sucht eine lokalisierte Zeichenfolge, die Default ähnelt. /// public static string Loc_NameplateTitlePosition_Default { get { @@ -934,7 +934,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The title on nameplates will be positioned depending on the title.. + /// Sucht eine lokalisierte Zeichenfolge, die The title on nameplates will be positioned depending on the title. ähnelt. /// public static string Loc_NameplateTitlePosition_Default_Description { get { @@ -943,7 +943,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Title visibility. + /// Sucht eine lokalisierte Zeichenfolge, die Title visibility ähnelt. /// public static string Loc_NameplateTitleVisibility { get { @@ -952,7 +952,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Always visible. + /// Sucht eine lokalisierte Zeichenfolge, die Always visible ähnelt. /// public static string Loc_NameplateTitleVisibility_Always { get { @@ -961,7 +961,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The title on nameplates will always be visible, even when the character does not have a title.. + /// Sucht eine lokalisierte Zeichenfolge, die The title on nameplates will always be visible, even when the character does not have a title. ähnelt. /// public static string Loc_NameplateTitleVisibility_Always_Description { get { @@ -970,7 +970,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Default. + /// Sucht eine lokalisierte Zeichenfolge, die Default ähnelt. /// public static string Loc_NameplateTitleVisibility_Default { get { @@ -979,7 +979,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The title on nameplates will only be visible when the character has a title.. + /// Sucht eine lokalisierte Zeichenfolge, die The title on nameplates will only be visible when the character has a title. ähnelt. /// public static string Loc_NameplateTitleVisibility_Default_Description { get { @@ -988,7 +988,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Never visible. + /// Sucht eine lokalisierte Zeichenfolge, die Never visible ähnelt. /// public static string Loc_NameplateTitleVisibility_Never { get { @@ -997,7 +997,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The title on nameplates will never visible.. + /// Sucht eine lokalisierte Zeichenfolge, die The title on nameplates will never visible. ähnelt. /// public static string Loc_NameplateTitleVisibility_Never_Description { get { @@ -1006,7 +1006,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Only visible when it has tags. + /// Sucht eine lokalisierte Zeichenfolge, die Only visible when it has tags ähnelt. /// public static string Loc_NameplateTitleVisibility_WhenHasTags { get { @@ -1015,7 +1015,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The title on nameplates will only be visible when it has tags.. + /// Sucht eine lokalisierte Zeichenfolge, die The title on nameplates will only be visible when it has tags. ähnelt. /// public static string Loc_NameplateTitleVisibility_WhenHasTags_Description { get { @@ -1024,7 +1024,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Player properties. + /// Sucht eine lokalisierte Zeichenfolge, die Player properties ähnelt. /// public static string Loc_PlayerCategory { get { @@ -1033,7 +1033,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Position properties. + /// Sucht eine lokalisierte Zeichenfolge, die Position properties ähnelt. /// public static string Loc_PositionCategory { get { @@ -1042,7 +1042,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Magical. + /// Sucht eine lokalisierte Zeichenfolge, die Magical ähnelt. /// public static string Loc_RangedDpsRole_Magical { get { @@ -1051,7 +1051,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Physical. + /// Sucht eine lokalisierte Zeichenfolge, die Physical ähnelt. /// public static string Loc_RangedDpsRole_Physical { get { @@ -1060,7 +1060,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to DPS. + /// Sucht eine lokalisierte Zeichenfolge, die DPS ähnelt. /// public static string Loc_Role_Dps { get { @@ -1069,7 +1069,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Healer. + /// Sucht eine lokalisierte Zeichenfolge, die Healer ähnelt. /// public static string Loc_Role_Healer { get { @@ -1078,7 +1078,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Land/Hand. + /// Sucht eine lokalisierte Zeichenfolge, die Land/Hand ähnelt. /// public static string Loc_Role_LandHand { get { @@ -1087,7 +1087,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Tank. + /// Sucht eine lokalisierte Zeichenfolge, die Tank ähnelt. /// public static string Loc_Role_Tank { get { @@ -1096,7 +1096,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Add a custom tag.. + /// Sucht eine lokalisierte Zeichenfolge, die Add a custom tag. ähnelt. /// public static string Loc_Static_AddCustomTag_Description { get { @@ -1105,7 +1105,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Add a property override.. + /// Sucht eine lokalisierte Zeichenfolge, die Add a property override. ähnelt. /// public static string Loc_Static_AddPropertyOverride_Description { get { @@ -1114,7 +1114,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Add tag. + /// Sucht eine lokalisierte Zeichenfolge, die Add tag: {0} ähnelt. /// public static string Loc_Static_ContextMenu_AddTag { get { @@ -1123,7 +1123,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Remove tag. + /// Sucht eine lokalisierte Zeichenfolge, die Remove tag: {0} ähnelt. /// public static string Loc_Static_ContextMenu_RemoveTag { get { @@ -1132,7 +1132,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Development. + /// Sucht eine lokalisierte Zeichenfolge, die Development ähnelt. /// public static string Loc_Static_Development { get { @@ -1141,7 +1141,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Experimental. + /// Sucht eine lokalisierte Zeichenfolge, die Experimental ähnelt. /// public static string Loc_Static_Experimental { get { @@ -1150,7 +1150,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Add '{0}' to {1}.. + /// Sucht eine lokalisierte Zeichenfolge, die Add '{0}' to {1}. ähnelt. /// public static string Loc_Static_Format_AddTagToPlayer { get { @@ -1159,7 +1159,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to General. + /// Sucht eine lokalisierte Zeichenfolge, die General ähnelt. /// public static string Loc_Static_General { get { @@ -1168,7 +1168,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to <Inherited>. + /// Sucht eine lokalisierte Zeichenfolge, die <Inherited> ähnelt. /// public static string Loc_Static_Inherited { get { @@ -1177,7 +1177,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Nameplates. + /// Sucht eine lokalisierte Zeichenfolge, die Nameplates ähnelt. /// public static string Loc_Static_Nameplates { get { @@ -1186,7 +1186,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to New tag. + /// Sucht eine lokalisierte Zeichenfolge, die New tag ähnelt. /// public static string Loc_Static_NewTag { get { @@ -1195,7 +1195,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to <No text>. + /// Sucht eine lokalisierte Zeichenfolge, die <No text> ähnelt. /// public static string Loc_Static_NoText { get { @@ -1204,7 +1204,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Player. + /// Sucht eine lokalisierte Zeichenfolge, die Player ähnelt. /// public static string Loc_Static_PlayerName { get { @@ -1213,7 +1213,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Player Tags. + /// Sucht eine lokalisierte Zeichenfolge, die Player Tags ähnelt. /// public static string Loc_Static_PluginName { get { @@ -1222,7 +1222,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Quick Tag. + /// Sucht eine lokalisierte Zeichenfolge, die Quick Tag ähnelt. /// public static string Loc_Static_QuickTag { get { @@ -1231,7 +1231,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Remove this custom tag.. + /// Sucht eine lokalisierte Zeichenfolge, die Remove this custom tag. ähnelt. /// public static string Loc_Static_RemoveCustomTag_Description { get { @@ -1240,7 +1240,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Remove this property override. The value will be inherited from the parent item.. + /// Sucht eine lokalisierte Zeichenfolge, die Remove this property override. The value will be inherited from the parent item. ähnelt. /// public static string Loc_Static_RemovePropertyOverride_Description { get { @@ -1249,7 +1249,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Reset all items to their defaults. Custom tags will not be touched.. + /// Sucht eine lokalisierte Zeichenfolge, die Reset all items to their defaults. Custom tags will not be touched. ähnelt. /// public static string Loc_Static_ResetAllDefault_Description { get { @@ -1258,7 +1258,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Reset this item to its defaults.. + /// Sucht eine lokalisierte Zeichenfolge, die Reset this item to its defaults. ähnelt. /// public static string Loc_Static_ResetDefault_Description { get { @@ -1267,7 +1267,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Tagged Players. + /// Sucht eine lokalisierte Zeichenfolge, die Tagged Players ähnelt. /// public static string Loc_Static_TaggedPlayers { get { @@ -1276,7 +1276,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Tags. + /// Sucht eine lokalisierte Zeichenfolge, die Tags ähnelt. /// public static string Loc_Static_Tags { get { @@ -1285,7 +1285,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to This plugin can modify nameplates and chat. When combined with other plugins that modify these things, you are likely to see unexpected behavior. The load order of your plugins may make a difference.. + /// Sucht eine lokalisierte Zeichenfolge, die This plugin can modify nameplates and chat. When combined with other plugins that modify these things, you are likely to see unexpected behavior. The load order of your plugins may make a difference. ähnelt. /// public static string Loc_Static_WarningMessage { get { @@ -1294,7 +1294,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to After. + /// Sucht eine lokalisierte Zeichenfolge, die After ähnelt. /// public static string Loc_TagPosition_After { get { @@ -1303,7 +1303,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Display the tag after the target element.. + /// Sucht eine lokalisierte Zeichenfolge, die Display the tag after the target element. ähnelt. /// public static string Loc_TagPosition_After_Description { get { @@ -1312,7 +1312,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Before. + /// Sucht eine lokalisierte Zeichenfolge, die Before ähnelt. /// public static string Loc_TagPosition_Before { get { @@ -1321,7 +1321,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Display the tag before the target element.. + /// Sucht eine lokalisierte Zeichenfolge, die Display the tag before the target element. ähnelt. /// public static string Loc_TagPosition_Before_Description { get { @@ -1330,7 +1330,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Replace. + /// Sucht eine lokalisierte Zeichenfolge, die Replace ähnelt. /// public static string Loc_TagPosition_Replace { get { @@ -1339,7 +1339,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Replace the target element with the tag.. + /// Sucht eine lokalisierte Zeichenfolge, die Replace the target element with the tag. ähnelt. /// public static string Loc_TagPosition_Replace_Description { get { @@ -1348,7 +1348,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Position in chat. + /// Sucht eine lokalisierte Zeichenfolge, die Position in chat ähnelt. /// public static string Loc_TagPositionInChat { get { @@ -1357,7 +1357,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Where the tag will be positioned in chat.. + /// Sucht eine lokalisierte Zeichenfolge, die Where the tag will be positioned in chat. ähnelt. /// public static string Loc_TagPositionInChat_Description { get { @@ -1366,7 +1366,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Position in nameplates. + /// Sucht eine lokalisierte Zeichenfolge, die Position in nameplates ähnelt. /// public static string Loc_TagPositionInNameplates { get { @@ -1375,7 +1375,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Where the tag will be positioned in nameplates.. + /// Sucht eine lokalisierte Zeichenfolge, die Where the tag will be positioned in nameplates. ähnelt. /// public static string Loc_TagPositionInNameplates_Description { get { @@ -1384,7 +1384,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Target in nameplates. + /// Sucht eine lokalisierte Zeichenfolge, die Target in nameplates ähnelt. /// public static string Loc_TagTargetInNameplates { get { @@ -1393,7 +1393,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The element that the tag should target in nameplates.. + /// Sucht eine lokalisierte Zeichenfolge, die The element that the tag should target in nameplates. ähnelt. /// public static string Loc_TagTargetInNameplates_Description { get { @@ -1402,7 +1402,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Text. + /// Sucht eine lokalisierte Zeichenfolge, die Text ähnelt. /// public static string Loc_Text { get { @@ -1411,7 +1411,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The text that will be displayed.. + /// Sucht eine lokalisierte Zeichenfolge, die The text that will be displayed. ähnelt. /// public static string Loc_Text_Description { get { @@ -1420,7 +1420,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Text properties. + /// Sucht eine lokalisierte Zeichenfolge, die Text properties ähnelt. /// public static string Loc_TextCategory { get { @@ -1429,7 +1429,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Color. + /// Sucht eine lokalisierte Zeichenfolge, die Color ähnelt. /// public static string Loc_TextColor { get { @@ -1438,7 +1438,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The color of the text.. + /// Sucht eine lokalisierte Zeichenfolge, die The color of the text. ähnelt. /// public static string Loc_TextColor_Description { get { @@ -1447,7 +1447,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to Glow color. + /// Sucht eine lokalisierte Zeichenfolge, die Glow color ähnelt. /// public static string Loc_TextGlowColor { get { @@ -1456,7 +1456,7 @@ namespace PlayerTags.Resources { } /// - /// Looks up a localized string similar to The glow color of the text.. + /// Sucht eine lokalisierte Zeichenfolge, die The glow color of the text. ähnelt. /// public static string Loc_TextGlowColor_Description { get { diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index bba2495..d7f1ecf 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -136,10 +136,10 @@ Player - Add tag + Add tag: {0} - Remove tag + Remove tag: {0} Nameplates @@ -363,7 +363,6 @@ Whether the icon will be shown in nameplates. - Text @@ -384,7 +383,7 @@ Italic - + Whether the text will be italic. @@ -400,7 +399,6 @@ Whether the text will be shown in nameplates. - Position in chat @@ -419,14 +417,12 @@ The element that the tag should target in nameplates. - Add to players A list of players to add tags to, separated by commas or semi-colons. E.g. "Cloud Strife, Tifa Lockhart". - After @@ -445,15 +441,12 @@ Replace the target element with the tag. - Enabled - Custom id - General properties @@ -472,7 +465,6 @@ Player properties - Show in pve duties @@ -491,7 +483,6 @@ Whether the tag should be visible in other circumstances for which there is no specific option. - Show for self @@ -528,77 +519,66 @@ Whether the tag should be visible for players in other circumstances for which there is no specific option. - Order by proximity Players that are closer to you will be ordered towards the top. - Show self Show yourself in the players list. - Show friends Show friends in the players list. - Show party members Show party members in the players list. - Show alliance members Show alliance members in the players list. - Show enemies Show enemies in the players list. - Show others Show others in the players list. - Apply color to chat name Whether the color will be applied to the name in chat. - Apply color to nameplate name Whether the color will be applied to the name in nameplates. - Apply color to nameplate title Whether the color will be applied to title in nameplates. - Apply color to nameplate free company