From c0f4339188cbd956b0e083493fa171aefddcf793 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 11 May 2022 13:34:04 +0200 Subject: [PATCH 001/174] compatibility with API v6 --- PlayerTags/DalamudPackager.targets | 2 +- PlayerTags/PlayerTags.csproj | 2 +- PlayerTags/PlayerTags.json | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/PlayerTags/DalamudPackager.targets b/PlayerTags/DalamudPackager.targets index fe58a7b..689b28c 100644 --- a/PlayerTags/DalamudPackager.targets +++ b/PlayerTags/DalamudPackager.targets @@ -6,6 +6,6 @@ OutputPath="$(OutputPath)" AssemblyName="$(AssemblyName)" MakeZip="true" - Exclude="$(AssemblyName).pdb;$(AssemblyName).deps.json" /> + Exclude="$(AssemblyName).pdb;$(AssemblyName).deps.json"/> \ No newline at end of file diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 5e6ab4a..d3f3480 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -20,7 +20,7 @@ - + $(DalamudLibPath)FFXIVClientStructs.dll false diff --git a/PlayerTags/PlayerTags.json b/PlayerTags/PlayerTags.json index 3bbd2d4..2470679 100644 --- a/PlayerTags/PlayerTags.json +++ b/PlayerTags/PlayerTags.json @@ -2,13 +2,14 @@ "Author": "r00telement", "Name": "Player Tags", "Description": "Lightweight job visibility in nameplates and chat. Create custom tags and add them to players with the context menu.", + "Punchline": "Lightweight job visibility in nameplates and chat.", "Tags": [ "Jobs", "UI" ], "CategoryTags": [ "jobs", "UI" ], - "RepoUrl": "https://github.com/r00telement/PlayerTags", - "IconUrl": "https://github.com/r00telement/PlayerTags/raw/main/PlayerTags/Resources/Promo/Icon.png", + "RepoUrl": "https://github.com/pilzinsel64/PlayerTags", + "IconUrl": "https://github.com/pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Icon.png", "ImageUrls": [ - "https://github.com/r00telement/PlayerTags/raw/main/PlayerTags/Resources/Promo/Nameplates_1.png", - "https://github.com/r00telement/PlayerTags/raw/main/PlayerTags/Resources/Promo/Chat_1.png" + "https://github.com/pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Nameplates_1.png", + "https://github.com/pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Chat_1.png" ], "Changelog": "" } \ No newline at end of file From cab8de17f552679ee7acf67c9f313479d19404e2 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 11 May 2022 13:37:37 +0200 Subject: [PATCH 002/174] revert links in PlayerTags.json --- PlayerTags/PlayerTags.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PlayerTags/PlayerTags.json b/PlayerTags/PlayerTags.json index 2470679..d522eed 100644 --- a/PlayerTags/PlayerTags.json +++ b/PlayerTags/PlayerTags.json @@ -5,11 +5,11 @@ "Punchline": "Lightweight job visibility in nameplates and chat.", "Tags": [ "Jobs", "UI" ], "CategoryTags": [ "jobs", "UI" ], - "RepoUrl": "https://github.com/pilzinsel64/PlayerTags", - "IconUrl": "https://github.com/pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Icon.png", + "RepoUrl": "https://github.com/r00telement/PlayerTags", + "IconUrl": "https://github.com/r00telement/PlayerTags/raw/main/PlayerTags/Resources/Promo/Icon.png", "ImageUrls": [ - "https://github.com/pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Nameplates_1.png", - "https://github.com/pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Chat_1.png" + "https://github.com/r00telement/PlayerTags/raw/main/PlayerTags/Resources/Promo/Nameplates_1.png", + "https://github.com/r00telement/PlayerTags/raw/main/PlayerTags/Resources/Promo/Chat_1.png" ], "Changelog": "" } \ No newline at end of file From b43935fb7e72ff69651621497c81023d633a15ef Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 29 May 2022 09:06:04 +0200 Subject: [PATCH 003/174] disable context menu on all places (keep in settings back-end) -> To be re-added as soon as new context menu in Dalamud is avialable. --- .../Configuration/PluginConfigurationUI.cs | 6 +- .../Features/CustomTagsContextMenuFeature.cs | 124 +++++++++--------- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index b051b2c..ac14b1a 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -53,9 +53,9 @@ public void Draw() { 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/Features/CustomTagsContextMenuFeature.cs b/PlayerTags/Features/CustomTagsContextMenuFeature.cs index bd73581..7bc8590 100644 --- a/PlayerTags/Features/CustomTagsContextMenuFeature.cs +++ b/PlayerTags/Features/CustomTagsContextMenuFeature.cs @@ -33,83 +33,83 @@ public class CustomTagsContextMenuFeature : IDisposable 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; - } + //m_ContextMenu = new ContextMenu(); + //if (!m_ContextMenu.IsValid) + //{ + // m_ContextMenu = null; + //} - if (m_ContextMenu != null) - { - m_ContextMenu.ContextMenuOpened += ContextMenuHooks_ContextMenuOpened; - } + //if (m_ContextMenu != null) + //{ + // m_ContextMenu.ContextMenuOpened += ContextMenuHooks_ContextMenuOpened; + //} } public void Dispose() { - if (m_ContextMenu != null) - { - m_ContextMenu.ContextMenuOpened -= ContextMenuHooks_ContextMenuOpened; + //if (m_ContextMenu != null) + //{ + // m_ContextMenu.ContextMenuOpened -= ContextMenuHooks_ContextMenuOpened; - m_ContextMenu.Dispose(); - m_ContextMenu = null; - } + // 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.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); + // }))); + // } - 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.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); + // }))); + // } + // } + //} } } From 14899c64f2264dfd12952e605e643279bca515e6 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 15 Jun 2022 22:07:55 +0200 Subject: [PATCH 004/174] updated version and description --- .../Features/CustomTagsContextMenuFeature.cs | 2 +- PlayerTags/PlayerTags.csproj | 2 +- PlayerTags/PlayerTags.json | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/PlayerTags/Features/CustomTagsContextMenuFeature.cs b/PlayerTags/Features/CustomTagsContextMenuFeature.cs index 7bc8590..23d832e 100644 --- a/PlayerTags/Features/CustomTagsContextMenuFeature.cs +++ b/PlayerTags/Features/CustomTagsContextMenuFeature.cs @@ -39,7 +39,7 @@ public CustomTagsContextMenuFeature(PluginConfiguration pluginConfiguration, Plu { m_PluginConfiguration = pluginConfiguration; m_PluginData = pluginData; - + //m_ContextMenu = new ContextMenu(); //if (!m_ContextMenu.IsValid) //{ diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index d3f3480..e5dc305 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,6 +1,6 @@  - r00telement + Pilzinsel64 1.2.0.0 diff --git a/PlayerTags/PlayerTags.json b/PlayerTags/PlayerTags.json index d522eed..10df840 100644 --- a/PlayerTags/PlayerTags.json +++ b/PlayerTags/PlayerTags.json @@ -1,15 +1,15 @@ { - "Author": "r00telement", + "Author": "Pilzinsel64", "Name": "Player Tags", - "Description": "Lightweight job visibility in nameplates and chat. Create custom tags and add them to players with the context menu.", + "Description": "Lightweight job visibility in nameplates and chat. Create custom tags and add them to players with the context menu.\n\nYou want to contribute and help developing new features or want to extend existing? Feel free to open Fork and open a Pull Request!\n\nThis plugin was originally developed by r00telement but forked and continued by Pilzinsel64.", "Punchline": "Lightweight job visibility in nameplates and chat.", "Tags": [ "Jobs", "UI" ], "CategoryTags": [ "jobs", "UI" ], - "RepoUrl": "https://github.com/r00telement/PlayerTags", - "IconUrl": "https://github.com/r00telement/PlayerTags/raw/main/PlayerTags/Resources/Promo/Icon.png", + "RepoUrl": "https://github.com/Pilzinsel64/PlayerTags", + "IconUrl": "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Icon.png", "ImageUrls": [ - "https://github.com/r00telement/PlayerTags/raw/main/PlayerTags/Resources/Promo/Nameplates_1.png", - "https://github.com/r00telement/PlayerTags/raw/main/PlayerTags/Resources/Promo/Chat_1.png" + "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Nameplates_1.png", + "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Chat_1.png" ], - "Changelog": "" + "Changelog": "Version 1.3\n- Updated for API v6\n- Disabled context menus for now (will be re-added soon with an another update)\n- Updated the plugin info" } \ No newline at end of file From 4a68edd1ba54504d5a8f61c04f4fbebfda0e5f70 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 15 Jun 2022 22:10:42 +0200 Subject: [PATCH 005/174] fix wrong version in plugin info --- PlayerTags/PlayerTags.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.json b/PlayerTags/PlayerTags.json index 10df840..6bdce34 100644 --- a/PlayerTags/PlayerTags.json +++ b/PlayerTags/PlayerTags.json @@ -11,5 +11,5 @@ "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Nameplates_1.png", "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Chat_1.png" ], - "Changelog": "Version 1.3\n- Updated for API v6\n- Disabled context menus for now (will be re-added soon with an another update)\n- Updated the plugin info" + "Changelog": "Version 1.2\n- Updated for API v6\n- Disabled context menus for now (will be re-added soon with an another update)\n- Updated the plugin info" } \ No newline at end of file From 342cb792b9d54af247c2514252cfaebf855e4da1 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 16 Jun 2022 01:18:31 +0200 Subject: [PATCH 006/174] 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 @@ public void Draw() 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 @@ public void Draw() { 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 @@ public class CustomTagsContextMenuFeature : IDisposable 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.Party; using Dalamud.Game.Command; using Dalamud.Game.Gui; +using Dalamud.Game.Gui.ContextMenus; using Dalamud.IoC; using Dalamud.Plugin; From 5d6a8f5b2b098898398e9de33678087083d60973 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 16 Jun 2022 01:39:31 +0200 Subject: [PATCH 007/174] fix plugin info --- PlayerTags/PlayerTags.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PlayerTags/PlayerTags.json b/PlayerTags/PlayerTags.json index 6bdce34..3650eae 100644 --- a/PlayerTags/PlayerTags.json +++ b/PlayerTags/PlayerTags.json @@ -1,15 +1,15 @@ { - "Author": "Pilzinsel64", + "Author": "r00telement", "Name": "Player Tags", "Description": "Lightweight job visibility in nameplates and chat. Create custom tags and add them to players with the context menu.\n\nYou want to contribute and help developing new features or want to extend existing? Feel free to open Fork and open a Pull Request!\n\nThis plugin was originally developed by r00telement but forked and continued by Pilzinsel64.", "Punchline": "Lightweight job visibility in nameplates and chat.", "Tags": [ "Jobs", "UI" ], "CategoryTags": [ "jobs", "UI" ], "RepoUrl": "https://github.com/Pilzinsel64/PlayerTags", - "IconUrl": "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Icon.png", + "IconUrl": "", "ImageUrls": [ "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Nameplates_1.png", "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Chat_1.png" ], - "Changelog": "Version 1.2\n- Updated for API v6\n- Disabled context menus for now (will be re-added soon with an another update)\n- Updated the plugin info" + "Changelog": "" } \ No newline at end of file From dc9e17a79f2a577801b5dca33b847405a4414deb Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 16 Jun 2022 01:40:55 +0200 Subject: [PATCH 008/174] keep original author --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index e5dc305..d3f3480 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,6 +1,6 @@  - Pilzinsel64 + r00telement 1.2.0.0 From 3a524f1b8d5bcf4a0b8846298f72989b7e87ef5c Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 16 Jun 2022 01:56:05 +0200 Subject: [PATCH 009/174] fix plugin info again --- PlayerTags/PlayerTags.csproj | 2 +- PlayerTags/PlayerTags.json | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index d3f3480..880d694 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,6 +1,6 @@  - r00telement + r00telement;Pilzinsel64 1.2.0.0 diff --git a/PlayerTags/PlayerTags.json b/PlayerTags/PlayerTags.json index 3650eae..015b42b 100644 --- a/PlayerTags/PlayerTags.json +++ b/PlayerTags/PlayerTags.json @@ -1,15 +1,13 @@ { - "Author": "r00telement", + "Author": "r00telement, Pilzinsel64", "Name": "Player Tags", "Description": "Lightweight job visibility in nameplates and chat. Create custom tags and add them to players with the context menu.\n\nYou want to contribute and help developing new features or want to extend existing? Feel free to open Fork and open a Pull Request!\n\nThis plugin was originally developed by r00telement but forked and continued by Pilzinsel64.", "Punchline": "Lightweight job visibility in nameplates and chat.", "Tags": [ "Jobs", "UI" ], "CategoryTags": [ "jobs", "UI" ], "RepoUrl": "https://github.com/Pilzinsel64/PlayerTags", - "IconUrl": "", "ImageUrls": [ "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Nameplates_1.png", "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Chat_1.png" - ], - "Changelog": "" + ] } \ No newline at end of file From 894bb08a4eb8178dbf217ec82fdac88b9299645a Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 16 Jun 2022 10:04:13 +0200 Subject: [PATCH 010/174] change names of image files and remove some --- PlayerTags/PlayerTags.json | 4 ++-- PlayerTags/Resources/Promo/Chat_2.png | Bin 102200 -> 0 bytes PlayerTags/Resources/Promo/Nameplates_1.png | Bin 532153 -> 0 bytes PlayerTags/Resources/Promo/PatchNote_1.png | Bin 30853 -> 0 bytes PlayerTags/Resources/Promo/PatchNote_3.png | Bin 9912 -> 0 bytes .../{Promo/Icon.png => images/icon.png} | Bin .../{Promo/Chat_1.png => images/image1.png} | Bin .../PatchNote_2.png => images/image2.png} | Bin 8 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 PlayerTags/Resources/Promo/Chat_2.png delete mode 100644 PlayerTags/Resources/Promo/Nameplates_1.png delete mode 100644 PlayerTags/Resources/Promo/PatchNote_1.png delete mode 100644 PlayerTags/Resources/Promo/PatchNote_3.png rename PlayerTags/Resources/{Promo/Icon.png => images/icon.png} (100%) rename PlayerTags/Resources/{Promo/Chat_1.png => images/image1.png} (100%) rename PlayerTags/Resources/{Promo/PatchNote_2.png => images/image2.png} (100%) diff --git a/PlayerTags/PlayerTags.json b/PlayerTags/PlayerTags.json index 015b42b..a4bf8cd 100644 --- a/PlayerTags/PlayerTags.json +++ b/PlayerTags/PlayerTags.json @@ -7,7 +7,7 @@ "CategoryTags": [ "jobs", "UI" ], "RepoUrl": "https://github.com/Pilzinsel64/PlayerTags", "ImageUrls": [ - "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Nameplates_1.png", - "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/Promo/Chat_1.png" + "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/images/image1.png", + "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/images/image2.png" ] } \ No newline at end of file diff --git a/PlayerTags/Resources/Promo/Chat_2.png b/PlayerTags/Resources/Promo/Chat_2.png deleted file mode 100644 index 1511f600d8ce326d1dd12771bae8e0757718d319..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102200 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%0D?diX!5Gt_^l)KXh?Qyu9yy`(NMn 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

Fdr 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 IM6N<$f*^r=;{X5v diff --git a/PlayerTags/Resources/Promo/Nameplates_1.png b/PlayerTags/Resources/Promo/Nameplates_1.png deleted file mode 100644 index 491e0665a8c9af6ba3392d8f3c827f94ce862eee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 532153 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

NQ0cXI#*x84S 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�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%0DF%4*l{)P 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 z%0A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

tGn>NK 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

%$d$IeE##FFR0hw8*jeZiY=RoBGxV=%F>2^ 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 z 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

0^sMn*+fCycpMPnA#eBJ+97%fdOtEoR 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

1ZTX5yQ5RC@|!OO1O4fFI_}{dWN$4Zv>=(} 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 diff --git a/PlayerTags/Resources/Promo/PatchNote_1.png b/PlayerTags/Resources/Promo/PatchNote_1.png deleted file mode 100644 index 7afa70b3d15e32ac20b30316744dec4fd82a8ab0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30853 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 z 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 diff --git a/PlayerTags/Resources/Promo/PatchNote_3.png b/PlayerTags/Resources/Promo/PatchNote_3.png deleted file mode 100644 index 8c2bd8f3826746d0bd54ed3ff104e3c6b6dd49fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9912 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 diff --git a/PlayerTags/Resources/Promo/Icon.png b/PlayerTags/Resources/images/icon.png similarity index 100% rename from PlayerTags/Resources/Promo/Icon.png rename to PlayerTags/Resources/images/icon.png diff --git a/PlayerTags/Resources/Promo/Chat_1.png b/PlayerTags/Resources/images/image1.png similarity index 100% rename from PlayerTags/Resources/Promo/Chat_1.png rename to PlayerTags/Resources/images/image1.png diff --git a/PlayerTags/Resources/Promo/PatchNote_2.png b/PlayerTags/Resources/images/image2.png similarity index 100% rename from PlayerTags/Resources/Promo/PatchNote_2.png rename to PlayerTags/Resources/images/image2.png From 9e15f027389a1a8c9149cfa72f47feffd3c68107 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 16 Jun 2022 10:04:32 +0200 Subject: [PATCH 011/174] remove ImageURLs in plugin info --- PlayerTags/PlayerTags.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/PlayerTags/PlayerTags.json b/PlayerTags/PlayerTags.json index a4bf8cd..60d41a1 100644 --- a/PlayerTags/PlayerTags.json +++ b/PlayerTags/PlayerTags.json @@ -5,9 +5,5 @@ "Punchline": "Lightweight job visibility in nameplates and chat.", "Tags": [ "Jobs", "UI" ], "CategoryTags": [ "jobs", "UI" ], - "RepoUrl": "https://github.com/Pilzinsel64/PlayerTags", - "ImageUrls": [ - "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/images/image1.png", - "https://github.com/Pilzinsel64/PlayerTags/raw/main/PlayerTags/Resources/images/image2.png" - ] + "RepoUrl": "https://github.com/Pilzinsel64/PlayerTags" } \ No newline at end of file From 7e28f028d10067a7f6e7a15bdbab9371bc5951d0 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 16 Jun 2022 14:54:37 +0200 Subject: [PATCH 012/174] 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 @@ private struct PlayerInfo private PluginData m_PluginData; private InheritableValue? m_ColorPickerPopupDataContext; + public static int asdfasdfasdf = 0; public PluginConfigurationUI(PluginConfiguration config, PluginData pluginData) { @@ -43,7 +44,7 @@ public void Draw() 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 @@ public Identity GetIdentity(string name, uint? worldId) }; } - 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 @@ public class CustomTagsContextMenuFeature : IDisposable 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 013/174] 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 @@ private struct PlayerInfo private PluginData m_PluginData; private InheritableValue? m_ColorPickerPopupDataContext; - public static int asdfasdfasdf = 0; public PluginConfigurationUI(PluginConfiguration config, PluginData pluginData) { @@ -44,7 +43,7 @@ public void Draw() 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 @@ public Identity GetIdentity(string name, uint? worldId) 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 @@ public CustomTagsContextMenuFeature(PluginConfiguration pluginConfiguration, Plu m_ContextMenu = new DalamudContextMenuBase(); m_ContextMenu.Functions.ContextMenu.OnOpenGameObjectContextMenu += ContextMenuHooks_ContextMenuOpened; - PluginConfigurationUI.asdfasdfasdf = 1; } public void Dispose() @@ -57,57 +56,44 @@ public void Dispose() 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 @@ internal Strings() { } /// - /// 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 @@ internal Strings() { } /// - /// 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 @@ internal Strings() { } /// - /// 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 @@ public static string Loc_ActivityCategory { } /// - /// 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 @@ public static string Loc_AllCustomTags { } /// - /// 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 @@ public static string Loc_AllRoleTags { } /// - /// 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 @@ public static string Loc_AllTags { } /// - /// 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 @@ public static string Loc_CustomId { } /// - /// 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 @@ public static string Loc_CustomTags { } /// - /// 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 @@ public static string Loc_DpsRole_Melee { } /// - /// 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 @@ public static string Loc_DpsRole_Ranged { } /// - /// 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 @@ public static string Loc_GameObjectNamesToApplyTo { } /// - /// 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 @@ public static string Loc_GameObjectNamesToApplyTo_Description { } /// - /// 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 @@ public static string Loc_GeneralCategory { } /// - /// 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 @@ public static string Loc_Icon { } /// - /// 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 @@ public static string Loc_Icon_Description { } /// - /// 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 @@ public static string Loc_IconCategory { } /// - /// 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 @@ public static string Loc_IsApplyTagsToAllChatMessagesEnabled { } /// - /// 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 @@ public static string Loc_IsApplyTagsToAllChatMessagesEnabled_Description { } /// - /// 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 @@ public static string Loc_IsCustomTagsContextMenuEnabled { } /// - /// 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 @@ public static string Loc_IsCustomTagsContextMenuEnabled_Description { } /// - /// 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 @@ public static string Loc_IsEnabled { } /// - /// 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 @@ public static string Loc_IsEnabled_Description { } /// - /// 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 @@ public static string Loc_IsExpanded { } /// - /// 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 @@ public static string Loc_IsIconVisibleInChat { } /// - /// 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 @@ public static string Loc_IsIconVisibleInChat_Description { } /// - /// 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 @@ public static string Loc_IsIconVisibleInNameplates { } /// - /// 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 @@ public static string Loc_IsIconVisibleInNameplates_Description { } /// - /// 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 @@ public static string Loc_IsLinkSelfInChatEnabled { } /// - /// 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 @@ public static string Loc_IsLinkSelfInChatEnabled_Description { } /// - /// 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 @@ public static string Loc_IsPlayerNameRandomlyGenerated { } /// - /// 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 @@ public static string Loc_IsPlayerNameRandomlyGenerated_Description { } /// - /// 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 @@ public static string Loc_IsPlayersTabAllianceVisible { } /// - /// 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 @@ public static string Loc_IsPlayersTabAllianceVisible_Description { } /// - /// 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 @@ public static string Loc_IsPlayersTabEnemiesVisible { } /// - /// 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 @@ public static string Loc_IsPlayersTabEnemiesVisible_Description { } /// - /// 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 @@ public static string Loc_IsPlayersTabFriendsVisible { } /// - /// 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 @@ public static string Loc_IsPlayersTabFriendsVisible_Description { } /// - /// 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 @@ public static string Loc_IsPlayersTabOrderedByProximity { } /// - /// 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 @@ public static string Loc_IsPlayersTabOrderedByProximity_Description { } /// - /// 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 @@ public static string Loc_IsPlayersTabOthersVisible { } /// - /// 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 @@ public static string Loc_IsPlayersTabOthersVisible_Description { } /// - /// 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 @@ public static string Loc_IsPlayersTabPartyVisible { } /// - /// 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 @@ public static string Loc_IsPlayersTabPartyVisible_Description { } /// - /// 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 @@ public static string Loc_IsPlayersTabSelfVisible { } /// - /// 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 @@ public static string Loc_IsPlayersTabSelfVisible_Description { } /// - /// 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 @@ public static string Loc_IsSelected { } /// - /// 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 @@ public static string Loc_IsShowInheritedPropertiesEnabled { } /// - /// 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 @@ public static string Loc_IsShowInheritedPropertiesEnabled_Description { } /// - /// 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 @@ public static string Loc_IsTextColorAppliedToChatName { } /// - /// 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 @@ public static string Loc_IsTextColorAppliedToChatName_Description { } /// - /// 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 @@ public static string Loc_IsTextColorAppliedToNameplateFreeCompany { } /// - /// 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 @@ public static string Loc_IsTextColorAppliedToNameplateFreeCompany_Description { } /// - /// 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 @@ public static string Loc_IsTextColorAppliedToNameplateName { } /// - /// 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 @@ public static string Loc_IsTextColorAppliedToNameplateName_Description { } /// - /// 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 @@ public static string Loc_IsTextColorAppliedToNameplateTitle { } /// - /// 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 @@ public static string Loc_IsTextColorAppliedToNameplateTitle_Description { } /// - /// 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 @@ public static string Loc_IsTextItalic { } /// - /// 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 @@ public static string Loc_IsTextItalic_Description { } /// - /// 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 @@ public static string Loc_IsTextVisibleInChat { } /// - /// 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 @@ public static string Loc_IsTextVisibleInChat_Description { } /// - /// 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 @@ public static string Loc_IsTextVisibleInNameplates { } /// - /// 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 @@ public static string Loc_IsTextVisibleInNameplates_Description { } /// - /// 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 @@ public static string Loc_IsVisibleForAlliancePlayers { } /// - /// 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 @@ public static string Loc_IsVisibleForAlliancePlayers_Description { } /// - /// 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 @@ public static string Loc_IsVisibleForEnemyPlayers { } /// - /// 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 @@ public static string Loc_IsVisibleForEnemyPlayers_Description { } /// - /// 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 @@ public static string Loc_IsVisibleForFriendPlayers { } /// - /// 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 @@ public static string Loc_IsVisibleForFriendPlayers_Description { } /// - /// 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 @@ public static string Loc_IsVisibleForOtherPlayers { } /// - /// 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 @@ public static string Loc_IsVisibleForOtherPlayers_Description { } /// - /// 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 @@ public static string Loc_IsVisibleForPartyPlayers { } /// - /// 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 @@ public static string Loc_IsVisibleForPartyPlayers_Description { } /// - /// 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 @@ public static string Loc_IsVisibleForSelf { } /// - /// 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 @@ public static string Loc_IsVisibleForSelf_Description { } /// - /// 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 @@ public static string Loc_IsVisibleInOverworld { } /// - /// 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 @@ public static string Loc_IsVisibleInOverworld_Description { } /// - /// 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 @@ public static string Loc_IsVisibleInPveDuties { } /// - /// 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 @@ public static string Loc_IsVisibleInPveDuties_Description { } /// - /// 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 @@ public static string Loc_IsVisibleInPvpDuties { } /// - /// 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 @@ public static string Loc_IsVisibleInPvpDuties_Description { } /// - /// 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 @@ public static string Loc_LandHandRole_Hand { } /// - /// 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 @@ public static string Loc_LandHandRole_Land { } /// - /// 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 @@ public static string Loc_NameplateElement_FreeCompany { } /// - /// 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 @@ public static string Loc_NameplateElement_FreeCompany_Description { } /// - /// 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 @@ public static string Loc_NameplateElement_Name { } /// - /// 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 @@ public static string Loc_NameplateElement_Name_Description { } /// - /// 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 @@ public static string Loc_NameplateElement_Title { } /// - /// 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 @@ public static string Loc_NameplateElement_Title_Description { } /// - /// 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 @@ public static string Loc_NameplateFreeCompanyVisibility { } /// - /// 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 @@ public static string Loc_NameplateFreeCompanyVisibility_Default { } /// - /// 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 @@ public static string Loc_NameplateFreeCompanyVisibility_Default_Description { } /// - /// 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 @@ public static string Loc_NameplateFreeCompanyVisibility_Never { } /// - /// 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 @@ public static string Loc_NameplateFreeCompanyVisibility_Never_Description { } /// - /// 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 @@ public static string Loc_NameplateTitlePosition { } /// - /// 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 @@ public static string Loc_NameplateTitlePosition_AlwaysAboveName { } /// - /// 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 @@ public static string Loc_NameplateTitlePosition_AlwaysAboveName_Description { } /// - /// 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 @@ public static string Loc_NameplateTitlePosition_AlwaysBelowName { } /// - /// 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 @@ public static string Loc_NameplateTitlePosition_AlwaysBelowName_Description { } /// - /// 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 @@ public static string Loc_NameplateTitlePosition_Default { } /// - /// 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 @@ public static string Loc_NameplateTitlePosition_Default_Description { } /// - /// 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 @@ public static string Loc_NameplateTitleVisibility { } /// - /// 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 @@ public static string Loc_NameplateTitleVisibility_Always { } /// - /// 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 @@ public static string Loc_NameplateTitleVisibility_Always_Description { } /// - /// 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 @@ public static string Loc_NameplateTitleVisibility_Default { } /// - /// 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 @@ public static string Loc_NameplateTitleVisibility_Default_Description { } /// - /// 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 @@ public static string Loc_NameplateTitleVisibility_Never { } /// - /// 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 @@ public static string Loc_NameplateTitleVisibility_Never_Description { } /// - /// 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 @@ public static string Loc_NameplateTitleVisibility_WhenHasTags { } /// - /// 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 @@ public static string Loc_NameplateTitleVisibility_WhenHasTags_Description { } /// - /// 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 @@ public static string Loc_PlayerCategory { } /// - /// 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 @@ public static string Loc_PositionCategory { } /// - /// 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 @@ public static string Loc_RangedDpsRole_Magical { } /// - /// 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 @@ public static string Loc_RangedDpsRole_Physical { } /// - /// 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 @@ public static string Loc_Role_Dps { } /// - /// 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 @@ public static string Loc_Role_Healer { } /// - /// 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 @@ public static string Loc_Role_LandHand { } /// - /// 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 @@ public static string Loc_Role_Tank { } /// - /// 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 @@ public static string Loc_Static_AddCustomTag_Description { } /// - /// 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 @@ public static string Loc_Static_AddPropertyOverride_Description { } /// - /// 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 @@ public static string Loc_Static_ContextMenu_AddTag { } /// - /// 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 @@ public static string Loc_Static_ContextMenu_RemoveTag { } /// - /// 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 @@ public static string Loc_Static_Development { } /// - /// 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 @@ public static string Loc_Static_Experimental { } /// - /// 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 @@ public static string Loc_Static_Format_AddTagToPlayer { } /// - /// 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 @@ public static string Loc_Static_General { } /// - /// 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 @@ public static string Loc_Static_Inherited { } /// - /// 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 @@ public static string Loc_Static_Nameplates { } /// - /// 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 @@ public static string Loc_Static_NewTag { } /// - /// 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 @@ public static string Loc_Static_NoText { } /// - /// 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 @@ public static string Loc_Static_PlayerName { } /// - /// 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 @@ public static string Loc_Static_PluginName { } /// - /// 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 @@ public static string Loc_Static_QuickTag { } /// - /// 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 @@ public static string Loc_Static_RemoveCustomTag_Description { } /// - /// 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 @@ public static string Loc_Static_RemovePropertyOverride_Description { } /// - /// 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 @@ public static string Loc_Static_ResetAllDefault_Description { } /// - /// 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 @@ public static string Loc_Static_ResetDefault_Description { } /// - /// 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 @@ public static string Loc_Static_TaggedPlayers { } /// - /// 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 @@ public static string Loc_Static_Tags { } /// - /// 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 @@ public static string Loc_Static_WarningMessage { } /// - /// 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 @@ public static string Loc_TagPosition_After { } /// - /// 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 @@ public static string Loc_TagPosition_After_Description { } /// - /// 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 @@ public static string Loc_TagPosition_Before { } /// - /// 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 @@ public static string Loc_TagPosition_Before_Description { } /// - /// 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 @@ public static string Loc_TagPosition_Replace { } /// - /// 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 @@ public static string Loc_TagPosition_Replace_Description { } /// - /// 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 @@ public static string Loc_TagPositionInChat { } /// - /// 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 @@ public static string Loc_TagPositionInChat_Description { } /// - /// 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 @@ public static string Loc_TagPositionInNameplates { } /// - /// 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 @@ public static string Loc_TagPositionInNameplates_Description { } /// - /// 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 @@ public static string Loc_TagTargetInNameplates { } /// - /// 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 @@ public static string Loc_TagTargetInNameplates_Description { } /// - /// 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 @@ public static string Loc_Text { } /// - /// 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 @@ public static string Loc_Text_Description { } /// - /// 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 @@ public static string Loc_TextCategory { } /// - /// 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 @@ public static string Loc_TextColor { } /// - /// 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 @@ public static string Loc_TextColor_Description { } /// - /// 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 @@ public static string Loc_TextGlowColor { } /// - /// 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 From 617d666aa33d8e400ddefc4ed46c1793a9d080fe Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 17 Jun 2022 12:45:25 +0200 Subject: [PATCH 014/174] cahnge version to v1.3 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index bbed5d0..fb3f3b2 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.2.0.0 + 1.3.0.0 From 28d56fe3c8504a5949933a4e22d837382e7bb486 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 18 Jun 2022 16:03:32 +0200 Subject: [PATCH 015/174] increase default window size --- PlayerTags/Configuration/PluginConfigurationUI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index 48fdab5..c25073c 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -41,7 +41,7 @@ public void Draw() return; } - ImGui.SetNextWindowSize(new Vector2(400, 500), ImGuiCond.FirstUseEver); + ImGui.SetNextWindowSize(new Vector2(600, 500), ImGuiCond.FirstUseEver); if (ImGui.Begin(Strings.Loc_Static_PluginName, ref m_PluginConfiguration.IsVisible)) { From 5085502b942e1457d3996717723163b2acb5d6ab Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 18 Jun 2022 17:48:53 +0200 Subject: [PATCH 016/174] add german translation --- PlayerTags/Resources/Strings.de.resx | 588 +++++++++++++++++++++++++++ 1 file changed, 588 insertions(+) create mode 100644 PlayerTags/Resources/Strings.de.resx diff --git a/PlayerTags/Resources/Strings.de.resx b/PlayerTags/Resources/Strings.de.resx new file mode 100644 index 0000000..a67b4aa --- /dev/null +++ b/PlayerTags/Resources/Strings.de.resx @@ -0,0 +1,588 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Player Tags + + + Dieses Plugin kann Namensanzeige und Chat verändern. Kombiniert mit anderen Plugins, die diese ebenfalls verändern, kann es zu unerwartetem Verhalten kommen. Die Lade-Reihenfolge deiner Plugins kann einen Unterschied machen. + + + Generell + + + Quick Tag + + + Getaggte Spieler + + + Spieler + + + Tag hinzufügen: {0} + + + Tag entfernen: {0} + + + Namensanzeigen + + + Füge '{0}' zu {1} hinzu. + + + <Vererbt> + + + Ausgewählt + + + Erweitert + + + Kontext-Menü Integration + + + Optionen zum Hinzufügen und Entfernen benutzerdefinierter Tags von Spielern sind im Kontextmenü verfügbar. + + + Zeige vererbte Eigenschaften + + + Eigenschaften, die von übergeordneten Elementen vererbt wurden, werden im Editor angezeigt + + + Sichtbarkeit der Freien Gesellschaft + + + Standart + + + Die Freie Gesellschaft ist nur dann auf der Namensanzeige sichtbar, wenn der Charakter Mitglied einer Freien Gesellschaft ist. + + + Nie sichtbar + + + Die Freie Gesellschaft ist nie auf der Namensanzeige zu sehen. + + + Sichtbarkeit des Titels + + + Immer sichtbar + + + Der Titel ist auch dann auf der Namensanzeige sichtbar, wenn der Charakter keinen Titel hat. + + + Standart + + + Der Titel ist nur dann auf der Namensanzeige sichtbar, wenn der Charakter einen Titel hat. + + + Nie sichtbar + + + Der Titel ist auf der Namensanzeige nie sichtbar. + + + Nur sichtbar, wenn getaggt + + + Der Titel ist nur auf der Namensanzeige sichtbar, wenn er getaggt ist. + + + Position des Titels + + + Immer über dem Namen + + + Der Titel wird immer oberhalb der Namensanzeige positioniert. + + + Immer unter dem Namen + + + Der Titel wird immer unterhalb der Namensanzeige positioniert + + + Standart + + + Die Position des Titels auf der Namensanzeige wird abhängig vom Titel bestimmt. + + + Freie Gesellschaft + + + Das Element "Freie Gesellschaft" auf der Namensanzeige + + + Name + + + Das Element "Name" auf der Namensanzeige + + + Titel + + + Das Element "Titel" auf der Namensanzeige + + + Entwicklung + + + Experimentell + + + Zufällig generierte Spielernamen + + + Ersetzt jeden Spielernamen durch einen zufällig generierten. + + + Tags für den eigenen Charakter im Chat anwenden + + + Versucht, deinen Chat-Namen mit deinem Charakter zu verknüpfen, was es erlaubt, Tags auf den eigenen Charakter im Chat anzuwenden. + + + Fügt Tags zu allen Chat-Nachrichten hinzu. + + + Fügt Tags zu allen Chat-Nachrichten hinzu, einschließlich Nicht-Sozialer Nachrichten. + + + Setze dieses Element auf seine Ursprungs-Werte zurück. + + + Setze alle Elemente auf ihre Ursprungs-Werte zurück. Benutzerdefinierte Tags bleiben unberührt. + + + Tags + + + <Kein Text> + + + Alle + + + Rollen + + + Handwerker/Sammler + + + Verteidiger + + + Heiler + + + Angreifer + + + Nahkämpfer + + + Fernkämpfer + + + Magisch + + + Physisch + + + Handwerker + + + Sammler + + + Benutzerdefiniert + + + Benutzerdefiniert + + + Aktiviert den Wert dieses Eingriffs. + + + Füge eine Eigenschafts-Überschreibung hinzu + + + Entferne diese Eigenschafts-Überschreibung. Der Wert wird vom übergeordneten Wert vererbt. + + + Neuer Tag + + + Füge einen benutzerdefinierten Tag hinzu. + + + Entferne diesen benutzerdefinierten Tag. + + + Symbol + + + Das Symbol, das dargestellt wird + + + Zeige im Chat + + + Bestimmt, ob das Symbol im Chat dargestellt wird. + + + Zeige in der Namensanzeige + + + Bestimmt, ob das Symbol in der Namensanzeige dargestellt wird. + + + Text + + + Der Text der angezeigt wird + + + Farbe + + + Die Farbe des Texts + + + Leuchtfarbe + + + Die Leuchtfarbe des Texts + + + Kursiv + + + Bestimmt, ob der Text kursiv dargestellt wird + + + Zeige in Chat + + + Bestimmt, ob der Text im Chat angezeigt wird + + + Zeige in der Namensanzeige + + + Bestimmt, ob der Text in der Namensanzeige dargestellt wird + + + Position im Chat + + + Bestimmt, wo der Tag im Chat positioniert wird + + + Position in der Namensanzeige + + + Bestimmt, wo der Tag in der Namensanzeige positioniert wird + + + Ziel in der Namensanzeige + + + Das Element in der Namensanzeige, auf das der Tag zugreifen soll. + + + Zu Spielern hinzufügen + + + Eine Liste von Spielern, denen Tags hinzugefügt werden sollen, getrennt durch Kommas oder Semikolons, z.B. "Cloud Strife, Tifa Lockhart". + + + Danach + + + Zeigt den Tag nach dem Zielelement an. + + + Davor + + + Zeigt den Tag vor dem Zielelement an. + + + Ersetze + + + Ersetze das Zielelement mit dem Tag + + + Aktiviert + + + Benutzerdefinierte ID + + + Generelle Eigenschaften + + + Symbol-Eigenschaften + + + Text-Eigenschaften + + + Positions-Eigenschaften + + + Aktivitäts-Eigenschaften + + + Spieler Eigenschaften + + + Zeige in PvE-Inhalten + + + Bestimmt, ob der Tag in PvE-Inhalten sichtbar sein soll. + + + Zeige in PvP-Inhalten + + + Bestimmt, ob der Tag in PvP-Inhalten sichtbar sein soll + + + Zeige überall sonst + + + Bestimmt, ob der Tag in Umständen sichtbar sein soll, für die keine spezifische Option verfügbar sind + + + Zeige für den eigenen Charakter + + + Bestimmt, ob der Tag für den eigenen Charakter sichtbar sein soll + + + Zeige für Gruppenmitglieder + + + Bestimmt, ob der Tag für Gruppenmitglieder sichtbar sein soll + + + Zeige für Allianz-Mitglieder + + + Bestimmt, ob der Tag für Allianz-Mitglieder sichtbar sein soll, die nicht in der aktuellen Gruppe sind + + + Zeige für Freunde + + + Bestimmt, ob der Tag für Freunde sichtbar sein soll + + + Zeige für Feinde + + + Bestimmt, ob der Tag für Feinde im PvP sichtbar sein soll. + + + Zeige für Andere + + + Bestimmt, ob der Tag für andere Spieler in Inhalten sichtbar sein soll, für die keine spezifische Option verfügbar sind + + + Sortiere nach Bekanntheitsgrad + + + Spieler, die dir bekannter sind, werden in der Liste weiter oben angezeigt. + + + Zeige eigenen Charakter + + + Zeige den eigenen Charakter in der Spielerliste + + + Zeige Freunde + + + Zeige Freunde in der Spielerliste + + + Zeige Gruppenmitglieder + + + Zeige Gruppenmitglieder in der Spielerliste + + + Zeige Allianz-Mitglieder + + + Zeige Allianz-Mitglieder in der Spieler-Liste + + + Zeige Feinde + + + Zeige Feinde in der Spieler-Liste + + + Zeige Andere + + + Zeige Andere in der Spielerliste + + + Wende Farbe auf den Chat-Namen an + + + Bestimmt, ob im Chat die Farbe auf den Namen angewendet wird. + + + Wende Farbe auf den Namen der Namensanzeige an + + + Bestimmt, ob die Farbe in der Namensanzeige auf den Namen angewendet wird + + + Wende die Farbe auf den Titel der Namensanzeige an + + + Bestimmt, ob die Farbe in der Namensanzeige auf den Titel angewendet wird + + + Wende Farbe auf die Freie Gesellschaft an + + + Bestimmt, ob die Farbe in der Namensanzeige auf die Freie Gesellschaft angewendet wird + + \ No newline at end of file From cb81c54e07e220ab0b0166f36a4c3c02ed649fc4 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 29 Jun 2022 19:07:43 +0200 Subject: [PATCH 017/174] Create README.md --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..fdf3833 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# PlayerTags + +Lightweight job visibility in nameplates and chat. Create custom tags and add them to players with the context menu. + +# Contribution + +You want to help and contribute to this project? \ +Feel free to open a pull request with your enhancements or bug fixes! + +# Translation + +You want to help and translate this plugin to your/other language(s)? \ +Start translation [here on Transifex](https://www.transifex.com/pilzinsel64/playertags)! + +If you want to contribute to a language that isn't listed, just tell me with an Issue or on goat's Discord Server (yes, feel free to ping me). ^^ + +# Credits + +This plugin was originally developed by r00telement but forked and continued by Pilzinsel64. From a3b482de351e8b3eaca0f5e88bb076cab41adfcf Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 13 Jul 2022 20:20:57 +0200 Subject: [PATCH 018/174] use Hook.FromAddress() instead of new Hook() --- PlayerTags/GameInterface/Nameplates/Nameplate.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/GameInterface/Nameplates/Nameplate.cs b/PlayerTags/GameInterface/Nameplates/Nameplate.cs index ecd3add..f1013c4 100644 --- a/PlayerTags/GameInterface/Nameplates/Nameplate.cs +++ b/PlayerTags/GameInterface/Nameplates/Nameplate.cs @@ -67,7 +67,7 @@ public Nameplate() if (m_PluginAddressResolver.SetPlayerNameplatePtr.HasValue) { - m_SetPlayerNameplateHook = new Hook(m_PluginAddressResolver.SetPlayerNameplatePtr.Value, new SetPlayerNameplateDelegate_Unmanaged(SetPlayerNameplateDetour)); + m_SetPlayerNameplateHook = Hook.FromAddress(m_PluginAddressResolver.SetPlayerNameplatePtr.Value, new SetPlayerNameplateDelegate_Unmanaged(SetPlayerNameplateDetour)); m_SetPlayerNameplateHook?.Enable(); } } From 3ea1f8f89558d62e1161d19cdcf3e1f12899bfb6 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 14 Jul 2022 11:15:36 +0200 Subject: [PATCH 019/174] use PluginInterface.AssemblyLocation & move paths to resource file --- PlayerTags/MyPaths.cs | 33 +++++++ PlayerTags/PlayerTags.csproj | 9 ++ PlayerTags/RandomNameGenerator.cs | 11 +-- PlayerTags/Resources/Paths.Designer.cs | 81 ++++++++++++++++ PlayerTags/Resources/Paths.resx | 126 +++++++++++++++++++++++++ 5 files changed, 251 insertions(+), 9 deletions(-) create mode 100644 PlayerTags/MyPaths.cs create mode 100644 PlayerTags/Resources/Paths.Designer.cs create mode 100644 PlayerTags/Resources/Paths.resx diff --git a/PlayerTags/MyPaths.cs b/PlayerTags/MyPaths.cs new file mode 100644 index 0000000..b5b88a1 --- /dev/null +++ b/PlayerTags/MyPaths.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PlayerTags +{ + internal class MyPaths + { + private static string? _PluginDirectoryPath = null; + + public static string PluginDirectoryPath + { + get + { + if (_PluginDirectoryPath is null) + { + var path = Path.GetDirectoryName(PluginServices.DalamudPluginInterface.AssemblyLocation.FullName); + if (path is null) + _PluginDirectoryPath = string.Empty; + else + _PluginDirectoryPath = path; + } + return _PluginDirectoryPath; + } + } + + public static string ResourcePath + => Path.Combine(PluginDirectoryPath, "Resources"); + } +} diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index fb3f3b2..b543362 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -53,6 +53,11 @@
+ + True + True + Paths.resx + True True @@ -61,6 +66,10 @@ + + ResXFileCodeGenerator + Paths.Designer.cs + PublicResXFileCodeGenerator Strings.Designer.cs diff --git a/PlayerTags/RandomNameGenerator.cs b/PlayerTags/RandomNameGenerator.cs index 384548d..54bebfb 100644 --- a/PlayerTags/RandomNameGenerator.cs +++ b/PlayerTags/RandomNameGenerator.cs @@ -11,12 +11,6 @@ namespace PlayerTags /// public static class RandomNameGenerator { - private static string? PluginDirectory - { - get { return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } - } - - private const string c_AdjectivesPath = "Resources/Words/Adjectives.txt"; private static string[]? s_Adjectives; private static string[] Adjectives { @@ -26,7 +20,7 @@ private static string[] Adjectives { try { - s_Adjectives = File.ReadAllLines($"{PluginDirectory}/{c_AdjectivesPath}"); + s_Adjectives = File.ReadAllLines(Path.Combine(MyPaths.ResourcePath, Resources.Paths.AdjectivesTxt)); } catch (Exception ex) { @@ -43,7 +37,6 @@ private static string[] Adjectives } } - private const string c_NounsPath = "Resources/Words/Nouns.txt"; private static string[]? s_Nouns; private static string[] Nouns { @@ -53,7 +46,7 @@ private static string[] Nouns { try { - s_Nouns = File.ReadAllLines($"{PluginDirectory}/{c_NounsPath}"); + s_Nouns = File.ReadAllLines(Path.Combine(MyPaths.ResourcePath, Resources.Paths.NounsTxt)); } catch (Exception ex) { diff --git a/PlayerTags/Resources/Paths.Designer.cs b/PlayerTags/Resources/Paths.Designer.cs new file mode 100644 index 0000000..d9d57ae --- /dev/null +++ b/PlayerTags/Resources/Paths.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace PlayerTags.Resources { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // 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()] + internal class Paths { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Paths() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PlayerTags.Resources.Paths", typeof(Paths).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Ü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)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Words/Adjectives.txt ähnelt. + /// + internal static string AdjectivesTxt { + get { + return ResourceManager.GetString("AdjectivesTxt", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Words/Nouns.txt ähnelt. + /// + internal static string NounsTxt { + get { + return ResourceManager.GetString("NounsTxt", resourceCulture); + } + } + } +} diff --git a/PlayerTags/Resources/Paths.resx b/PlayerTags/Resources/Paths.resx new file mode 100644 index 0000000..2de3cc2 --- /dev/null +++ b/PlayerTags/Resources/Paths.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Words/Adjectives.txt + + + Words/Nouns.txt + + \ No newline at end of file From 8472e5cf9eb755ecd070f034c242ff1c11683263 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 14 Jul 2022 20:49:59 +0200 Subject: [PATCH 020/174] change version to v1.4 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index b543362..cdf9cb8 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.3.0.0 + 1.4.0.0 From 25103c0790579929c17b46ff7437d0ff86aedf1c Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 2 Aug 2022 11:22:23 +0200 Subject: [PATCH 021/174] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fdf3833..a897243 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Feel free to open a pull request with your enhancements or bug fixes! # Translation You want to help and translate this plugin to your/other language(s)? \ -Start translation [here on Transifex](https://www.transifex.com/pilzinsel64/playertags)! +Start translation [here on Crowdin](https://crwd.in/playertags)! If you want to contribute to a language that isn't listed, just tell me with an Issue or on goat's Discord Server (yes, feel free to ping me). ^^ From c35e4e4c055519ec0d674b9ee9037b4654c106fd Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 6 Aug 2022 19:31:38 +0200 Subject: [PATCH 022/174] Add how to combine with PartyIcons --- .../Documentation/How To: Combine with PartyIcons.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 PlayerTags/Documentation/How To: Combine with PartyIcons.md diff --git a/PlayerTags/Documentation/How To: Combine with PartyIcons.md b/PlayerTags/Documentation/How To: Combine with PartyIcons.md new file mode 100644 index 0000000..168577d --- /dev/null +++ b/PlayerTags/Documentation/How To: Combine with PartyIcons.md @@ -0,0 +1,12 @@ +# How To: Combine with PartyIcons + +If you want to integrate the job icon to the nameplate, that is pretty simple. +Instead of re-implementing the whole part of the feature from PartyIcons, I dicided to make a simple description. + +## Configuration +1. Install the Dalamud Plugin "PartyIcons" +2. Open the configuration of PartyIcons and switch to the tab "Nameplates". Set everything marked with the red area to this and ensure to not have coloring enabled. +![grafik](https://user-images.githubusercontent.com/23138465/183259547-9d6d247a-a2b6-4cca-b86e-d2f576dd498e.png) + +## In-game screenshot +![grafik](https://user-images.githubusercontent.com/23138465/183259636-e868b1a9-7b03-4a2c-b851-6559d5b52c59.png) From 95d36c1a1841923f9e63e3e914b4ed19fda73a93 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 24 Aug 2022 10:26:36 +0200 Subject: [PATCH 023/174] disable NULL value warnings --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index cdf9cb8..b872a9f 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -7,7 +7,7 @@ net5.0-windows7 x64 - enable + annotations latest true false From f810dea85d290723a5a4b40781b8620a35d545a4 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 24 Aug 2022 10:26:53 +0200 Subject: [PATCH 024/174] target .NET 6 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index b872a9f..7e0f145 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -5,7 +5,7 @@ - net5.0-windows7 + net6.0-windows7.0 x64 annotations latest From 3a11764afbd4adbd8e7bf40b4c246650ef94d7db Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 24 Aug 2022 10:27:55 +0200 Subject: [PATCH 025/174] update NuGet packages --- PlayerTags/PlayerTags.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 7e0f145..af8e1a5 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -20,8 +20,8 @@ - - + + $(DalamudLibPath)FFXIVClientStructs.dll false From 69a0bd51ead4f082665ae241a596dc77b2dc618a Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 24 Aug 2022 10:28:51 +0200 Subject: [PATCH 026/174] use new DalamudContextMenu instead of DalamudContextMenuBase --- PlayerTags/Features/CustomTagsContextMenuFeature.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PlayerTags/Features/CustomTagsContextMenuFeature.cs b/PlayerTags/Features/CustomTagsContextMenuFeature.cs index afea808..dbfb362 100644 --- a/PlayerTags/Features/CustomTagsContextMenuFeature.cs +++ b/PlayerTags/Features/CustomTagsContextMenuFeature.cs @@ -33,22 +33,22 @@ public class CustomTagsContextMenuFeature : IDisposable private PluginConfiguration m_PluginConfiguration; private PluginData m_PluginData; - private DalamudContextMenuBase? m_ContextMenu; + private DalamudContextMenu? m_ContextMenu; public CustomTagsContextMenuFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) { m_PluginConfiguration = pluginConfiguration; m_PluginData = pluginData; - m_ContextMenu = new DalamudContextMenuBase(); - m_ContextMenu.Functions.ContextMenu.OnOpenGameObjectContextMenu += ContextMenuHooks_ContextMenuOpened; + m_ContextMenu = new DalamudContextMenu(); + m_ContextMenu.OnOpenGameObjectContextMenu += ContextMenuHooks_ContextMenuOpened; } public void Dispose() { if (m_ContextMenu != null) { - m_ContextMenu.Functions.ContextMenu.OnOpenGameObjectContextMenu -= ContextMenuHooks_ContextMenuOpened; + m_ContextMenu.OnOpenGameObjectContextMenu -= ContextMenuHooks_ContextMenuOpened; ((IDisposable)m_ContextMenu).Dispose(); m_ContextMenu = null; } From 9c76b29ede55a9bcef7acf4fe0ace08889d1f548 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 24 Aug 2022 10:28:59 +0200 Subject: [PATCH 027/174] change version to v1.5 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index af8e1a5..9881818 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.4.0.0 + 1.5.0.0 From a033ee618218ce431940d36cafac2432a4deea5d Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 24 Aug 2022 10:38:47 +0200 Subject: [PATCH 028/174] Fix naming of how to documentation --- ...ine with PartyIcons.md => How To - Combine with PartyIcons.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename PlayerTags/Documentation/{How To: Combine with PartyIcons.md => How To - Combine with PartyIcons.md} (100%) diff --git a/PlayerTags/Documentation/How To: Combine with PartyIcons.md b/PlayerTags/Documentation/How To - Combine with PartyIcons.md similarity index 100% rename from PlayerTags/Documentation/How To: Combine with PartyIcons.md rename to PlayerTags/Documentation/How To - Combine with PartyIcons.md From 306d7f12a0d12383c33f40ce5822ab3bb7f1878c Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 24 Aug 2022 11:07:47 +0200 Subject: [PATCH 029/174] prepair project for api7 branche --- PlayerTags/PlayerTags.csproj | 4 ++++ PlayerTags/packages.lock.json | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 PlayerTags/packages.lock.json diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 9881818..49616d9 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -14,6 +14,10 @@ false $(AppData)\XIVLauncher\devPlugins\PlayerTags\ + + + true + $(appdata)\XIVLauncher\addon\Hooks\dev\ diff --git a/PlayerTags/packages.lock.json b/PlayerTags/packages.lock.json new file mode 100644 index 0000000..abf5900 --- /dev/null +++ b/PlayerTags/packages.lock.json @@ -0,0 +1,19 @@ +{ + "version": 1, + "dependencies": { + "net6.0-windows7.0": { + "Dalamud.ContextMenu": { + "type": "Direct", + "requested": "[1.2.1, )", + "resolved": "1.2.1", + "contentHash": "RiBkn1OYRTnVbfUGYolLBE8MOeXjok+JiZaryb27oGa7YARCTu0XgUzkRiCglujknsHOn5kAaXsT3TUJmqMigg==" + }, + "DalamudPackager": { + "type": "Direct", + "requested": "[2.1.8, )", + "resolved": "2.1.8", + "contentHash": "YqagNXs9InxmqkXzq7kLveImxnodkBEicAhydMXVp7dFjC7xb76U6zGgAax4/BWIWfZeWzr5DJyQSev31kj81A==" + } + } + } +} \ No newline at end of file From 0be77a25d7d5da69b86a3fa17bcc325abb35a887 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 24 Aug 2022 11:56:02 +0200 Subject: [PATCH 030/174] minor fixes --- PlayerTags/Data/PluginData.cs | 1 - PlayerTags/PlayerTags.csproj | 2 +- PlayerTags/PluginServices.cs | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/PlayerTags/Data/PluginData.cs b/PlayerTags/Data/PluginData.cs index de76ea9..50df87d 100644 --- a/PlayerTags/Data/PluginData.cs +++ b/PlayerTags/Data/PluginData.cs @@ -1,7 +1,6 @@ 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; using Dalamud.Logging; using PlayerTags.Configuration; diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 49616d9..4dce414 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -12,11 +12,11 @@ true false false - $(AppData)\XIVLauncher\devPlugins\PlayerTags\ true + true diff --git a/PlayerTags/PluginServices.cs b/PlayerTags/PluginServices.cs index 36902ee..7728766 100644 --- a/PlayerTags/PluginServices.cs +++ b/PlayerTags/PluginServices.cs @@ -5,7 +5,6 @@ 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 86e8d2d519443b1abe6234d40c24c5479c420d60 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 29 Aug 2022 20:19:03 +0200 Subject: [PATCH 031/174] use seperated ActivityContextManager class & pre-pair testing stuff for fixing group member number and name location --- PlayerTags/Data/ActivityContextManager.cs | 50 ++++++++++++++++++++ PlayerTags/Features/LinkSelfInChatFeature.cs | 25 +++++++--- PlayerTags/Features/TagTargetFeature.cs | 33 ++----------- 3 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 PlayerTags/Data/ActivityContextManager.cs diff --git a/PlayerTags/Data/ActivityContextManager.cs b/PlayerTags/Data/ActivityContextManager.cs new file mode 100644 index 0000000..2225db0 --- /dev/null +++ b/PlayerTags/Data/ActivityContextManager.cs @@ -0,0 +1,50 @@ +using Dalamud.Plugin; +using Lumina.Excel.GeneratedSheets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PlayerTags.Data +{ + public class ActivityContextManager : IDisposable + { + private ActivityContext m_CurrentActivityContext; + + public ActivityContext CurrentActivityContext => m_CurrentActivityContext; + + public ActivityContextManager() + { + m_CurrentActivityContext = ActivityContext.None; + PluginServices.ClientState.TerritoryChanged += ClientState_TerritoryChanged; + } + + private void ClientState_TerritoryChanged(object? sender, ushort e) + { + m_CurrentActivityContext = ActivityContext.None; + + var contentFinderConditionsSheet = PluginServices.DataManager.GameData.GetExcelSheet(); + if (contentFinderConditionsSheet != null) + { + var foundContentFinderCondition = contentFinderConditionsSheet.FirstOrDefault(contentFinderCondition => contentFinderCondition.TerritoryType.Row == PluginServices.ClientState.TerritoryType); + if (foundContentFinderCondition != null) + { + if (foundContentFinderCondition.PvP) + { + m_CurrentActivityContext = ActivityContext.PvpDuty; + } + else + { + m_CurrentActivityContext = ActivityContext.PveDuty; + } + } + } + } + + public void Dispose() + { + PluginServices.ClientState.TerritoryChanged -= ClientState_TerritoryChanged; + } + } +} diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs index ad9e0af..c3f146e 100644 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ b/PlayerTags/Features/LinkSelfInChatFeature.cs @@ -12,11 +12,13 @@ public class LinkSelfInChatFeature : IDisposable { private PluginConfiguration m_PluginConfiguration; private PluginData m_PluginData; + private ActivityContextManager activityContextManager; public LinkSelfInChatFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) { m_PluginConfiguration = pluginConfiguration; m_PluginData = pluginData; + activityContextManager = new(); PluginServices.ChatGui.ChatMessage += Chat_ChatMessage; } @@ -24,6 +26,7 @@ public LinkSelfInChatFeature(PluginConfiguration pluginConfiguration, PluginData public void Dispose() { PluginServices.ChatGui.ChatMessage -= Chat_ChatMessage; + activityContextManager.Dispose(); } private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) @@ -58,21 +61,31 @@ private void ParsePayloads(SeString seString) else { var textMatchIndex = textPayload.Text.IndexOf(playerName); + while (textMatchIndex >= 0) { var textPayloadIndex = seString.Payloads.IndexOf(payload); // Chop text to the left and insert it as a new payload - if (textMatchIndex > 0) + if (textMatchIndex > 0) // textMatchIndex > 1 TODO: Find out, why this does the correct thing but doesn't let process the name correctly. { - seString.Payloads.Insert(textPayloadIndex, new TextPayload(textPayload.Text.Substring(0, textMatchIndex))); + var indexToUser = textMatchIndex; + + // TODO: Find out, why this does the correct thing but doesn't let process the name correctly. + //if (indexToUser == 1 && activityContextManager.CurrentActivityContext != ActivityContext.None) + // indexToUser--; + + seString.Payloads.Insert(textPayloadIndex, new TextPayload(textPayload.Text.Substring(0, indexToUser))); // Remove from the chopped text from the original payload - textPayload.Text = textPayload.Text.Substring(textMatchIndex, textPayload.Text.Length - textMatchIndex); + textPayload.Text = textPayload.Text.Substring(indexToUser, textPayload.Text.Length - textMatchIndex); } + // TODO: Find out, why this does the correct thing but doesn't let process the name correctly. + var textPayloadTextLenghOffset = /*textMatchIndex == 1 ? 1 :*/ 0; + // This is the last reference to the local player in this payload - if (textPayload.Text.Length == playerName.Length) + if (textPayload.Text.Length == playerName.Length + textPayloadTextLenghOffset) { playerTextPayloads.Add(textPayload); break; @@ -84,7 +97,7 @@ private void ParsePayloads(SeString seString) seString.Payloads.Insert(textPayloadIndex, playerTextPayload); // Remove from the chopped text from the original payload - textPayload.Text = textPayload.Text.Substring(0, playerName.Length); + textPayload.Text = textPayload.Text.Substring(0, playerName.Length + textPayloadTextLenghOffset); textMatchIndex = textPayload.Text.IndexOf(playerName); } @@ -100,7 +113,7 @@ private void ParsePayloads(SeString seString) //seString.Payloads.Insert(seString.Payloads.IndexOf(playerTextPayload), playerPayload); // For now, don't follow up with a text payload. Only use a player payload. - var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); + var playerPayload = new PlayerPayload(playerTextPayload.Text, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); seString.Payloads.Insert(seString.Payloads.IndexOf(playerTextPayload), playerPayload); seString.Payloads.Remove(playerTextPayload); } diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index 1771f84..0e49fcc 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -15,50 +15,25 @@ namespace PlayerTags.Features /// public abstract class TagTargetFeature : IDisposable { - private ActivityContext m_CurrentActivityContext; + public ActivityContextManager ActivityContextManager { get; init; } public TagTargetFeature() { - - m_CurrentActivityContext = ActivityContext.None; - - PluginServices.ClientState.TerritoryChanged += ClientState_TerritoryChanged; + ActivityContextManager = new(); } public virtual void Dispose() { - PluginServices.ClientState.TerritoryChanged -= ClientState_TerritoryChanged; + ActivityContextManager.Dispose(); } protected abstract bool IsIconVisible(Tag tag); protected abstract bool IsTextVisible(Tag tag); - private void ClientState_TerritoryChanged(object? sender, ushort e) - { - m_CurrentActivityContext = ActivityContext.None; - - var contentFinderConditionsSheet = PluginServices.DataManager.GameData.GetExcelSheet(); - if (contentFinderConditionsSheet != null) - { - var foundContentFinderCondition = contentFinderConditionsSheet.FirstOrDefault(contentFinderCondition => contentFinderCondition.TerritoryType.Row == PluginServices.ClientState.TerritoryType); - if (foundContentFinderCondition != null) - { - if (foundContentFinderCondition.PvP) - { - m_CurrentActivityContext = ActivityContext.PvpDuty; - } - else - { - m_CurrentActivityContext = ActivityContext.PveDuty; - } - } - } - } - protected bool IsTagVisible(Tag tag, GameObject? gameObject) { - bool isVisibleForActivity = ActivityContextHelper.GetIsVisible(m_CurrentActivityContext, + bool isVisibleForActivity = ActivityContextHelper.GetIsVisible(ActivityContextManager.CurrentActivityContext, tag.IsVisibleInPveDuties.InheritedValue ?? false, tag.IsVisibleInPvpDuties.InheritedValue ?? false, tag.IsVisibleInOverworld.InheritedValue ?? false); From 499d3c14efbab6f20d0d3f567d447f7337ba0821 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 1 Sep 2022 13:59:40 +0200 Subject: [PATCH 032/174] revert any self linking chat fix changes --- PlayerTags/Features/LinkSelfInChatFeature.cs | 23 +++++--------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs index c3f146e..e5dbeaf 100644 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ b/PlayerTags/Features/LinkSelfInChatFeature.cs @@ -67,25 +67,17 @@ private void ParsePayloads(SeString seString) var textPayloadIndex = seString.Payloads.IndexOf(payload); // Chop text to the left and insert it as a new payload - if (textMatchIndex > 0) // textMatchIndex > 1 TODO: Find out, why this does the correct thing but doesn't let process the name correctly. + if (textMatchIndex > 0) { - var indexToUser = textMatchIndex; - - // TODO: Find out, why this does the correct thing but doesn't let process the name correctly. - //if (indexToUser == 1 && activityContextManager.CurrentActivityContext != ActivityContext.None) - // indexToUser--; - - seString.Payloads.Insert(textPayloadIndex, new TextPayload(textPayload.Text.Substring(0, indexToUser))); + // Add the content before the player + seString.Payloads.Insert(textPayloadIndex, new TextPayload(textPayload.Text.Substring(0, textMatchIndex))); // Remove from the chopped text from the original payload - textPayload.Text = textPayload.Text.Substring(indexToUser, textPayload.Text.Length - textMatchIndex); + textPayload.Text = textPayload.Text.Substring(textMatchIndex, textPayload.Text.Length - textMatchIndex); } - // TODO: Find out, why this does the correct thing but doesn't let process the name correctly. - var textPayloadTextLenghOffset = /*textMatchIndex == 1 ? 1 :*/ 0; - // This is the last reference to the local player in this payload - if (textPayload.Text.Length == playerName.Length + textPayloadTextLenghOffset) + if (textPayload.Text.Length == playerName.Length) { playerTextPayloads.Add(textPayload); break; @@ -97,7 +89,7 @@ private void ParsePayloads(SeString seString) seString.Payloads.Insert(textPayloadIndex, playerTextPayload); // Remove from the chopped text from the original payload - textPayload.Text = textPayload.Text.Substring(0, playerName.Length + textPayloadTextLenghOffset); + textPayload.Text = textPayload.Text.Substring(0, playerName.Length); textMatchIndex = textPayload.Text.IndexOf(playerName); } @@ -109,9 +101,6 @@ private void ParsePayloads(SeString seString) // Typically when you receive a player payload followed by a text payload, it displays the text // and links it with the player payload. When trying to make one of these manually, it displays the player payload separately, // effectively doubling up the player name. - //var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); - //seString.Payloads.Insert(seString.Payloads.IndexOf(playerTextPayload), playerPayload); - // For now, don't follow up with a text payload. Only use a player payload. var playerPayload = new PlayerPayload(playerTextPayload.Text, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); seString.Payloads.Insert(seString.Payloads.IndexOf(playerTextPayload), playerPayload); From c3ddd0546bec9439136fa4058475c98ce2cbbccc Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 1 Sep 2022 19:43:57 +0200 Subject: [PATCH 033/174] revert last changes --- PlayerTags/Features/LinkSelfInChatFeature.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs index e5dbeaf..3ff938a 100644 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ b/PlayerTags/Features/LinkSelfInChatFeature.cs @@ -102,7 +102,7 @@ private void ParsePayloads(SeString seString) // and links it with the player payload. When trying to make one of these manually, it displays the player payload separately, // effectively doubling up the player name. // For now, don't follow up with a text payload. Only use a player payload. - var playerPayload = new PlayerPayload(playerTextPayload.Text, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); + var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); seString.Payloads.Insert(seString.Payloads.IndexOf(playerTextPayload), playerPayload); seString.Payloads.Remove(playerTextPayload); } From 7a37aa6de730a1dcb4707e6a856556f4a7c3f6b8 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 2 Sep 2022 13:28:21 +0200 Subject: [PATCH 034/174] add backend possiblity to define general settings per ActivityContext & polish up the code a bit --- .../Configuration/PluginConfiguration.cs | 66 +++++++++++++++++-- .../Configuration/PluginConfigurationUI.cs | 44 +++++++++++-- .../Data/NameplateFreeCompanyVisibility.cs | 5 +- PlayerTags/Data/NameplateTitlePosition.cs | 5 +- PlayerTags/Data/NameplateTitleVisibility.cs | 5 +- 5 files changed, 114 insertions(+), 11 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index ac0998c..288d169 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -12,11 +12,69 @@ namespace PlayerTags.Configuration public class PluginConfiguration : IPluginConfiguration { public int Version { get; set; } = 0; - public bool IsVisible = false; - public NameplateFreeCompanyVisibility NameplateFreeCompanyVisibility = NameplateFreeCompanyVisibility.Default; - public NameplateTitleVisibility NameplateTitleVisibility = NameplateTitleVisibility.WhenHasTags; - public NameplateTitlePosition NameplateTitlePosition = NameplateTitlePosition.AlwaysAboveName; + + private const NameplateFreeCompanyVisibility DefaultNameplateFreeCompanyVisibility = Data.NameplateFreeCompanyVisibility.Default; + private const NameplateTitleVisibility DefaultNameplateTitleVisibility = Data.NameplateTitleVisibility.WhenHasTags; + private const NameplateTitlePosition DefaultNameplateTitlePosition = Data.NameplateTitlePosition.AlwaysAboveName; + + [JsonProperty("NameplateFreeCompanyVisibilityV2")] + public Dictionary NameplateFreeCompanyVisibility = new Dictionary() + { + { ActivityContext.None, DefaultNameplateFreeCompanyVisibility }, + { ActivityContext.PveDuty, DefaultNameplateFreeCompanyVisibility }, + { ActivityContext.PvpDuty, DefaultNameplateFreeCompanyVisibility } + }; + [JsonProperty("NameplateTitleVisibilityV2")] + public Dictionary NameplateTitleVisibility = new Dictionary() + { + { ActivityContext.None, DefaultNameplateTitleVisibility }, + { ActivityContext.PveDuty, DefaultNameplateTitleVisibility }, + { ActivityContext.PvpDuty, DefaultNameplateTitleVisibility } + }; + [JsonProperty("NameplateTitlePositionV2")] + public Dictionary NameplateTitlePosition = new Dictionary() + { + { ActivityContext.None, DefaultNameplateTitlePosition }, + { ActivityContext.PveDuty, DefaultNameplateTitlePosition }, + { ActivityContext.PvpDuty, DefaultNameplateTitlePosition } + }; + + #region Obsulate Properties + + [JsonProperty("NameplateFreeCompanyVisibility"), Obsolete] + private NameplateFreeCompanyVisibility NameplateFreeCompanyVisibilityV1 + { + set + { + NameplateFreeCompanyVisibility[ActivityContext.None] = value; + NameplateFreeCompanyVisibility[ActivityContext.PveDuty] = value; + NameplateFreeCompanyVisibility[ActivityContext.PvpDuty] = value; + } + } + [JsonProperty("NameplateTitleVisibility"), Obsolete] + public NameplateTitleVisibility NameplateTitleVisibilityV1 + { + set + { + NameplateTitleVisibility[ActivityContext.None] = value; + NameplateTitleVisibility[ActivityContext.PveDuty] = value; + NameplateTitleVisibility[ActivityContext.PvpDuty] = value; + } + } + [JsonProperty("NameplateTitlePosition"), Obsolete] + public NameplateTitlePosition NameplateTitlePositionV1 + { + set + { + NameplateTitlePosition[ActivityContext.None] = value; + NameplateTitlePosition[ActivityContext.PveDuty] = value; + NameplateTitlePosition[ActivityContext.PvpDuty] = value; + } + } + + #endregion + public bool IsPlayerNameRandomlyGenerated = false; public bool IsCustomTagsContextMenuEnabled = true; public bool IsShowInheritedPropertiesEnabled = true; diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index c25073c..f5e3a10 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -1,4 +1,5 @@ -using Dalamud.Game.ClientState.Objects.SubKinds; +using Dalamud.Configuration; +using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Interface; using Dalamud.Logging; @@ -25,6 +26,7 @@ private struct PlayerInfo private PluginConfiguration m_PluginConfiguration; private PluginData m_PluginData; + private PropertyProxy propertyProxy; private InheritableValue? m_ColorPickerPopupDataContext; @@ -32,6 +34,7 @@ public PluginConfigurationUI(PluginConfiguration config, PluginData pluginData) { m_PluginConfiguration = config; m_PluginData = pluginData; + propertyProxy = new PropertyProxy(config); } public void Draw() @@ -63,9 +66,9 @@ public void Draw() ImGui.Spacing(); ImGui.Spacing(); DrawHeading(Strings.Loc_Static_Nameplates); - DrawComboBox(true, true, false, ref m_PluginConfiguration.NameplateFreeCompanyVisibility, () => m_PluginConfiguration.Save(m_PluginData)); - DrawComboBox(true, true, false, ref m_PluginConfiguration.NameplateTitleVisibility, () => m_PluginConfiguration.Save(m_PluginData)); - DrawComboBox(true, true, false, ref m_PluginConfiguration.NameplateTitlePosition, () => m_PluginConfiguration.Save(m_PluginData)); + DrawComboBox(true, true, false, ref propertyProxy.NameplateFreeCompanyVisibility, () => m_PluginConfiguration.Save(m_PluginData)); + DrawComboBox(true, true, false, ref propertyProxy.NameplateTitleVisibility, () => m_PluginConfiguration.Save(m_PluginData)); + DrawComboBox(true, true, false, ref propertyProxy.NameplateTitlePosition, () => m_PluginConfiguration.Save(m_PluginData)); ImGui.Spacing(); @@ -1159,5 +1162,38 @@ private void DrawUIColorPicker(System.Action colorSelected) currentColumn++; } } + + private class PropertyProxy + { + private PluginConfiguration pluginConfig; + + public NameplateFreeCompanyVisibility NameplateFreeCompanyVisibility; + public NameplateTitleVisibility NameplateTitleVisibility; + public NameplateTitlePosition NameplateTitlePosition; + + public PropertyProxy(PluginConfiguration config) + { + pluginConfig = config; + } + + public void LoadData() + { + NameplateFreeCompanyVisibility = pluginConfig.NameplateFreeCompanyVisibility[ActivityContext.None]; + NameplateTitleVisibility = pluginConfig.NameplateTitleVisibility[ActivityContext.None]; + NameplateTitlePosition = pluginConfig.NameplateTitlePosition[ActivityContext.None]; + } + + public void SaveData() + { + foreach (var key in pluginConfig.NameplateFreeCompanyVisibility.Keys) + pluginConfig.NameplateFreeCompanyVisibility[key] = NameplateFreeCompanyVisibility; + + foreach (var key in pluginConfig.NameplateTitleVisibility.Keys) + pluginConfig.NameplateTitleVisibility[key] = NameplateTitleVisibility; + + foreach (var key in pluginConfig.NameplateTitlePosition.Keys) + pluginConfig.NameplateTitlePosition[key] = NameplateTitlePosition; + } + } } } diff --git a/PlayerTags/Data/NameplateFreeCompanyVisibility.cs b/PlayerTags/Data/NameplateFreeCompanyVisibility.cs index 9f00b2d..6308f8c 100644 --- a/PlayerTags/Data/NameplateFreeCompanyVisibility.cs +++ b/PlayerTags/Data/NameplateFreeCompanyVisibility.cs @@ -1,5 +1,8 @@ -namespace PlayerTags.Data +using Newtonsoft.Json; + +namespace PlayerTags.Data { + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum NameplateFreeCompanyVisibility { Default, diff --git a/PlayerTags/Data/NameplateTitlePosition.cs b/PlayerTags/Data/NameplateTitlePosition.cs index 7c8613e..08052d8 100644 --- a/PlayerTags/Data/NameplateTitlePosition.cs +++ b/PlayerTags/Data/NameplateTitlePosition.cs @@ -1,5 +1,8 @@ -namespace PlayerTags.Data +using Newtonsoft.Json; + +namespace PlayerTags.Data { + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum NameplateTitlePosition { Default, diff --git a/PlayerTags/Data/NameplateTitleVisibility.cs b/PlayerTags/Data/NameplateTitleVisibility.cs index 0cba968..3914b47 100644 --- a/PlayerTags/Data/NameplateTitleVisibility.cs +++ b/PlayerTags/Data/NameplateTitleVisibility.cs @@ -1,5 +1,8 @@ -namespace PlayerTags.Data +using Newtonsoft.Json; + +namespace PlayerTags.Data { + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum NameplateTitleVisibility { Default, From 3dc7e93f0813990fa00a381c47673a4a903ca3a3 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 2 Sep 2022 13:28:21 +0200 Subject: [PATCH 035/174] add backend possiblity to define general settings per ActivityContext & polish up the code a bit --- .../Configuration/PluginConfiguration.cs | 66 +++++++- .../Configuration/PluginConfigurationUI.cs | 44 +++++- .../Data/NameplateFreeCompanyVisibility.cs | 5 +- PlayerTags/Data/NameplateTitlePosition.cs | 5 +- PlayerTags/Data/NameplateTitleVisibility.cs | 5 +- .../Features/NameplateTagTargetFeature.cs | 148 +++++------------- 6 files changed, 156 insertions(+), 117 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index ac0998c..288d169 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -12,11 +12,69 @@ namespace PlayerTags.Configuration public class PluginConfiguration : IPluginConfiguration { public int Version { get; set; } = 0; - public bool IsVisible = false; - public NameplateFreeCompanyVisibility NameplateFreeCompanyVisibility = NameplateFreeCompanyVisibility.Default; - public NameplateTitleVisibility NameplateTitleVisibility = NameplateTitleVisibility.WhenHasTags; - public NameplateTitlePosition NameplateTitlePosition = NameplateTitlePosition.AlwaysAboveName; + + private const NameplateFreeCompanyVisibility DefaultNameplateFreeCompanyVisibility = Data.NameplateFreeCompanyVisibility.Default; + private const NameplateTitleVisibility DefaultNameplateTitleVisibility = Data.NameplateTitleVisibility.WhenHasTags; + private const NameplateTitlePosition DefaultNameplateTitlePosition = Data.NameplateTitlePosition.AlwaysAboveName; + + [JsonProperty("NameplateFreeCompanyVisibilityV2")] + public Dictionary NameplateFreeCompanyVisibility = new Dictionary() + { + { ActivityContext.None, DefaultNameplateFreeCompanyVisibility }, + { ActivityContext.PveDuty, DefaultNameplateFreeCompanyVisibility }, + { ActivityContext.PvpDuty, DefaultNameplateFreeCompanyVisibility } + }; + [JsonProperty("NameplateTitleVisibilityV2")] + public Dictionary NameplateTitleVisibility = new Dictionary() + { + { ActivityContext.None, DefaultNameplateTitleVisibility }, + { ActivityContext.PveDuty, DefaultNameplateTitleVisibility }, + { ActivityContext.PvpDuty, DefaultNameplateTitleVisibility } + }; + [JsonProperty("NameplateTitlePositionV2")] + public Dictionary NameplateTitlePosition = new Dictionary() + { + { ActivityContext.None, DefaultNameplateTitlePosition }, + { ActivityContext.PveDuty, DefaultNameplateTitlePosition }, + { ActivityContext.PvpDuty, DefaultNameplateTitlePosition } + }; + + #region Obsulate Properties + + [JsonProperty("NameplateFreeCompanyVisibility"), Obsolete] + private NameplateFreeCompanyVisibility NameplateFreeCompanyVisibilityV1 + { + set + { + NameplateFreeCompanyVisibility[ActivityContext.None] = value; + NameplateFreeCompanyVisibility[ActivityContext.PveDuty] = value; + NameplateFreeCompanyVisibility[ActivityContext.PvpDuty] = value; + } + } + [JsonProperty("NameplateTitleVisibility"), Obsolete] + public NameplateTitleVisibility NameplateTitleVisibilityV1 + { + set + { + NameplateTitleVisibility[ActivityContext.None] = value; + NameplateTitleVisibility[ActivityContext.PveDuty] = value; + NameplateTitleVisibility[ActivityContext.PvpDuty] = value; + } + } + [JsonProperty("NameplateTitlePosition"), Obsolete] + public NameplateTitlePosition NameplateTitlePositionV1 + { + set + { + NameplateTitlePosition[ActivityContext.None] = value; + NameplateTitlePosition[ActivityContext.PveDuty] = value; + NameplateTitlePosition[ActivityContext.PvpDuty] = value; + } + } + + #endregion + public bool IsPlayerNameRandomlyGenerated = false; public bool IsCustomTagsContextMenuEnabled = true; public bool IsShowInheritedPropertiesEnabled = true; diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index c25073c..f5e3a10 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -1,4 +1,5 @@ -using Dalamud.Game.ClientState.Objects.SubKinds; +using Dalamud.Configuration; +using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Interface; using Dalamud.Logging; @@ -25,6 +26,7 @@ private struct PlayerInfo private PluginConfiguration m_PluginConfiguration; private PluginData m_PluginData; + private PropertyProxy propertyProxy; private InheritableValue? m_ColorPickerPopupDataContext; @@ -32,6 +34,7 @@ public PluginConfigurationUI(PluginConfiguration config, PluginData pluginData) { m_PluginConfiguration = config; m_PluginData = pluginData; + propertyProxy = new PropertyProxy(config); } public void Draw() @@ -63,9 +66,9 @@ public void Draw() ImGui.Spacing(); ImGui.Spacing(); DrawHeading(Strings.Loc_Static_Nameplates); - DrawComboBox(true, true, false, ref m_PluginConfiguration.NameplateFreeCompanyVisibility, () => m_PluginConfiguration.Save(m_PluginData)); - DrawComboBox(true, true, false, ref m_PluginConfiguration.NameplateTitleVisibility, () => m_PluginConfiguration.Save(m_PluginData)); - DrawComboBox(true, true, false, ref m_PluginConfiguration.NameplateTitlePosition, () => m_PluginConfiguration.Save(m_PluginData)); + DrawComboBox(true, true, false, ref propertyProxy.NameplateFreeCompanyVisibility, () => m_PluginConfiguration.Save(m_PluginData)); + DrawComboBox(true, true, false, ref propertyProxy.NameplateTitleVisibility, () => m_PluginConfiguration.Save(m_PluginData)); + DrawComboBox(true, true, false, ref propertyProxy.NameplateTitlePosition, () => m_PluginConfiguration.Save(m_PluginData)); ImGui.Spacing(); @@ -1159,5 +1162,38 @@ private void DrawUIColorPicker(System.Action colorSelected) currentColumn++; } } + + private class PropertyProxy + { + private PluginConfiguration pluginConfig; + + public NameplateFreeCompanyVisibility NameplateFreeCompanyVisibility; + public NameplateTitleVisibility NameplateTitleVisibility; + public NameplateTitlePosition NameplateTitlePosition; + + public PropertyProxy(PluginConfiguration config) + { + pluginConfig = config; + } + + public void LoadData() + { + NameplateFreeCompanyVisibility = pluginConfig.NameplateFreeCompanyVisibility[ActivityContext.None]; + NameplateTitleVisibility = pluginConfig.NameplateTitleVisibility[ActivityContext.None]; + NameplateTitlePosition = pluginConfig.NameplateTitlePosition[ActivityContext.None]; + } + + public void SaveData() + { + foreach (var key in pluginConfig.NameplateFreeCompanyVisibility.Keys) + pluginConfig.NameplateFreeCompanyVisibility[key] = NameplateFreeCompanyVisibility; + + foreach (var key in pluginConfig.NameplateTitleVisibility.Keys) + pluginConfig.NameplateTitleVisibility[key] = NameplateTitleVisibility; + + foreach (var key in pluginConfig.NameplateTitlePosition.Keys) + pluginConfig.NameplateTitlePosition[key] = NameplateTitlePosition; + } + } } } diff --git a/PlayerTags/Data/NameplateFreeCompanyVisibility.cs b/PlayerTags/Data/NameplateFreeCompanyVisibility.cs index 9f00b2d..6308f8c 100644 --- a/PlayerTags/Data/NameplateFreeCompanyVisibility.cs +++ b/PlayerTags/Data/NameplateFreeCompanyVisibility.cs @@ -1,5 +1,8 @@ -namespace PlayerTags.Data +using Newtonsoft.Json; + +namespace PlayerTags.Data { + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum NameplateFreeCompanyVisibility { Default, diff --git a/PlayerTags/Data/NameplateTitlePosition.cs b/PlayerTags/Data/NameplateTitlePosition.cs index 7c8613e..08052d8 100644 --- a/PlayerTags/Data/NameplateTitlePosition.cs +++ b/PlayerTags/Data/NameplateTitlePosition.cs @@ -1,5 +1,8 @@ -namespace PlayerTags.Data +using Newtonsoft.Json; + +namespace PlayerTags.Data { + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum NameplateTitlePosition { Default, diff --git a/PlayerTags/Data/NameplateTitleVisibility.cs b/PlayerTags/Data/NameplateTitleVisibility.cs index 0cba968..3914b47 100644 --- a/PlayerTags/Data/NameplateTitleVisibility.cs +++ b/PlayerTags/Data/NameplateTitleVisibility.cs @@ -1,5 +1,8 @@ -namespace PlayerTags.Data +using Newtonsoft.Json; + +namespace PlayerTags.Data { + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum NameplateTitleVisibility { Default, diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index 9de7908..6152244 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -2,9 +2,11 @@ using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; +using Lumina.Excel.GeneratedSheets; using PlayerTags.Configuration; using PlayerTags.Data; using PlayerTags.GameInterface.Nameplates; +using PlayerTags.Inheritables; using System; using System.Collections.Generic; using System.Linq; @@ -98,41 +100,25 @@ protected override bool IsTextVisible(Tag tag) private void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs args) { var beforeTitleBytes = args.Title.Encode(); - AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany/*, out isNameChanged, out isTitleChanged, out isFreeCompanyChanged*/); - - if (m_PluginConfiguration.NameplateTitlePosition == NameplateTitlePosition.AlwaysAboveName) - { + AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany); + + if (m_PluginConfiguration.NameplateTitlePosition[ActivityContextManager.CurrentActivityContext] == NameplateTitlePosition.AlwaysAboveName) args.IsTitleAboveName = true; - } - else if (m_PluginConfiguration.NameplateTitlePosition == NameplateTitlePosition.AlwaysBelowName) - { + else if (m_PluginConfiguration.NameplateTitlePosition[ActivityContextManager.CurrentActivityContext] == NameplateTitlePosition.AlwaysBelowName) args.IsTitleAboveName = false; - } - if (m_PluginConfiguration.NameplateTitleVisibility == NameplateTitleVisibility.Default) - { - } - else if (m_PluginConfiguration.NameplateTitleVisibility == NameplateTitleVisibility.Always) - { + if (m_PluginConfiguration.NameplateTitleVisibility[ActivityContextManager.CurrentActivityContext] == NameplateTitleVisibility.Always) args.IsTitleVisible = true; - } - else if (m_PluginConfiguration.NameplateTitleVisibility == NameplateTitleVisibility.Never) - { + else if (m_PluginConfiguration.NameplateTitleVisibility[ActivityContextManager.CurrentActivityContext] == NameplateTitleVisibility.Never) args.IsTitleVisible = false; - } - else if (m_PluginConfiguration.NameplateTitleVisibility == NameplateTitleVisibility.WhenHasTags) + else if (m_PluginConfiguration.NameplateTitleVisibility[ActivityContextManager.CurrentActivityContext] == NameplateTitleVisibility.WhenHasTags) { bool hasTitleChanged = !beforeTitleBytes.SequenceEqual(args.Title.Encode()); args.IsTitleVisible = hasTitleChanged; } - if (m_PluginConfiguration.NameplateFreeCompanyVisibility == NameplateFreeCompanyVisibility.Default) - { - } - else if (m_PluginConfiguration.NameplateFreeCompanyVisibility == NameplateFreeCompanyVisibility.Never) - { + if (m_PluginConfiguration.NameplateFreeCompanyVisibility[ActivityContextManager.CurrentActivityContext] == NameplateFreeCompanyVisibility.Never) args.FreeCompany.Payloads.Clear(); - } } /// @@ -174,13 +160,7 @@ private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString t if (playerCharacter.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter.ClassJob.GameData.Abbreviation, out var jobTag)) { if (jobTag.TagTargetInNameplates.InheritedValue != null && jobTag.TagPositionInNameplates.InheritedValue != null) - { - var payloads = GetPayloads(jobTag, gameObject); - if (payloads.Any()) - { - AddPayloadChanges(jobTag.TagTargetInNameplates.InheritedValue.Value, jobTag.TagPositionInNameplates.InheritedValue.Value, payloads, nameplateChanges); - } - } + checkTag(jobTag); } // Add the randomly generated name tag payload @@ -191,9 +171,7 @@ private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString t { var generatedName = RandomNameGenerator.Generate(characterName); if (generatedName != null) - { AddPayloadChanges(NameplateElement.Name, TagPosition.Replace, Enumerable.Empty().Append(new TextPayload(generatedName)), nameplateChanges); - } } } @@ -203,15 +181,16 @@ private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString t { var customTag = m_PluginData.CustomTags.FirstOrDefault(tag => tag.CustomId.Value == customTagId); if (customTag != null) + checkTag(customTag); + } + + void checkTag(Tag tag) + { + if (tag.TagTargetInNameplates.InheritedValue != null && tag.TagPositionInNameplates.InheritedValue != null) { - if (customTag.TagTargetInNameplates.InheritedValue != null && customTag.TagPositionInNameplates.InheritedValue != null) - { - var payloads = GetPayloads(customTag, gameObject); - if (payloads.Any()) - { - AddPayloadChanges(customTag.TagTargetInNameplates.InheritedValue.Value, customTag.TagPositionInNameplates.InheritedValue.Value, payloads, nameplateChanges); - } - } + var payloads = GetPayloads(tag, gameObject); + if (payloads.Any()) + AddPayloadChanges(tag.TagTargetInNameplates.InheritedValue.Value, tag.TagPositionInNameplates.InheritedValue.Value, payloads, nameplateChanges); } } } @@ -220,23 +199,16 @@ private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString t foreach ((var nameplateElement, var stringChanges) in nameplateChanges) { SeString? seString = null; + if (nameplateElement == NameplateElement.Name) - { seString = name; - } else if (nameplateElement == NameplateElement.Title) - { seString = title; - } else if (nameplateElement == NameplateElement.FreeCompany) - { seString = freeCompany; - } if (seString != null) - { ApplyStringChanges(seString, stringChanges); - } } if (gameObject is PlayerCharacter playerCharacter1) @@ -247,71 +219,35 @@ private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString t { var customTag = m_PluginData.CustomTags.FirstOrDefault(tag => tag.CustomId.Value == customTagId); if (customTag != null) - { - if (IsTagVisible(customTag, gameObject)) - { - if (customTag.TextColor.InheritedValue != null) - { - if (name.Payloads.Any(payload => payload is TextPayload) - && customTag.IsTextColorAppliedToNameplateName.InheritedValue != null - && customTag.IsTextColorAppliedToNameplateName.InheritedValue.Value) - { - name.Payloads.Insert(0, (new UIForegroundPayload(customTag.TextColor.InheritedValue.Value))); - name.Payloads.Add(new UIForegroundPayload(0)); - } - - if (title.Payloads.Any(payload => payload is TextPayload) - && customTag.IsTextColorAppliedToNameplateTitle.InheritedValue != null - && customTag.IsTextColorAppliedToNameplateTitle.InheritedValue.Value) - { - title.Payloads.Insert(0, (new UIForegroundPayload(customTag.TextColor.InheritedValue.Value))); - title.Payloads.Add(new UIForegroundPayload(0)); - } - - if (freeCompany.Payloads.Any(payload => payload is TextPayload) - && customTag.IsTextColorAppliedToNameplateFreeCompany.InheritedValue != null - && customTag.IsTextColorAppliedToNameplateFreeCompany.InheritedValue.Value) - { - freeCompany.Payloads.Insert(0, (new UIForegroundPayload(customTag.TextColor.InheritedValue.Value))); - freeCompany.Payloads.Add(new UIForegroundPayload(0)); - } - } - } - } + applyTextColor(customTag); } if (playerCharacter1.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter1.ClassJob.GameData.Abbreviation, out var jobTag)) + applyTextColor(jobTag); + + + void applyTextColor(Tag tag) { - if (IsTagVisible(jobTag, gameObject)) + if (IsTagVisible(tag, gameObject)) { - if (jobTag.TextColor.InheritedValue != null) + if (tag.TextColor.InheritedValue != null) { - if (name.Payloads.Any(payload => payload is TextPayload) - && jobTag.IsTextColorAppliedToNameplateName.InheritedValue != null - && jobTag.IsTextColorAppliedToNameplateName.InheritedValue.Value) - { - name.Payloads.Insert(0, (new UIForegroundPayload(jobTag.TextColor.InheritedValue.Value))); - name.Payloads.Add(new UIForegroundPayload(0)); - } - - if (title.Payloads.Any(payload => payload is TextPayload) - && jobTag.IsTextColorAppliedToNameplateTitle.InheritedValue != null - && jobTag.IsTextColorAppliedToNameplateTitle.InheritedValue.Value) - { - title.Payloads.Insert(0, (new UIForegroundPayload(jobTag.TextColor.InheritedValue.Value))); - title.Payloads.Add(new UIForegroundPayload(0)); - } - - if (freeCompany.Payloads.Any(payload => payload is TextPayload) - && jobTag.IsTextColorAppliedToNameplateFreeCompany.InheritedValue != null - && jobTag.IsTextColorAppliedToNameplateFreeCompany.InheritedValue.Value) - { - freeCompany.Payloads.Insert(0, (new UIForegroundPayload(jobTag.TextColor.InheritedValue.Value))); - freeCompany.Payloads.Add(new UIForegroundPayload(0)); - } + applyTextColor2(name, tag.IsTextColorAppliedToNameplateName, tag.TextColor); + applyTextColor2(title, tag.IsTextColorAppliedToNameplateTitle, tag.TextColor); + applyTextColor2(freeCompany, tag.IsTextColorAppliedToNameplateFreeCompany, tag.TextColor); } } - } + } + void applyTextColor2(SeString destPayload, InheritableValue enableFlag, InheritableValue colorValue) + { + if (destPayload.Payloads.Any(payload => payload is TextPayload) + && enableFlag.InheritedValue != null + && enableFlag.InheritedValue.Value) + { + destPayload.Payloads.Insert(0, (new UIForegroundPayload(colorValue.InheritedValue.Value))); + destPayload.Payloads.Add(new UIForegroundPayload(0)); + } + } } } } From 1c0564b3f4f5525d47b156d4acd541a38a7c7e96 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 2 Sep 2022 15:37:53 +0200 Subject: [PATCH 036/174] some more work moving settings around --- .../Configuration/PluginConfiguration.cs | 123 ++++++++++-------- .../Configuration/PluginConfigurationUI.cs | 97 ++++++++------ PlayerTags/Data/ActivityContext.cs | 4 +- PlayerTags/Features/ChatTagTargetFeature.cs | 2 +- PlayerTags/Features/LinkSelfInChatFeature.cs | 2 +- .../Features/NameplateTagTargetFeature.cs | 12 +- 6 files changed, 133 insertions(+), 107 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index 288d169..aa5e778 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -17,63 +17,14 @@ public class PluginConfiguration : IPluginConfiguration private const NameplateFreeCompanyVisibility DefaultNameplateFreeCompanyVisibility = Data.NameplateFreeCompanyVisibility.Default; private const NameplateTitleVisibility DefaultNameplateTitleVisibility = Data.NameplateTitleVisibility.WhenHasTags; private const NameplateTitlePosition DefaultNameplateTitlePosition = Data.NameplateTitlePosition.AlwaysAboveName; + private const bool DefaultIsApplyTagsToAllChatMessagesEnabled = true; - [JsonProperty("NameplateFreeCompanyVisibilityV2")] - public Dictionary NameplateFreeCompanyVisibility = new Dictionary() + public Dictionary GeneralOptions = new Dictionary() { - { ActivityContext.None, DefaultNameplateFreeCompanyVisibility }, - { ActivityContext.PveDuty, DefaultNameplateFreeCompanyVisibility }, - { ActivityContext.PvpDuty, DefaultNameplateFreeCompanyVisibility } + { ActivityContext.None, new GeneralOptionsClass() }, + { ActivityContext.PveDuty, new GeneralOptionsClass() }, + { ActivityContext.PvpDuty, new GeneralOptionsClass() } }; - [JsonProperty("NameplateTitleVisibilityV2")] - public Dictionary NameplateTitleVisibility = new Dictionary() - { - { ActivityContext.None, DefaultNameplateTitleVisibility }, - { ActivityContext.PveDuty, DefaultNameplateTitleVisibility }, - { ActivityContext.PvpDuty, DefaultNameplateTitleVisibility } - }; - [JsonProperty("NameplateTitlePositionV2")] - public Dictionary NameplateTitlePosition = new Dictionary() - { - { ActivityContext.None, DefaultNameplateTitlePosition }, - { ActivityContext.PveDuty, DefaultNameplateTitlePosition }, - { ActivityContext.PvpDuty, DefaultNameplateTitlePosition } - }; - - #region Obsulate Properties - - [JsonProperty("NameplateFreeCompanyVisibility"), Obsolete] - private NameplateFreeCompanyVisibility NameplateFreeCompanyVisibilityV1 - { - set - { - NameplateFreeCompanyVisibility[ActivityContext.None] = value; - NameplateFreeCompanyVisibility[ActivityContext.PveDuty] = value; - NameplateFreeCompanyVisibility[ActivityContext.PvpDuty] = value; - } - } - [JsonProperty("NameplateTitleVisibility"), Obsolete] - public NameplateTitleVisibility NameplateTitleVisibilityV1 - { - set - { - NameplateTitleVisibility[ActivityContext.None] = value; - NameplateTitleVisibility[ActivityContext.PveDuty] = value; - NameplateTitleVisibility[ActivityContext.PvpDuty] = value; - } - } - [JsonProperty("NameplateTitlePosition"), Obsolete] - public NameplateTitlePosition NameplateTitlePositionV1 - { - set - { - NameplateTitlePosition[ActivityContext.None] = value; - NameplateTitlePosition[ActivityContext.PveDuty] = value; - NameplateTitlePosition[ActivityContext.PvpDuty] = value; - } - } - - #endregion public bool IsPlayerNameRandomlyGenerated = false; public bool IsCustomTagsContextMenuEnabled = true; @@ -85,8 +36,6 @@ public NameplateTitlePosition NameplateTitlePositionV1 public bool IsPlayersTabAllianceVisible = true; public bool IsPlayersTabEnemiesVisible = true; public bool IsPlayersTabOthersVisible = false; - public bool IsLinkSelfInChatEnabled = false; - public bool IsApplyTagsToAllChatMessagesEnabled = true; [JsonProperty(TypeNameHandling = TypeNameHandling.None, ItemTypeNameHandling = TypeNameHandling.None)] public Dictionary AllTagsChanges = new Dictionary(); @@ -118,6 +67,58 @@ public NameplateTitlePosition NameplateTitlePositionV1 [JsonProperty(TypeNameHandling = TypeNameHandling.None, ItemTypeNameHandling = TypeNameHandling.None)] public List Identities = new List(); + #region Obsulate Properties + + [JsonProperty("NameplateFreeCompanyVisibility"), Obsolete] + private NameplateFreeCompanyVisibility NameplateFreeCompanyVisibilityV1 + { + set + { + foreach (var key in GeneralOptions.Keys) + GeneralOptions[key].NameplateFreeCompanyVisibility = value; + } + } + [JsonProperty("NameplateTitleVisibility"), Obsolete] + public NameplateTitleVisibility NameplateTitleVisibilityV1 + { + set + { + foreach (var key in GeneralOptions.Keys) + GeneralOptions[key].NameplateTitleVisibility = value; + } + } + [JsonProperty("NameplateTitlePosition"), Obsolete] + public NameplateTitlePosition NameplateTitlePositionV1 + { + set + { + foreach (var key in GeneralOptions.Keys) + GeneralOptions[key].NameplateTitlePosition = value; + } + } + + [JsonProperty("IsApplyTagsToAllChatMessagesEnabled"), Obsolete] + private bool IsApplyTagsToAllChatMessagesEnabledV1 + { + set + { + foreach (var key in GeneralOptions.Keys) + GeneralOptions[key].IsApplyTagsToAllChatMessagesEnabled = value; + } + } + + [JsonProperty("IsLinkSelfInChatEnabled"), Obsolete] + private bool IsLinkSelfInChatEnabledV1 + { + set + { + foreach (var key in GeneralOptions.Keys) + GeneralOptions[key].IsLinkSelfInChatEnabled = value; + } + } + + #endregion + public event System.Action? Saved; public void Save(PluginData pluginData) @@ -219,4 +220,14 @@ public void Save(PluginData pluginData) Saved?.Invoke(); } } + + public class GeneralOptionsClass + { + public NameplateFreeCompanyVisibility NameplateFreeCompanyVisibility = NameplateFreeCompanyVisibility.Default; + public NameplateTitleVisibility NameplateTitleVisibility = NameplateTitleVisibility.WhenHasTags; + public NameplateTitlePosition NameplateTitlePosition = NameplateTitlePosition.AlwaysAboveName; + + public bool IsApplyTagsToAllChatMessagesEnabled = true; + public bool IsLinkSelfInChatEnabled = false; + } } diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index f5e3a10..ef4fd27 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -48,6 +48,8 @@ public void Draw() if (ImGui.Begin(Strings.Loc_Static_PluginName, ref m_PluginConfiguration.IsVisible)) { + propertyProxy.LoadData(); + ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1, 0.8f, 0.5f, 1)); ImGui.TextWrapped(Strings.Loc_Static_WarningMessage); ImGui.PopStyleColor(); @@ -60,23 +62,23 @@ public void Draw() { ImGui.Spacing(); ImGui.Spacing(); - DrawCheckbox(nameof(m_PluginConfiguration.IsCustomTagsContextMenuEnabled), true, ref m_PluginConfiguration.IsCustomTagsContextMenuEnabled, () => m_PluginConfiguration.Save(m_PluginData)); + DrawCheckbox(nameof(m_PluginConfiguration.IsCustomTagsContextMenuEnabled), true, ref m_PluginConfiguration.IsCustomTagsContextMenuEnabled, () => SaveSettings()); ImGui.Spacing(); ImGui.Spacing(); DrawHeading(Strings.Loc_Static_Nameplates); - DrawComboBox(true, true, false, ref propertyProxy.NameplateFreeCompanyVisibility, () => m_PluginConfiguration.Save(m_PluginData)); - DrawComboBox(true, true, false, ref propertyProxy.NameplateTitleVisibility, () => m_PluginConfiguration.Save(m_PluginData)); - DrawComboBox(true, true, false, ref propertyProxy.NameplateTitlePosition, () => m_PluginConfiguration.Save(m_PluginData)); + DrawComboBox(true, true, false, ref propertyProxy.NameplateFreeCompanyVisibility, () => SaveSettings(true)); + DrawComboBox(true, true, false, ref propertyProxy.NameplateTitleVisibility, () => SaveSettings(true)); + DrawComboBox(true, true, false, ref propertyProxy.NameplateTitlePosition, () => SaveSettings(true)); ImGui.Spacing(); ImGui.Spacing(); DrawHeading(Strings.Loc_Static_Experimental); - DrawCheckbox(nameof(m_PluginConfiguration.IsPlayerNameRandomlyGenerated), true, ref m_PluginConfiguration.IsPlayerNameRandomlyGenerated, () => m_PluginConfiguration.Save(m_PluginData)); - DrawCheckbox(nameof(m_PluginConfiguration.IsLinkSelfInChatEnabled), true, ref m_PluginConfiguration.IsLinkSelfInChatEnabled, () => m_PluginConfiguration.Save(m_PluginData)); - DrawCheckbox(nameof(m_PluginConfiguration.IsApplyTagsToAllChatMessagesEnabled), true, ref m_PluginConfiguration.IsApplyTagsToAllChatMessagesEnabled, () => m_PluginConfiguration.Save(m_PluginData)); + DrawCheckbox(nameof(m_PluginConfiguration.IsPlayerNameRandomlyGenerated), true, ref m_PluginConfiguration.IsPlayerNameRandomlyGenerated, () => SaveSettings()); + DrawCheckbox(nameof(propertyProxy.IsLinkSelfInChatEnabled), true, ref propertyProxy.IsLinkSelfInChatEnabled, () => SaveSettings(true)); + DrawCheckbox(nameof(propertyProxy.IsApplyTagsToAllChatMessagesEnabled), true, ref propertyProxy.IsApplyTagsToAllChatMessagesEnabled, () => SaveSettings(true)); ImGui.EndTabItem(); } @@ -85,7 +87,7 @@ public void Draw() { ImGui.Spacing(); ImGui.Spacing(); - DrawCheckbox(nameof(m_PluginConfiguration.IsShowInheritedPropertiesEnabled), true, ref m_PluginConfiguration.IsShowInheritedPropertiesEnabled, () => m_PluginConfiguration.Save(m_PluginData)); + DrawCheckbox(nameof(m_PluginConfiguration.IsShowInheritedPropertiesEnabled), true, ref m_PluginConfiguration.IsShowInheritedPropertiesEnabled, () => SaveSettings()); ImGui.BeginGroup(); ImGui.Columns(2); @@ -112,13 +114,13 @@ public void Draw() { ImGui.Spacing(); ImGui.Spacing(); - DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabOrderedByProximity), true, ref m_PluginConfiguration.IsPlayersTabOrderedByProximity, () => m_PluginConfiguration.Save(m_PluginData)); - DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabSelfVisible), true, ref m_PluginConfiguration.IsPlayersTabSelfVisible, () => m_PluginConfiguration.Save(m_PluginData)); - DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabFriendsVisible), true, ref m_PluginConfiguration.IsPlayersTabFriendsVisible, () => m_PluginConfiguration.Save(m_PluginData)); - DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabPartyVisible), true, ref m_PluginConfiguration.IsPlayersTabPartyVisible, () => m_PluginConfiguration.Save(m_PluginData)); - DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabAllianceVisible), true, ref m_PluginConfiguration.IsPlayersTabAllianceVisible, () => m_PluginConfiguration.Save(m_PluginData)); - DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabEnemiesVisible), true, ref m_PluginConfiguration.IsPlayersTabEnemiesVisible, () => m_PluginConfiguration.Save(m_PluginData)); - DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabOthersVisible), true, ref m_PluginConfiguration.IsPlayersTabOthersVisible, () => m_PluginConfiguration.Save(m_PluginData)); + DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabOrderedByProximity), true, ref m_PluginConfiguration.IsPlayersTabOrderedByProximity, () => SaveSettings()); + DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabSelfVisible), true, ref m_PluginConfiguration.IsPlayersTabSelfVisible, () => SaveSettings()); + DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabFriendsVisible), true, ref m_PluginConfiguration.IsPlayersTabFriendsVisible, () => SaveSettings()); + DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabPartyVisible), true, ref m_PluginConfiguration.IsPlayersTabPartyVisible, () => SaveSettings()); + DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabAllianceVisible), true, ref m_PluginConfiguration.IsPlayersTabAllianceVisible, () => SaveSettings()); + DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabEnemiesVisible), true, ref m_PluginConfiguration.IsPlayersTabEnemiesVisible, () => SaveSettings()); + DrawCheckbox(nameof(m_PluginConfiguration.IsPlayersTabOthersVisible), true, ref m_PluginConfiguration.IsPlayersTabOthersVisible, () => SaveSettings()); ImGui.Spacing(); ImGui.Spacing(); @@ -234,7 +236,7 @@ public void Draw() if (!m_PluginConfiguration.IsVisible) { - m_PluginConfiguration.Save(m_PluginData); + SaveSettings(); } } @@ -275,12 +277,12 @@ void DrawQuickAddRow(Identity identity, int rowIndex) if (isTagAssigned) { m_PluginData.AddCustomTagToIdentity(customTag, identity); - m_PluginConfiguration.Save(m_PluginData); + SaveSettings(); } else { m_PluginData.RemoveCustomTagFromIdentity(customTag, identity); - m_PluginConfiguration.Save(m_PluginData); + SaveSettings(); } }); @@ -316,7 +318,7 @@ public void Select(Tag tag) } tag.IsSelected.Value = true; - m_PluginConfiguration.Save(m_PluginData); + SaveSettings(); } public void DrawTree(Tag tag) @@ -422,7 +424,7 @@ public void DrawTree(Tag tag) m_PluginData.RemoveCustomTagFromIdentities(tag); m_PluginData.AllCustomTags.Children.Remove(tag); m_PluginData.CustomTags.Remove(tag); - m_PluginConfiguration.Save(m_PluginData); + SaveSettings(); Select(m_PluginData.AllCustomTags); } @@ -444,12 +446,12 @@ public void DrawTree(Tag tag) if (isOpened && tag.Children.Any() && !tag.IsExpanded.Value) { tag.IsExpanded.Value = true; - m_PluginConfiguration.Save(m_PluginData); + SaveSettings(); } else if (!isOpened && tag.IsExpanded.Value) { tag.IsExpanded.Value = false; - m_PluginConfiguration.Save(m_PluginData); + SaveSettings(); } @@ -552,7 +554,7 @@ public void DrawControls(Tag tag) inheritableBool.Value = true; } - m_PluginConfiguration.Save(m_PluginData); + SaveSettings(); ImGui.CloseCurrentPopup(); } @@ -692,7 +694,7 @@ private void DrawRemovePropertyOverrideButton(IInheritable inheritable) if (ImGui.Button(FontAwesomeIcon.TrashAlt.ToIconString(), new Vector2(23, 23))) { inheritable.Behavior = InheritableBehavior.Inherit; - m_PluginConfiguration.Save(m_PluginData); + SaveSettings(); } ImGui.PopFont(); ImGui.PopStyleColor(); @@ -741,7 +743,7 @@ private void DrawInheritable(string localizedStringName, InheritableValue { DrawCheckbox("IsEnabled", false, ref inheritable.Value, () => { - m_PluginConfiguration.Save(m_PluginData); + SaveSettings(); }); ImGui.SameLine(); @@ -811,7 +813,7 @@ private void DrawInheritable(string localizedStringName, bool shouldLocal { inheritable.Behavior = InheritableBehavior.Disabled; } - m_PluginConfiguration.Save(m_PluginData); + SaveSettings(); }); if (isEnabled) @@ -819,7 +821,7 @@ private void DrawInheritable(string localizedStringName, bool shouldLocal ImGui.SameLine(); ImGui.SetNextItemWidth(200); ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(200, 0)); - DrawComboBox(false, shouldLocalizeNames, shouldOrderNames, ref inheritable.Value, () => { m_PluginConfiguration.Save(m_PluginData); }); + DrawComboBox(false, shouldLocalizeNames, shouldOrderNames, ref inheritable.Value, () => { SaveSettings(); }); ImGui.EndChild(); } @@ -886,7 +888,7 @@ private void DrawInheritable(string localizedStringName, InheritableValue { m_PluginConfiguration.Save(m_PluginData); }); + DrawTextBox(localizedStringName, ref inheritable.Value, () => { SaveSettings(); }); ImGui.EndChild(); } @@ -1163,6 +1165,13 @@ private void DrawUIColorPicker(System.Action colorSelected) } } + private void SaveSettings(bool saveProxy = false) + { + if (saveProxy) + propertyProxy.SaveData(); + m_PluginConfiguration.Save(m_PluginData); + } + private class PropertyProxy { private PluginConfiguration pluginConfig; @@ -1170,6 +1179,8 @@ private class PropertyProxy public NameplateFreeCompanyVisibility NameplateFreeCompanyVisibility; public NameplateTitleVisibility NameplateTitleVisibility; public NameplateTitlePosition NameplateTitlePosition; + public bool IsApplyTagsToAllChatMessagesEnabled; + public bool IsLinkSelfInChatEnabled; public PropertyProxy(PluginConfiguration config) { @@ -1178,21 +1189,23 @@ public PropertyProxy(PluginConfiguration config) public void LoadData() { - NameplateFreeCompanyVisibility = pluginConfig.NameplateFreeCompanyVisibility[ActivityContext.None]; - NameplateTitleVisibility = pluginConfig.NameplateTitleVisibility[ActivityContext.None]; - NameplateTitlePosition = pluginConfig.NameplateTitlePosition[ActivityContext.None]; + NameplateFreeCompanyVisibility = pluginConfig.GeneralOptions[ActivityContext.None].NameplateFreeCompanyVisibility; + NameplateTitleVisibility = pluginConfig.GeneralOptions[ActivityContext.None].NameplateTitleVisibility; + NameplateTitlePosition = pluginConfig.GeneralOptions[ActivityContext.None].NameplateTitlePosition; + IsApplyTagsToAllChatMessagesEnabled = pluginConfig.GeneralOptions[ActivityContext.None].IsApplyTagsToAllChatMessagesEnabled; + IsLinkSelfInChatEnabled = pluginConfig.GeneralOptions[ActivityContext.None].IsLinkSelfInChatEnabled; } public void SaveData() { - foreach (var key in pluginConfig.NameplateFreeCompanyVisibility.Keys) - pluginConfig.NameplateFreeCompanyVisibility[key] = NameplateFreeCompanyVisibility; - - foreach (var key in pluginConfig.NameplateTitleVisibility.Keys) - pluginConfig.NameplateTitleVisibility[key] = NameplateTitleVisibility; - - foreach (var key in pluginConfig.NameplateTitlePosition.Keys) - pluginConfig.NameplateTitlePosition[key] = NameplateTitlePosition; + foreach (var key in pluginConfig.GeneralOptions.Keys) + { + pluginConfig.GeneralOptions[key].NameplateFreeCompanyVisibility = NameplateFreeCompanyVisibility; + pluginConfig.GeneralOptions[key].NameplateTitleVisibility = NameplateTitleVisibility; + pluginConfig.GeneralOptions[key].NameplateTitlePosition = NameplateTitlePosition; + pluginConfig.GeneralOptions[key].IsApplyTagsToAllChatMessagesEnabled = IsApplyTagsToAllChatMessagesEnabled; + pluginConfig.GeneralOptions[key].IsLinkSelfInChatEnabled = IsLinkSelfInChatEnabled; + } } } } diff --git a/PlayerTags/Data/ActivityContext.cs b/PlayerTags/Data/ActivityContext.cs index 91ae10a..6b5ef7c 100644 --- a/PlayerTags/Data/ActivityContext.cs +++ b/PlayerTags/Data/ActivityContext.cs @@ -1,8 +1,10 @@ -using System; +using Newtonsoft.Json; +using System; namespace PlayerTags.Data { [Flags] + [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum ActivityContext { None = 0x0, diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index ad3de03..3300cca 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -103,7 +103,7 @@ public override void Dispose() private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) { - if (m_PluginConfiguration.IsApplyTagsToAllChatMessagesEnabled || Enum.IsDefined(type)) + if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].IsApplyTagsToAllChatMessagesEnabled || Enum.IsDefined(type)) { AddTagsToChat(sender); AddTagsToChat(message); diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs index 3ff938a..e822cc2 100644 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ b/PlayerTags/Features/LinkSelfInChatFeature.cs @@ -31,7 +31,7 @@ public void Dispose() private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) { - if (m_PluginConfiguration.IsLinkSelfInChatEnabled) + if (m_PluginConfiguration.GeneralOptions[activityContextManager.CurrentActivityContext].IsLinkSelfInChatEnabled) { ParsePayloads(sender); ParsePayloads(message); diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index 6152244..122eb0d 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -102,22 +102,22 @@ private void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs args) var beforeTitleBytes = args.Title.Encode(); AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany); - if (m_PluginConfiguration.NameplateTitlePosition[ActivityContextManager.CurrentActivityContext] == NameplateTitlePosition.AlwaysAboveName) + if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].NameplateTitlePosition == NameplateTitlePosition.AlwaysAboveName) args.IsTitleAboveName = true; - else if (m_PluginConfiguration.NameplateTitlePosition[ActivityContextManager.CurrentActivityContext] == NameplateTitlePosition.AlwaysBelowName) + else if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].NameplateTitlePosition == NameplateTitlePosition.AlwaysBelowName) args.IsTitleAboveName = false; - if (m_PluginConfiguration.NameplateTitleVisibility[ActivityContextManager.CurrentActivityContext] == NameplateTitleVisibility.Always) + if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].NameplateTitleVisibility == NameplateTitleVisibility.Always) args.IsTitleVisible = true; - else if (m_PluginConfiguration.NameplateTitleVisibility[ActivityContextManager.CurrentActivityContext] == NameplateTitleVisibility.Never) + else if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].NameplateTitleVisibility == NameplateTitleVisibility.Never) args.IsTitleVisible = false; - else if (m_PluginConfiguration.NameplateTitleVisibility[ActivityContextManager.CurrentActivityContext] == NameplateTitleVisibility.WhenHasTags) + else if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].NameplateTitleVisibility == NameplateTitleVisibility.WhenHasTags) { bool hasTitleChanged = !beforeTitleBytes.SequenceEqual(args.Title.Encode()); args.IsTitleVisible = hasTitleChanged; } - if (m_PluginConfiguration.NameplateFreeCompanyVisibility[ActivityContextManager.CurrentActivityContext] == NameplateFreeCompanyVisibility.Never) + if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].NameplateFreeCompanyVisibility == NameplateFreeCompanyVisibility.Never) args.FreeCompany.Payloads.Clear(); } From 39b49fb4a888ee45e95f121698cea88227190a1b Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 2 Sep 2022 15:38:49 +0200 Subject: [PATCH 037/174] disable writing Text color in TagTargetFeature, it's working out of the box (compatiblity with other plugins) --- PlayerTags/Features/TagTargetFeature.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index 0e49fcc..2c2bd4b 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -116,17 +116,17 @@ private Payload[] CreatePayloads(Tag tag) newPayloads.Add(new UIGlowPayload(tag.TextGlowColor.InheritedValue.Value)); } - if (tag.TextColor.InheritedValue != null) - { - newPayloads.Add(new UIForegroundPayload(tag.TextColor.InheritedValue.Value)); - } + //if (tag.TextColor.InheritedValue != null) + //{ + // newPayloads.Add(new UIForegroundPayload(tag.TextColor.InheritedValue.Value)); + //} newPayloads.Add(new TextPayload(text)); - if (tag.TextColor.InheritedValue != null) - { - newPayloads.Add(new UIForegroundPayload(0)); - } + //if (tag.TextColor.InheritedValue != null) + //{ + // newPayloads.Add(new UIForegroundPayload(0)); + //} if (tag.TextGlowColor.InheritedValue != null) { From e0718ac856995919ec29b2fbbedafc8a824df339 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 12:01:06 +0200 Subject: [PATCH 038/174] optimize code for coloring names --- PlayerTags/Features/ChatTagTargetFeature.cs | 39 ++------- .../Features/NameplateTagTargetFeature.cs | 29 ++----- PlayerTags/Features/TagTargetFeature.cs | 85 +++++++++++++++++-- 3 files changed, 90 insertions(+), 63 deletions(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 3300cca..5906835 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -3,11 +3,13 @@ using Dalamud.Game.Text; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; +using Lumina.Excel.GeneratedSheets; using PlayerTags.Configuration; using PlayerTags.Data; using System; using System.Collections.Generic; using System.Linq; +using Action = System.Action; namespace PlayerTags.Features { @@ -240,44 +242,17 @@ private void AddTagsToChat(SeString message) { var customTag = m_PluginData.CustomTags.FirstOrDefault(tag => tag.CustomId.Value == customTagId); if (customTag != null) - { - if (IsTagVisible(customTag, stringMatch.GameObject)) - { - if (customTag.TextColor.InheritedValue != null) - { - if (message.Payloads.Any(payload => payload is TextPayload || payload is PlayerPayload) - && customTag.IsTextColorAppliedToChatName.InheritedValue != null - && customTag.IsTextColorAppliedToChatName.InheritedValue.Value) - { - int payloadIndex = message.Payloads.IndexOf(stringMatch.PreferredPayload); - message.Payloads.Insert(payloadIndex + 1, new UIForegroundPayload(0)); - message.Payloads.Insert(payloadIndex, (new UIForegroundPayload(customTag.TextColor.InheritedValue.Value))); - } - } - } - } + applyTextFormatting(customTag); } if (stringMatch.GameObject is PlayerCharacter playerCharacter1) { if (playerCharacter1.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter1.ClassJob.GameData.Abbreviation, out var jobTag)) - { - if (IsTagVisible(jobTag, stringMatch.GameObject)) - { - if (jobTag.TextColor.InheritedValue != null) - { - if (message.Payloads.Any(payload => payload is TextPayload || payload is PlayerPayload) - && jobTag.IsTextColorAppliedToChatName.InheritedValue != null - && jobTag.IsTextColorAppliedToChatName.InheritedValue.Value) - { - int payloadIndex = message.Payloads.IndexOf(stringMatch.PreferredPayload); - message.Payloads.Insert(payloadIndex + 1, new UIForegroundPayload(0)); - message.Payloads.Insert(payloadIndex, (new UIForegroundPayload(jobTag.TextColor.InheritedValue.Value))); - } - } - } - } + applyTextFormatting(jobTag); } + + void applyTextFormatting(Tag tag) + => ApplyTextFormatting(stringMatch.GameObject, tag, new[] { message }, new[] { tag.IsTextColorAppliedToChatName }, stringMatch.PreferredPayload); } ApplyStringChanges(message, stringChanges, stringMatch.PreferredPayload); diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index 122eb0d..ff3a3b3 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -219,34 +219,17 @@ void checkTag(Tag tag) { var customTag = m_PluginData.CustomTags.FirstOrDefault(tag => tag.CustomId.Value == customTagId); if (customTag != null) - applyTextColor(customTag); + applyTextFormatting(customTag); } if (playerCharacter1.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter1.ClassJob.GameData.Abbreviation, out var jobTag)) - applyTextColor(jobTag); + applyTextFormatting(jobTag); - - void applyTextColor(Tag tag) + void applyTextFormatting(Tag tag) { - if (IsTagVisible(tag, gameObject)) - { - if (tag.TextColor.InheritedValue != null) - { - applyTextColor2(name, tag.IsTextColorAppliedToNameplateName, tag.TextColor); - applyTextColor2(title, tag.IsTextColorAppliedToNameplateTitle, tag.TextColor); - applyTextColor2(freeCompany, tag.IsTextColorAppliedToNameplateFreeCompany, tag.TextColor); - } - } - } - void applyTextColor2(SeString destPayload, InheritableValue enableFlag, InheritableValue colorValue) - { - if (destPayload.Payloads.Any(payload => payload is TextPayload) - && enableFlag.InheritedValue != null - && enableFlag.InheritedValue.Value) - { - destPayload.Payloads.Insert(0, (new UIForegroundPayload(colorValue.InheritedValue.Value))); - destPayload.Payloads.Add(new UIForegroundPayload(0)); - } + var destStrings = new[] { name, title, freeCompany }; + var isTextColorApplied = new[] { tag.IsTextColorAppliedToNameplateName, tag.IsTextColorAppliedToNameplateTitle, tag.IsTextColorAppliedToNameplateFreeCompany }; + ApplyTextFormatting(gameObject, tag, new[] { name, title, freeCompany }, isTextColorApplied, null); } } } diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index 2c2bd4b..849c732 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -2,11 +2,15 @@ using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; +using FFXIVClientStructs.FFXIV.Client.Game.Object; using Lumina.Excel.GeneratedSheets; using PlayerTags.Data; +using PlayerTags.Inheritables; using System; using System.Collections.Generic; using System.Linq; +using System.Xml.Linq; +using GameObject = Dalamud.Game.ClientState.Objects.Types.GameObject; namespace PlayerTags.Features { @@ -111,10 +115,10 @@ private Payload[] CreatePayloads(Tag tag) newPayloads.Add(new EmphasisItalicPayload(true)); } - if (tag.TextGlowColor.InheritedValue != null) - { - newPayloads.Add(new UIGlowPayload(tag.TextGlowColor.InheritedValue.Value)); - } + //if (tag.TextGlowColor.InheritedValue != null) + //{ + // newPayloads.Add(new UIGlowPayload(tag.TextGlowColor.InheritedValue.Value)); + //} //if (tag.TextColor.InheritedValue != null) //{ @@ -128,10 +132,10 @@ private Payload[] CreatePayloads(Tag tag) // newPayloads.Add(new UIForegroundPayload(0)); //} - if (tag.TextGlowColor.InheritedValue != null) - { - newPayloads.Add(new UIGlowPayload(0)); - } + //if (tag.TextGlowColor.InheritedValue != null) + //{ + // newPayloads.Add(new UIGlowPayload(0)); + //} if (tag.IsTextItalic.InheritedValue != null && tag.IsTextItalic.InheritedValue.Value) { @@ -305,5 +309,70 @@ protected void ApplyStringChanges(SeString seString, Dictionary[] textColorApplied, Payload preferedPayload) + { + if (IsTagVisible(tag, gameObject)) + { + for (int i = 0; i < destStrings.Length; i++) + { + var destString = destStrings[i]; + var isTextColorApplied = textColorApplied[i]; + applyTextColor(destString, isTextColorApplied, tag.TextColor); + applyTextGlowColor(destString, isTextColorApplied, tag.TextGlowColor); + //applyTextItalicColor(destString, tag.IsTextItalic); // Disabled, because that is needed only for a few parts somewhere else. + } + } + + void applyTextColor(SeString destPayload, InheritableValue enableFlag, InheritableValue colorValue) + { + if (shouldApplyFormattingPayloads(destPayload) + && enableFlag.InheritedValue != null + && enableFlag.InheritedValue.Value + && colorValue.InheritedValue != null) + applyTextFormattingPayloads(destPayload, new UIForegroundPayload(colorValue.InheritedValue.Value), new UIForegroundPayload(0)); + } + + void applyTextGlowColor(SeString destPayload, InheritableValue enableFlag, InheritableValue colorValue) + { + if (shouldApplyFormattingPayloads(destPayload) + && enableFlag.InheritedValue != null + && enableFlag.InheritedValue.Value + && colorValue.InheritedValue != null) + applyTextFormattingPayloads(destPayload, new UIGlowPayload(colorValue.InheritedValue.Value), new UIGlowPayload(0)); + } + + //void applyTextItalicColor(SeString destPayload, InheritableValue italicValue) + //{ + // if (shouldApplyFormattingPayloads(destPayload) + // && italicValue.InheritedValue != null + // && italicValue.InheritedValue.Value) + // applyTextFormattingPayloads(destPayload, new EmphasisItalicPayload(true), new EmphasisItalicPayload(false)); + //} + + bool shouldApplyFormattingPayloads(SeString destPayload) + => destPayload.Payloads.Any(payload => payload is TextPayload || payload is PlayerPayload); + + void applyTextFormattingPayloads(SeString destPayload, Payload startPayload, Payload endPayload) + { + if (preferedPayload == null) + applyTextFormattingPayloadToStartAndEnd(destPayload, startPayload, endPayload); + else + applyTextFormattingPayloadsToSpecificPosition(destPayload, startPayload, endPayload, preferedPayload); + } + + void applyTextFormattingPayloadToStartAndEnd(SeString destPayload, Payload startPayload, Payload endPayload) + { + destPayload.Payloads.Insert(0, startPayload); + destPayload.Payloads.Add(endPayload); + } + + void applyTextFormattingPayloadsToSpecificPosition(SeString destPayload, Payload startPayload, Payload endPayload, Payload preferedPayload) + { + int payloadIndex = destPayload.Payloads.IndexOf(preferedPayload); + destPayload.Payloads.Insert(payloadIndex + 1, endPayload); + destPayload.Payloads.Insert(payloadIndex, startPayload); + } + } } } From 0f80e54841c2158089ad4e1b906c976a0416844a Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 12:17:15 +0200 Subject: [PATCH 039/174] Add chinese translation --- PlayerTags/Resources/Strings.es-ES.resx | 588 ++++++++++++++++++++++++ 1 file changed, 588 insertions(+) create mode 100644 PlayerTags/Resources/Strings.es-ES.resx diff --git a/PlayerTags/Resources/Strings.es-ES.resx b/PlayerTags/Resources/Strings.es-ES.resx new file mode 100644 index 0000000..4ae4ade --- /dev/null +++ b/PlayerTags/Resources/Strings.es-ES.resx @@ -0,0 +1,588 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Player Tags + + + 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. + + + General + + + Quick Tag + + + Tagged Players + + + Player + + + Add tag: {0} + + + Remove tag: {0} + + + Nameplates + + + Add '{0}' to {1}. + + + <Inherited> + + + Selected + + + Expanded + + + Context menu integration + + + Options will be available in context menus for adding and removing custom tags from players. + + + Show inherited properties + + + Properties inherited from parent nodes will be shown in the editor. + + + Free company visibility + + + Default + + + The free company on nameplates will only be visible when the character is in a free company. + + + Never visible + + + The free company on nameplates will never be visible. + + + Title visibility + + + Always visible + + + The title on nameplates will always be visible, even when the character does not have a title. + + + Default + + + The title on nameplates will only be visible when the character has a title. + + + Never visible + + + The title on nameplates will never visible. + + + Only visible when it has tags + + + The title on nameplates will only be visible when it has tags. + + + Title position + + + Always above name + + + The title on nameplates will always be positioned above the name. + + + Always below name + + + The title on nameplates will always be positioned below the name. + + + Default + + + The title on nameplates will be positioned depending on the title. + + + Free company + + + The free company element on nameplates. + + + Name + + + The name element on nameplates. + + + Title + + + The title element on nameplates. + + + Development + + + Experimental + + + Randomly generate player names + + + Replace every player's name with a randomly generated one. + + + Apply tags to self in chat + + + Attempts to link your chat name to your character, allowing tags to be applied to self in chat. + + + Apply tags to all chat messages + + + Applies tags to all chat messages, including non-social messages. + + + Reset this item to its defaults. + + + Reset all items to their defaults. Custom tags will not be touched. + + + Tags + + + <No text> + + + All + + + Roles + + + Land/Hand + + + Tank + + + Healer + + + DPS + + + Melee + + + Ranged + + + Magical + + + Physical + + + Hand + + + Land + + + Custom + + + Custom + + + Enable the value of this override. + + + Add a property override. + + + Remove this property override. The value will be inherited from the parent item. + + + New tag + + + Add a custom tag. + + + Remove this custom tag. + + + Icon + + + The icon that will be displayed. + + + Show in chat + + + Whether the icon will be shown in chat. + + + Show in nameplates + + + Whether the icon will be shown in nameplates. + + + Text + + + The text that will be displayed. + + + Color + + + The color of the text. + + + Glow color + + + The glow color of the text. + + + Italic + + + Whether the text will be italic. + + + Show in chat + + + Whether the text will be shown in chat. + + + Show in nameplates + + + Whether the text will be shown in nameplates. + + + Position in chat + + + Where the tag will be positioned in chat. + + + Position in nameplates + + + Where the tag will be positioned in nameplates. + + + Target in nameplates + + + 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 + + + Display the tag after the target element. + + + Before + + + Display the tag before the target element. + + + Replace + + + Replace the target element with the tag. + + + Enabled + + + Custom id + + + General properties + + + Icon properties + + + Text properties + + + Position properties + + + Activity properties + + + Player properties + + + Show in pve duties + + + Whether the tag should be visible in pve duties. + + + Show in pvp duties + + + Whether the tag should be visible in pvp duties. + + + Show elsewhere + + + Whether the tag should be visible in other circumstances for which there is no specific option. + + + Show for self + + + Whether the tag should be visible for the local player. + + + Show for party members + + + Whether the tag should be visible for party members. + + + Show for alliance members + + + Whether the tag should be visible for alliance members who are not in the current party. + + + Show for friends + + + Whether the tag should be visible for friends. + + + Show for enemies + + + Whether the tag should be visible for enemies in pvp. + + + Show for others + + + 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 + + + Whether the color will be applied to the free company in nameplates. + + \ No newline at end of file From 4b60fa18b61e5220db6c5336d08d40af8b549615 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 12:17:21 +0200 Subject: [PATCH 040/174] add ui option for activity context profiles --- .../Configuration/PluginConfiguration.cs | 1 + .../Configuration/PluginConfigurationUI.cs | 73 ++++++++++-- PlayerTags/Resources/Strings.Designer.cs | 108 ++++++++++++++++++ PlayerTags/Resources/Strings.de.resx | 36 +++--- PlayerTags/Resources/Strings.resx | 36 ++++++ 5 files changed, 227 insertions(+), 27 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index aa5e778..2d9efb7 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -36,6 +36,7 @@ public class PluginConfiguration : IPluginConfiguration public bool IsPlayersTabAllianceVisible = true; public bool IsPlayersTabEnemiesVisible = true; public bool IsPlayersTabOthersVisible = false; + public bool IsGeneralOptionsAllTheSameEnabled = true; [JsonProperty(TypeNameHandling = TypeNameHandling.None, ItemTypeNameHandling = TypeNameHandling.None)] public Dictionary AllTagsChanges = new Dictionary(); diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index ef4fd27..ae73ad4 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -65,6 +65,12 @@ public void Draw() DrawCheckbox(nameof(m_PluginConfiguration.IsCustomTagsContextMenuEnabled), true, ref m_PluginConfiguration.IsCustomTagsContextMenuEnabled, () => SaveSettings()); + ImGui.Spacing(); + ImGui.Spacing(); + DrawHeading(Strings.Loc_Static_CurrentActivityProfile); + DrawComboBox(true, true, false, ref propertyProxy.CurrentActivityContext, () => SaveSettings(false)); + + ImGui.Spacing(); ImGui.Spacing(); DrawHeading(Strings.Loc_Static_Nameplates); @@ -72,14 +78,18 @@ public void Draw() DrawComboBox(true, true, false, ref propertyProxy.NameplateTitleVisibility, () => SaveSettings(true)); DrawComboBox(true, true, false, ref propertyProxy.NameplateTitlePosition, () => SaveSettings(true)); - ImGui.Spacing(); ImGui.Spacing(); - DrawHeading(Strings.Loc_Static_Experimental); - DrawCheckbox(nameof(m_PluginConfiguration.IsPlayerNameRandomlyGenerated), true, ref m_PluginConfiguration.IsPlayerNameRandomlyGenerated, () => SaveSettings()); + DrawHeading(Strings.Loc_Static_ChatExperimental); DrawCheckbox(nameof(propertyProxy.IsLinkSelfInChatEnabled), true, ref propertyProxy.IsLinkSelfInChatEnabled, () => SaveSettings(true)); DrawCheckbox(nameof(propertyProxy.IsApplyTagsToAllChatMessagesEnabled), true, ref propertyProxy.IsApplyTagsToAllChatMessagesEnabled, () => SaveSettings(true)); + + ImGui.Spacing(); + ImGui.Spacing(); + DrawHeading(Strings.Loc_Static_OtherExperimental); + DrawCheckbox(nameof(m_PluginConfiguration.IsPlayerNameRandomlyGenerated), true, ref m_PluginConfiguration.IsPlayerNameRandomlyGenerated, () => SaveSettings()); + ImGui.EndTabItem(); } @@ -1176,6 +1186,7 @@ private class PropertyProxy { private PluginConfiguration pluginConfig; + public ActivityContextSelection CurrentActivityContext; public NameplateFreeCompanyVisibility NameplateFreeCompanyVisibility; public NameplateTitleVisibility NameplateTitleVisibility; public NameplateTitlePosition NameplateTitlePosition; @@ -1185,20 +1196,34 @@ private class PropertyProxy public PropertyProxy(PluginConfiguration config) { pluginConfig = config; + CurrentActivityContext = config.IsGeneralOptionsAllTheSameEnabled ? ActivityContextSelection.All : ActivityContextSelection.None; } public void LoadData() { - NameplateFreeCompanyVisibility = pluginConfig.GeneralOptions[ActivityContext.None].NameplateFreeCompanyVisibility; - NameplateTitleVisibility = pluginConfig.GeneralOptions[ActivityContext.None].NameplateTitleVisibility; - NameplateTitlePosition = pluginConfig.GeneralOptions[ActivityContext.None].NameplateTitlePosition; - IsApplyTagsToAllChatMessagesEnabled = pluginConfig.GeneralOptions[ActivityContext.None].IsApplyTagsToAllChatMessagesEnabled; - IsLinkSelfInChatEnabled = pluginConfig.GeneralOptions[ActivityContext.None].IsLinkSelfInChatEnabled; + var currentActivityContext = GetActivityContext(CurrentActivityContext); + NameplateFreeCompanyVisibility = pluginConfig.GeneralOptions[currentActivityContext].NameplateFreeCompanyVisibility; + NameplateTitleVisibility = pluginConfig.GeneralOptions[currentActivityContext].NameplateTitleVisibility; + NameplateTitlePosition = pluginConfig.GeneralOptions[currentActivityContext].NameplateTitlePosition; + IsApplyTagsToAllChatMessagesEnabled = pluginConfig.GeneralOptions[currentActivityContext].IsApplyTagsToAllChatMessagesEnabled; + IsLinkSelfInChatEnabled = pluginConfig.GeneralOptions[currentActivityContext].IsLinkSelfInChatEnabled; } public void SaveData() { - foreach (var key in pluginConfig.GeneralOptions.Keys) + if (CurrentActivityContext == ActivityContextSelection.All) + { + pluginConfig.IsGeneralOptionsAllTheSameEnabled = true; + foreach (var key in pluginConfig.GeneralOptions.Keys) + applyChanges(key); + } + else + { + pluginConfig.IsGeneralOptionsAllTheSameEnabled = false; + applyChanges(GetActivityContext(CurrentActivityContext)); + } + + void applyChanges(ActivityContext key) { pluginConfig.GeneralOptions[key].NameplateFreeCompanyVisibility = NameplateFreeCompanyVisibility; pluginConfig.GeneralOptions[key].NameplateTitleVisibility = NameplateTitleVisibility; @@ -1207,6 +1232,36 @@ public void SaveData() pluginConfig.GeneralOptions[key].IsLinkSelfInChatEnabled = IsLinkSelfInChatEnabled; } } + + private ActivityContext GetActivityContext(ActivityContextSelection selection) + { + ActivityContext result; + + switch (selection) + { + case ActivityContextSelection.PveDuty: + result = ActivityContext.PveDuty; + break; + case ActivityContextSelection.PvpDuty: + result = ActivityContext.PvpDuty; + break; + case ActivityContextSelection.All: + case ActivityContextSelection.None: + default: + result = ActivityContext.None; + break; + } + + return result; + } + } + + private enum ActivityContextSelection + { + All, + None, + PveDuty, + PvpDuty } } } diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index 24f48a9..be0b1f5 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -69,6 +69,87 @@ public static string Loc_ActivityCategory { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Below options to be apply for ähnelt. + /// + public static string Loc_ActivityContextSelection { + get { + return ResourceManager.GetString("Loc_ActivityContextSelection", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Everywhere ähnelt. + /// + public static string Loc_ActivityContextSelection_All { + get { + return ResourceManager.GetString("Loc_ActivityContextSelection_All", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die The most options below will apply everywhere you are. They will be the same in Overworld, in PvE Duties and PvP Duties. Your options defined specifically for another context will be overwritten. ähnelt. + /// + public static string Loc_ActivityContextSelection_All_Description { + get { + return ResourceManager.GetString("Loc_ActivityContextSelection_All_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die No Duty ähnelt. + /// + public static string Loc_ActivityContextSelection_None { + get { + return ResourceManager.GetString("Loc_ActivityContextSelection_None", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die The most options below will apply only if you are outside of any duty. ähnelt. + /// + public static string Loc_ActivityContextSelection_None_Description { + get { + return ResourceManager.GetString("Loc_ActivityContextSelection_None_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die PvE Duties ähnelt. + /// + public static string Loc_ActivityContextSelection_PveDuty { + get { + return ResourceManager.GetString("Loc_ActivityContextSelection_PveDuty", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die The most options below will apply only to PvE Duties. ähnelt. + /// + public static string Loc_ActivityContextSelection_PveDuty_Description { + get { + return ResourceManager.GetString("Loc_ActivityContextSelection_PveDuty_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die PvP Duties ähnelt. + /// + public static string Loc_ActivityContextSelection_PvpDuty { + get { + return ResourceManager.GetString("Loc_ActivityContextSelection_PvpDuty", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die The most options below will apply only to PvP Duties. ähnelt. + /// + public static string Loc_ActivityContextSelection_PvpDuty_Description { + get { + return ResourceManager.GetString("Loc_ActivityContextSelection_PvpDuty_Description", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Custom ähnelt. /// @@ -1113,6 +1194,15 @@ public static string Loc_Static_AddPropertyOverride_Description { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Chat (Erperimental) ähnelt. + /// + public static string Loc_Static_ChatExperimental { + get { + return ResourceManager.GetString("Loc_Static_ChatExperimental", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Add tag: {0} ähnelt. /// @@ -1131,6 +1221,15 @@ public static string Loc_Static_ContextMenu_RemoveTag { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Current Activity Profile ähnelt. + /// + public static string Loc_Static_CurrentActivityProfile { + get { + return ResourceManager.GetString("Loc_Static_CurrentActivityProfile", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Development ähnelt. /// @@ -1203,6 +1302,15 @@ public static string Loc_Static_NoText { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Other (Experimental) ähnelt. + /// + public static string Loc_Static_OtherExperimental { + get { + return ResourceManager.GetString("Loc_Static_OtherExperimental", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Player ähnelt. /// diff --git a/PlayerTags/Resources/Strings.de.resx b/PlayerTags/Resources/Strings.de.resx index a67b4aa..41de432 100644 --- a/PlayerTags/Resources/Strings.de.resx +++ b/PlayerTags/Resources/Strings.de.resx @@ -59,46 +59,46 @@ : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> - - + + - + - - - - + + + + - - + + - - + + - - - - + + + + - + - + @@ -127,7 +127,7 @@ Generell - Quick Tag + Schnell-Tag Getaggte Spieler diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index d7f1ecf..1f99ebc 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -585,4 +585,40 @@ Whether the color will be applied to the free company in nameplates. + + Everywhere + + + No Duty + + + PvE Duties + + + PvP Duties + + + Current Activity Profile + + + Below options to be apply for + + + The most options below will apply everywhere you are. They will be the same in Overworld, in PvE Duties and PvP Duties. Your options defined specifically for another context will be overwritten. + + + The most options below will apply only if you are outside of any duty. + + + The most options below will apply only to PvE Duties. + + + The most options below will apply only to PvP Duties. + + + Chat (Erperimental) + + + Other (Experimental) + \ No newline at end of file From 8d40744cdfe372aa7c0a0553c1b5e3ded7dd3f44 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 12:20:48 +0200 Subject: [PATCH 041/174] update translation files --- PlayerTags/Resources/Strings.de.resx | 36 +++ PlayerTags/Resources/Strings.es-ES.resx | 330 +++++++++++++----------- 2 files changed, 219 insertions(+), 147 deletions(-) diff --git a/PlayerTags/Resources/Strings.de.resx b/PlayerTags/Resources/Strings.de.resx index 41de432..422c6cf 100644 --- a/PlayerTags/Resources/Strings.de.resx +++ b/PlayerTags/Resources/Strings.de.resx @@ -585,4 +585,40 @@ Bestimmt, ob die Farbe in der Namensanzeige auf die Freie Gesellschaft angewendet wird + + Überall + + + Außerhalb von Inhalten + + + PvE-Inhalte + + + PvP-Inhalte + + + Aktuelles Aktivitätsprofil + + + Untenstehende Optionen anwenden für + + + Die meisten untenstehenden Optionen werden für überall gelten, wo auch immer Du dich befindest. Sie werden außerhalb von Inhalten, in PvE- und PvP-Inhalten gelten. Die untenstehenden Optionen werden für ein bestimmtes Aktivitätskontext definierte Optionen überschreiben. + + + Die meisten untestehenden Optionen werden nur außerhalb von Inhalten gelten. + + + Die meisten untenstehenden Optionen werden nur in PvE-Inhalten gelten. + + + Die meisten untenstehenden Optionen werden nur in PvP-Inhalten gelten. + + + Chat (Experimentell) + + + Andere (Experimentell) + \ No newline at end of file diff --git a/PlayerTags/Resources/Strings.es-ES.resx b/PlayerTags/Resources/Strings.es-ES.resx index 4ae4ade..7940a1f 100644 --- a/PlayerTags/Resources/Strings.es-ES.resx +++ b/PlayerTags/Resources/Strings.es-ES.resx @@ -118,471 +118,507 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Player Tags + Etiquetas de Jugador - 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. + Este plugin puede modificar las placas de nombre y el chat. Cuando se combina con otros plugins que modifican estos elementos, puede que topes con comportamientos inesperados. El orden de carga de los plugins puede marcar la diferencia. General - Quick Tag + Etiqueta Rápida - Tagged Players + Jugadores Etiquetados - Player + Jugador - Add tag: {0} + Añadir etiqueta: {0} - Remove tag: {0} + Eliminar etiqueta: {0} - Nameplates + Placas de nombre - Add '{0}' to {1}. + Añadir '{0}' a {1}. <Inherited> - Selected + Seleccionado - Expanded + Expandido - Context menu integration + Integración con menú contextual - Options will be available in context menus for adding and removing custom tags from players. + Se añadirán opciones al menú contextual para añadir y eliminar etiquetas personalizadas a los jugadores. - Show inherited properties + Mostrar propiedades heredadas - Properties inherited from parent nodes will be shown in the editor. + Se mostrarán propiedades heredadas de nodos padre en el editor. - Free company visibility + Visibilidad de FC - Default + Predeterminado - The free company on nameplates will only be visible when the character is in a free company. + La FC en las placas de nombre sólo será visible cuando el jugador sea miembro de una FC. - Never visible + Nunca visible - The free company on nameplates will never be visible. + La FC en la placa del nombre nunca será visible. - Title visibility + Visibilidad de título - Always visible + Siempre visible - The title on nameplates will always be visible, even when the character does not have a title. + El título en la placa de nombre siempre será visible, incluso cuando el jugador no tenga uno asignado. - Default + Predeterminado - The title on nameplates will only be visible when the character has a title. + El título en la placa de nombre sólo será visible cuando el jugador tenga uno. - Never visible + Nunca visible - The title on nameplates will never visible. + El título en la placa de nombre nunca será visible. - Only visible when it has tags + Sólo visible cuando tenga etiquetas - The title on nameplates will only be visible when it has tags. + El título en la placa de nombre sólo será visible cuando tenga alguna etiqueta. - Title position + Posición del título - Always above name + Siempre sobre el nombre - The title on nameplates will always be positioned above the name. + El título en la placa del nombre siempre estará sobre el nombre. - Always below name + Siempre debajo del nombre - The title on nameplates will always be positioned below the name. + El título en la placa del nombre siempre estará bajo el nombre. - Default + Predeterminado - The title on nameplates will be positioned depending on the title. + El título en la placa de nombre se posicionará sobre o bajo el nombre, dependiendo del título. Free company - The free company element on nameplates. + El elemento de FC en la placa de nombre. - Name + Nombre - The name element on nameplates. + El elemento del nombre en las placas de nombre. - Title + Título - The title element on nameplates. + El elemento de título en las placas de nombre. - Development + Desarrollo Experimental - Randomly generate player names + Generar nombres de jugador aleatorios - Replace every player's name with a randomly generated one. + Reemplaza todos los nombres de jugadores con nombres generados al azar. - Apply tags to self in chat + Aplicar etiquetas a ti mismo en chat - Attempts to link your chat name to your character, allowing tags to be applied to self in chat. + Intenta enlazar tu nombre en chat a tu personaje, permitiendo que las etiquetas se te apliquen a ti mismo en el chat. - Apply tags to all chat messages + Aplicar etiquetas a todos los mensajes de chat - Applies tags to all chat messages, including non-social messages. + Aplicar etiquetas a todos los mensajes de chat, incluyendo mensajes no sociales. - Reset this item to its defaults. + Restablecer este elemento a sus valores por defecto. - Reset all items to their defaults. Custom tags will not be touched. + Restablecer todos los elementos a sus valores predeterminados. Las etiquetas personalizadas no serán tocadas. - Tags + Etiquetas <No text> - All + Todos Roles - Land/Hand + Gatherer/Crafter - Tank + Tanque - Healer + Sanador DPS - Melee + Melé - Ranged + A distancia - Magical + Mágico - Physical + Físico - Hand + Crafter - Land + Gatherer - Custom + Personalizado - Custom + Personalizado - Enable the value of this override. + Habilitar el valor de esta anulación. - Add a property override. + Agregar una anulación de propiedad. - Remove this property override. The value will be inherited from the parent item. + Quitar esta anulación de propiedad. El valor se tomará desde el elemento base. - New tag + Nueva etiqueta - Add a custom tag. + Añadir una etiqueta personalizada. - Remove this custom tag. + Eliminar esta etiqueta personalizada. - Icon + Icono - The icon that will be displayed. + El icono que se mostrará. - Show in chat + Mostrar en el chat - Whether the icon will be shown in chat. + Si el icono se mostrará o no dentro del chat. - Show in nameplates + Mostrar en placas de nombre - Whether the icon will be shown in nameplates. + Si el icono se mostrará o no en las placas de nombre. - Text + Texto - The text that will be displayed. + El texto que será mostrado. Color - The color of the text. + El color del texto. - Glow color + Color de resplandor - The glow color of the text. + El color del resplandor del texto. Italic - Whether the text will be italic. + Si el texto se mostrará en cursiva. - Show in chat + Mostrar en el chat - Whether the text will be shown in chat. + Si el texto se mostrará en el chat. - Show in nameplates + Mostrar en las placas de nombre - Whether the text will be shown in nameplates. + Si el texto se mostrará o no en las placas de nombre. - Position in chat + Posición en el chat - Where the tag will be positioned in chat. + Donde se posicionará la etiqueta en el chat. - Position in nameplates + Posición en las placas de nombre - Where the tag will be positioned in nameplates. + Donde se mostrará la etiqueta en las placas de nombre. - Target in nameplates + Objetivo en placas de nombre - The element that the tag should target in nameplates. + El elemento al que se debe dirigir la etiqueta dentro de las placas de nombre. - Add to players + Añadir a jugadores - A list of players to add tags to, separated by commas or semi-colons. E.g. "Cloud Strife, Tifa Lockhart". + Lista de jugadores a los que aplicar etiquetas, separadas por comas o punto y coma. Ejemplo: "Cloud Strife, Tifa Lockhart". - After + Después - Display the tag after the target element. + Mostrar la etiqueta tras el elemento de objetivo. - Before + Antes - Display the tag before the target element. + Mostrar la etiqueta antes del elemento de objetivo. - Replace + Reemplazar - Replace the target element with the tag. + Reemplaza el elemento de objetivo con la etiqueta. - Enabled + Habilitado - Custom id + ID personalizada - General properties + Propiedades generales - Icon properties + Propiedades de icono - Text properties + Propiedades de texto - Position properties + Propiedades de posición - Activity properties + Propiedades de actividad - Player properties + Propiedades de jugador - Show in pve duties + Mostrar en duties PVE - Whether the tag should be visible in pve duties. + Mostrar la etiqueta o no en las duties PVE. - Show in pvp duties + Mostrar en duties PVP - Whether the tag should be visible in pvp duties. + Mostrar la etiqueta o no en duties PVP. - Show elsewhere + Mostrar en otros - Whether the tag should be visible in other circumstances for which there is no specific option. + Mostrar o no la etiqueta en otras circunstancias para las que no hay opción específica. - Show for self + Mostrar para ti mismo - Whether the tag should be visible for the local player. + Mostrar o no la etiqueta para el jugador local. - Show for party members + Mostrar para miembros de party - Whether the tag should be visible for party members. + Mostrar o no la etiqueta para los miembros de party. - Show for alliance members + Mostrar para miembros de alianza - Whether the tag should be visible for alliance members who are not in the current party. + Mostrar o no la etiqueta para miembros de alianza (excluyendo la party actual). - Show for friends + Mostrar para amigos - Whether the tag should be visible for friends. + Mostrar o no la etiqueta para los amigos. - Show for enemies + Mostrar para enemigos - Whether the tag should be visible for enemies in pvp. + Mostrar o no la etiqueta en los enemigos en PVP. - Show for others + Mostrar para otros - Whether the tag should be visible for players in other circumstances for which there is no specific option. + Mostrar o no la etiqueta para jugadores en otras circunstancias para las que no hay opción específica. - Order by proximity + Orden por proximidad - Players that are closer to you will be ordered towards the top. + Los jugadores que estén más cerca de ti estarán más arriba en la lista. - Show self + Mostrar uno mismo - Show yourself in the players list. + Mostrarte a ti mismo en la lista de jugadores. - Show friends + Mostrar amigos - Show friends in the players list. + Mostrar amigos en la lista de jugadores. - Show party members + Mostrar miembros de party - Show party members in the players list. + Mostrar miembros de party en la lista de jugadores. - Show alliance members + Mostrar miembros de alianza - Show alliance members in the players list. + Mostrar miembros de alianza en la lista de jugadores. - Show enemies + Mostrar enemigos - Show enemies in the players list. + Mostrar enemigos en la lista de jugadores. - Show others + Mostrar otros - Show others in the players list. + Mostrar otros en la lista de jugadores. - Apply color to chat name + Aplicar color a nombre en chat - Whether the color will be applied to the name in chat. + Aplicar o no el color seleccionado al nombre en el chat. - Apply color to nameplate name + Aplicar color al nombre de la placa - Whether the color will be applied to the name in nameplates. + Si el color se aplicará o no al nombre en las placas de nombre. - Apply color to nameplate title + Aplicar color al título en la placa de nombre - Whether the color will be applied to title in nameplates. + Si el color se aplicará o no al título del jugador en las placas de nombre. - Apply color to nameplate free company + Aplicar color a la FC en la placa de nombre - Whether the color will be applied to the free company in nameplates. + Si el color se aplicará o no al nombre de la FC en las placas de nombre. + + + Everywhere + + + No Duty + + + PvE Duties + + + PvP Duties + + + Current Activity Profile + + + Below options to be apply for + + + The most options below will apply everywhere you are. They will be the same in Overworld, in PvE Duties and PvP Duties. Your options defined specifically for another context will be overwritten. + + + The most options below will apply only if you are outside of any duty. + + + The most options below will apply only to PvE Duties. + + + The most options below will apply only to PvP Duties. + + + Chat (Erperimental) + + + Other (Experimental) \ No newline at end of file From c63998ec16b12ce4e926478f25df3507bcd10f91 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 12:21:52 +0200 Subject: [PATCH 042/174] change version to v1.6 --- PlayerTags/PlayerTags.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 4dce414..b95f226 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,11 +1,11 @@  r00telement;Pilzinsel64 - 1.5.0.0 + 1.6.0.0 - net6.0-windows7.0 + net6.0-windows x64 annotations latest From 5007e227bfb57b242b0aa1858c98a64158d59a1c Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 18:17:40 +0200 Subject: [PATCH 043/174] adjust default options (show icon and color in nameplate except on free company) --- PlayerTags/Data/DefaultPluginData.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PlayerTags/Data/DefaultPluginData.cs b/PlayerTags/Data/DefaultPluginData.cs index afbd018..563857a 100644 --- a/PlayerTags/Data/DefaultPluginData.cs +++ b/PlayerTags/Data/DefaultPluginData.cs @@ -47,8 +47,11 @@ public DefaultPluginData() IsExpanded = true, IsIconVisibleInChat = true, IsTextVisibleInChat = true, + IsIconVisibleInNameplates = true, IsTextVisibleInNameplates = true, - IsTextColorAppliedToChatName = true + IsTextColorAppliedToChatName = true, + IsTextColorAppliedToNameplateName = true, + IsTextColorAppliedToNameplateTitle = true }; RoleTags = new Dictionary(); From 4ed9cac03ca30c438abacdaf5129e7c28137efd1 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 18:17:49 +0200 Subject: [PATCH 044/174] fix typo --- PlayerTags/Resources/Strings.Designer.cs | 2 +- PlayerTags/Resources/Strings.resx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index be0b1f5..cd33701 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -1195,7 +1195,7 @@ public static string Loc_Static_AddPropertyOverride_Description { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Chat (Erperimental) ähnelt. + /// Sucht eine lokalisierte Zeichenfolge, die Chat (Experimental) ähnelt. /// public static string Loc_Static_ChatExperimental { get { diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 1f99ebc..74fe9b7 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -616,7 +616,7 @@ The most options below will apply only to PvP Duties. - Chat (Erperimental) + Chat (Experimental) Other (Experimental) From bec210b37216346f822a7058d97292c0da21951b Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 18:24:34 +0200 Subject: [PATCH 045/174] change version to v1.6.1 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index b95f226..fc6bd28 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.6.0.0 + 1.6.1.0 From 3ac85bdc9abb9746d1870d98601e8400130011c9 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 18:38:53 +0200 Subject: [PATCH 046/174] don't show color by default on nameplate name --- PlayerTags/Data/DefaultPluginData.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/PlayerTags/Data/DefaultPluginData.cs b/PlayerTags/Data/DefaultPluginData.cs index 563857a..8cd118d 100644 --- a/PlayerTags/Data/DefaultPluginData.cs +++ b/PlayerTags/Data/DefaultPluginData.cs @@ -50,7 +50,6 @@ public DefaultPluginData() IsIconVisibleInNameplates = true, IsTextVisibleInNameplates = true, IsTextColorAppliedToChatName = true, - IsTextColorAppliedToNameplateName = true, IsTextColorAppliedToNameplateTitle = true }; From 4a3c712e349d3774a46b3caf437853dc55a7811e Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 19:07:35 +0200 Subject: [PATCH 047/174] enable text coloring again for player tag --- PlayerTags/Features/TagTargetFeature.cs | 32 ++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index 849c732..5876aec 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -115,27 +115,27 @@ private Payload[] CreatePayloads(Tag tag) newPayloads.Add(new EmphasisItalicPayload(true)); } - //if (tag.TextGlowColor.InheritedValue != null) - //{ - // newPayloads.Add(new UIGlowPayload(tag.TextGlowColor.InheritedValue.Value)); - //} + if (tag.TextGlowColor.InheritedValue != null) + { + newPayloads.Add(new UIGlowPayload(tag.TextGlowColor.InheritedValue.Value)); + } - //if (tag.TextColor.InheritedValue != null) - //{ - // newPayloads.Add(new UIForegroundPayload(tag.TextColor.InheritedValue.Value)); - //} + if (tag.TextColor.InheritedValue != null) + { + newPayloads.Add(new UIForegroundPayload(tag.TextColor.InheritedValue.Value)); + } newPayloads.Add(new TextPayload(text)); - //if (tag.TextColor.InheritedValue != null) - //{ - // newPayloads.Add(new UIForegroundPayload(0)); - //} + if (tag.TextColor.InheritedValue != null) + { + newPayloads.Add(new UIForegroundPayload(0)); + } - //if (tag.TextGlowColor.InheritedValue != null) - //{ - // newPayloads.Add(new UIGlowPayload(0)); - //} + if (tag.TextGlowColor.InheritedValue != null) + { + newPayloads.Add(new UIGlowPayload(0)); + } if (tag.IsTextItalic.InheritedValue != null && tag.IsTextItalic.InheritedValue.Value) { From d4a15bdf33d4bc0c13670b97df9e7bc4062c92a6 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 19:07:57 +0200 Subject: [PATCH 048/174] change version to v1.6.2 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index fc6bd28..a0eb3d5 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.6.1.0 + 1.6.2.0 From e01a3bc7ce1688e700a3adbb1acf7841713f2739 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 19:19:52 +0200 Subject: [PATCH 049/174] revert default option --- PlayerTags/Data/DefaultPluginData.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/PlayerTags/Data/DefaultPluginData.cs b/PlayerTags/Data/DefaultPluginData.cs index 8cd118d..1d09d2d 100644 --- a/PlayerTags/Data/DefaultPluginData.cs +++ b/PlayerTags/Data/DefaultPluginData.cs @@ -50,7 +50,6 @@ public DefaultPluginData() IsIconVisibleInNameplates = true, IsTextVisibleInNameplates = true, IsTextColorAppliedToChatName = true, - IsTextColorAppliedToNameplateTitle = true }; RoleTags = new Dictionary(); From 4cd90a83eb76bb09c30b7d126090c8b7e3057cf8 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 3 Sep 2022 19:36:46 +0200 Subject: [PATCH 050/174] disable glow color for whole text again --- PlayerTags/Features/TagTargetFeature.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index 5876aec..8261f53 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -319,7 +319,7 @@ protected void ApplyTextFormatting(GameObject gameObject, Tag tag, SeString[] de var destString = destStrings[i]; var isTextColorApplied = textColorApplied[i]; applyTextColor(destString, isTextColorApplied, tag.TextColor); - applyTextGlowColor(destString, isTextColorApplied, tag.TextGlowColor); + //applyTextGlowColor(destString, isTextColorApplied, tag.TextGlowColor); //applyTextItalicColor(destString, tag.IsTextItalic); // Disabled, because that is needed only for a few parts somewhere else. } } @@ -333,14 +333,14 @@ void applyTextColor(SeString destPayload, InheritableValue enableFlag, Inh applyTextFormattingPayloads(destPayload, new UIForegroundPayload(colorValue.InheritedValue.Value), new UIForegroundPayload(0)); } - void applyTextGlowColor(SeString destPayload, InheritableValue enableFlag, InheritableValue colorValue) - { - if (shouldApplyFormattingPayloads(destPayload) - && enableFlag.InheritedValue != null - && enableFlag.InheritedValue.Value - && colorValue.InheritedValue != null) - applyTextFormattingPayloads(destPayload, new UIGlowPayload(colorValue.InheritedValue.Value), new UIGlowPayload(0)); - } + //void applyTextGlowColor(SeString destPayload, InheritableValue enableFlag, InheritableValue colorValue) + //{ + // if (shouldApplyFormattingPayloads(destPayload) + // && enableFlag.InheritedValue != null + // && enableFlag.InheritedValue.Value + // && colorValue.InheritedValue != null) + // applyTextFormattingPayloads(destPayload, new UIGlowPayload(colorValue.InheritedValue.Value), new UIGlowPayload(0)); + //} //void applyTextItalicColor(SeString destPayload, InheritableValue italicValue) //{ From 2cf5f83dfd5be9350dc5a4272edc8f1012ec0215 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 4 Sep 2022 09:57:30 +0200 Subject: [PATCH 051/174] update spanish translation --- PlayerTags/Resources/Strings.es-ES.resx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/PlayerTags/Resources/Strings.es-ES.resx b/PlayerTags/Resources/Strings.es-ES.resx index 7940a1f..ddb61bf 100644 --- a/PlayerTags/Resources/Strings.es-ES.resx +++ b/PlayerTags/Resources/Strings.es-ES.resx @@ -586,39 +586,39 @@ Si el color se aplicará o no al nombre de la FC en las placas de nombre. - Everywhere + En todas partes - No Duty + Sin Duty - PvE Duties + Duties PvE - PvP Duties + Duties PvP - Current Activity Profile + Perfil de Actividad Actual - Below options to be apply for + Opciones inferiores a aplicar - The most options below will apply everywhere you are. They will be the same in Overworld, in PvE Duties and PvP Duties. Your options defined specifically for another context will be overwritten. + La mayoría de opciones abajo se aplicarán estés donde estés. Serán las mismas en el mundo abierto y en duties PvE y PvP. Las opciones que definas para otros contextos específicos serán sobreescritas. - The most options below will apply only if you are outside of any duty. + La mayoría de opciones abajo se aplicarán solo si no estás en una Duty de cualquier tipo. - The most options below will apply only to PvE Duties. + La mayoría de opciones abajo se aplicarán solo en Duties PvE. - The most options below will apply only to PvP Duties. + La mayoría de opciones abajo se aplicarán solo en Duties PvP. - Chat (Erperimental) + Chat (Experimental) - Other (Experimental) + Otros (Experimental) \ No newline at end of file From ae2f191c74f3f8bdf2bb1bfb5c89606885075f34 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 4 Sep 2022 09:57:52 +0200 Subject: [PATCH 052/174] change version to v1.6.3 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index a0eb3d5..244acc5 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.6.2.0 + 1.6.3.0 From 2a16aa144e73c450d72026c4edfde5afb37e3236 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 4 Sep 2022 21:00:33 +0200 Subject: [PATCH 053/174] Add current translation contributors to README --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index a897243..89606f4 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,12 @@ Start translation [here on Crowdin](https://crwd.in/playertags)! If you want to contribute to a language that isn't listed, just tell me with an Issue or on goat's Discord Server (yes, feel free to ping me). ^^ +| Language | Contributors | +| :--- | :--- | +| Spanish | Risu | +| German | Pilzinsel64, xEbony | +| ... | You? | + # Credits This plugin was originally developed by r00telement but forked and continued by Pilzinsel64. From 2c2286a0e0cc78d11e4e2a75d65ed6fef33aed4f Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 4 Sep 2022 21:10:27 +0200 Subject: [PATCH 054/174] Update README.md --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 89606f4..e9d17c0 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,12 @@ Start translation [here on Crowdin](https://crwd.in/playertags)! If you want to contribute to a language that isn't listed, just tell me with an Issue or on goat's Discord Server (yes, feel free to ping me). ^^ -| Language | Contributors | -| :--- | :--- | -| Spanish | Risu | -| German | Pilzinsel64, xEbony | -| ... | You? | +| Language | Contributors | Comments | +| :--- | :--- | :--- | +| English | Pilzinsel64 | Source Language +| German | Pilzinsel64, xEbony +| Spanish | Risu +| ... | You? # Credits From 3a3db4969aca67feed1f383715a5d8fac309c686 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 4 Sep 2022 21:11:17 +0200 Subject: [PATCH 055/174] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e9d17c0..923da71 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Feel free to open a pull request with your enhancements or bug fixes! # Translation You want to help and translate this plugin to your/other language(s)? \ -Start translation [here on Crowdin](https://crwd.in/playertags)! +Start translation [here on Crowdin](https://crowdin.com/project/playertags)! If you want to contribute to a language that isn't listed, just tell me with an Issue or on goat's Discord Server (yes, feel free to ping me). ^^ From 59fc6d4bf608b672a057cd82bde875b46ce66fb2 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 5 Sep 2022 17:50:05 +0200 Subject: [PATCH 056/174] LinkSelfInChatFeature: fix right content of message gets chropped and replaced by name --- PlayerTags/Features/LinkSelfInChatFeature.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs index e822cc2..fb1c857 100644 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ b/PlayerTags/Features/LinkSelfInChatFeature.cs @@ -89,7 +89,7 @@ private void ParsePayloads(SeString seString) seString.Payloads.Insert(textPayloadIndex, playerTextPayload); // Remove from the chopped text from the original payload - textPayload.Text = textPayload.Text.Substring(0, playerName.Length); + textPayload.Text = textPayload.Text.Substring(playerName.Length); textMatchIndex = textPayload.Text.IndexOf(playerName); } From a3197d89cf3e17b562ddb81b557a21aa5cc91c17 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 5 Sep 2022 18:26:28 +0200 Subject: [PATCH 057/174] change version to v1.6.4 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 244acc5..9fc45ef 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.6.3.0 + 1.6.4.0 From cd4ccac194c0787c30376e615160361c70a251bf Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 6 Sep 2022 11:48:33 +0200 Subject: [PATCH 058/174] use RawPayload.LinkTerminator to terminate PlayerPayload --- PlayerTags/Features/LinkSelfInChatFeature.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs index fb1c857..0346fd9 100644 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ b/PlayerTags/Features/LinkSelfInChatFeature.cs @@ -103,7 +103,10 @@ private void ParsePayloads(SeString seString) // effectively doubling up the player name. // For now, don't follow up with a text payload. Only use a player payload. var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); - seString.Payloads.Insert(seString.Payloads.IndexOf(playerTextPayload), playerPayload); + var playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload); + seString.Payloads.Insert(playerPayloadIndex++, playerPayload); + // Normally used to end PlayerPayload linking. But for the own player it has no affect. Anyway, use it, just because. Maybe it's needed in the future somewhere else. + seString.Payloads.Insert(playerPayloadIndex++, RawPayload.LinkTerminator); seString.Payloads.Remove(playerTextPayload); } } From d03c91e28cea8e9a002db2352f09d1f758136213 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 11 Sep 2022 20:57:22 +0200 Subject: [PATCH 059/174] use Dalamud language for Localizer fixes https://github.com/Pilzinsel64/PlayerTags/issues/12 --- PlayerTags/Localizer.cs | 16 +++++++++++++++- PlayerTags/Plugin.cs | 9 +++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/PlayerTags/Localizer.cs b/PlayerTags/Localizer.cs index afc110c..41a3f72 100644 --- a/PlayerTags/Localizer.cs +++ b/PlayerTags/Localizer.cs @@ -1,11 +1,25 @@ using Dalamud.Logging; +using Dalamud.Plugin; using PlayerTags.Resources; using System; +using System.Globalization; namespace PlayerTags { public static class Localizer { + private static CultureInfo culture = null; + + public static void SetLanguage(string langCode) + { + SetLanguage(new CultureInfo(langCode)); + } + + public static void SetLanguage(CultureInfo cultureInfo) + { + culture = cultureInfo; + } + public static string GetName(TEnum value) { return $"{typeof(TEnum).Name}_{value}"; @@ -37,7 +51,7 @@ public static string GetString(string localizedStringName, bool isDescription) public static string GetString(string localizedStringId) { - string? value = Strings.ResourceManager.GetString(localizedStringId, Strings.Culture); + string? value = Strings.ResourceManager.GetString(localizedStringId, culture ?? Strings.Culture); if (value != null) { return value; diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index fd98d98..4b3384e 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -28,6 +28,9 @@ public Plugin(DalamudPluginInterface pluginInterface) m_PluginData = new PluginData(m_PluginConfiguration); m_PluginConfigurationUI = new PluginConfigurationUI(m_PluginConfiguration, m_PluginData); + Localizer.SetLanguage(PluginServices.DalamudPluginInterface.UiLanguage); + PluginServices.DalamudPluginInterface.LanguageChanged += DalamudPluginInterface_LanguageChanged; + PluginServices.DalamudPluginInterface.UiBuilder.Draw += UiBuilder_Draw; PluginServices.DalamudPluginInterface.UiBuilder.OpenConfigUi += UiBuilder_OpenConfigUi; PluginServices.CommandManager.AddHandler(c_CommandName, new CommandInfo((string command, string arguments) => @@ -46,11 +49,17 @@ public void Dispose() m_NameplatesTagTargetFeature.Dispose(); m_CustomTagsContextMenuFeature.Dispose(); m_LinkSelfInChatFeature.Dispose(); + PluginServices.DalamudPluginInterface.LanguageChanged -= DalamudPluginInterface_LanguageChanged; PluginServices.CommandManager.RemoveHandler(c_CommandName); PluginServices.DalamudPluginInterface.UiBuilder.OpenConfigUi -= UiBuilder_OpenConfigUi; PluginServices.DalamudPluginInterface.UiBuilder.Draw -= UiBuilder_Draw; } + private void DalamudPluginInterface_LanguageChanged(string langCode) + { + Localizer.SetLanguage(langCode); + } + private void UiBuilder_Draw() { if (m_PluginConfiguration.IsVisible) From 3f21931b3159eab98510608f33034e39c6b76454 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 11 Sep 2022 20:59:07 +0200 Subject: [PATCH 060/174] change version to v1.6.5 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 9fc45ef..13ab654 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.6.4.0 + 1.6.5.0 From 1392a9dddd75db079175f636bc9c9eade5cc5ad2 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 12 Sep 2022 16:01:35 +0200 Subject: [PATCH 061/174] use SignatureHelper for Hook --- .../GameInterface/Nameplates/Nameplate.cs | 56 +++++-------------- 1 file changed, 14 insertions(+), 42 deletions(-) diff --git a/PlayerTags/GameInterface/Nameplates/Nameplate.cs b/PlayerTags/GameInterface/Nameplates/Nameplate.cs index f1013c4..468c37e 100644 --- a/PlayerTags/GameInterface/Nameplates/Nameplate.cs +++ b/PlayerTags/GameInterface/Nameplates/Nameplate.cs @@ -1,13 +1,12 @@ -using Dalamud.Game; -using Dalamud.Game.ClientState.Objects.SubKinds; +using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Objects.Types; -using Dalamud.Game.Text.SeStringHandling; using Dalamud.Hooking; using Dalamud.Logging; +using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.UI; using System; -using System.Runtime.InteropServices; using System.Linq; +using System.Runtime.InteropServices; namespace PlayerTags.GameInterface.Nameplates { @@ -16,24 +15,11 @@ namespace PlayerTags.GameInterface.Nameplates /// public class Nameplate : IDisposable { - private class PluginAddressResolver : BaseAddressResolver - { - private const string c_SetPlayerNameplateSignature = "48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 56 41 57 48 83 EC 40 44 0F B6 E2"; - public IntPtr? SetPlayerNameplatePtr { get; private set; } - - protected override void Setup64Bit(SigScanner scanner) - { - if (scanner.TryScanText(c_SetPlayerNameplateSignature, out var setPlayerNameplatePtr)) - { - SetPlayerNameplatePtr = setPlayerNameplatePtr; - } - } - } - private delegate IntPtr SetPlayerNameplateDelegate_Unmanaged(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId); - private Hook? m_SetPlayerNameplateHook; - private PluginAddressResolver m_PluginAddressResolver; + [Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 56 41 57 48 83 EC 40 44 0F B6 E2", DetourName = nameof(SetPlayerNameplateDetour))] + private readonly Hook? hook_AddonNamePlate_SetPlayerNameplateDetour = null; + private unsafe delegate IntPtr AddonNamePlate_SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId); /// /// Occurs when a player nameplate is updated by the game. @@ -47,39 +33,25 @@ public bool IsValid { get { - if (!m_PluginAddressResolver.SetPlayerNameplatePtr.HasValue) - { - return false; - } - - return true; + return hook_AddonNamePlate_SetPlayerNameplateDetour != null + && hook_AddonNamePlate_SetPlayerNameplateDetour.IsEnabled; } } public Nameplate() { - m_PluginAddressResolver = new PluginAddressResolver(); - m_PluginAddressResolver.Setup(); - if (!IsValid) - { - return; - } - - if (m_PluginAddressResolver.SetPlayerNameplatePtr.HasValue) - { - m_SetPlayerNameplateHook = Hook.FromAddress(m_PluginAddressResolver.SetPlayerNameplatePtr.Value, new SetPlayerNameplateDelegate_Unmanaged(SetPlayerNameplateDetour)); - m_SetPlayerNameplateHook?.Enable(); - } + SignatureHelper.Initialise(this); + hook_AddonNamePlate_SetPlayerNameplateDetour?.Enable(); } public void Dispose() { - m_SetPlayerNameplateHook?.Disable(); + hook_AddonNamePlate_SetPlayerNameplateDetour?.Disable(); } private IntPtr SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId) { - if (m_SetPlayerNameplateHook == null) + if (hook_AddonNamePlate_SetPlayerNameplateDetour == null) { return IntPtr.Zero; } @@ -129,7 +101,7 @@ private IntPtr SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool is newFreeCompanyPtr = GameInterfaceHelper.PluginAllocate(afterFreeCompanyBytes); } - var result = m_SetPlayerNameplateHook.Original(playerNameplateObjectPtr, playerNameplateUpdatedArgs.IsTitleAboveName, playerNameplateUpdatedArgs.IsTitleVisible, newTitlePtr, newNamePtr, newFreeCompanyPtr, playerNameplateUpdatedArgs.IconId); + var result = hook_AddonNamePlate_SetPlayerNameplateDetour.Original(playerNameplateObjectPtr, playerNameplateUpdatedArgs.IsTitleAboveName, playerNameplateUpdatedArgs.IsTitleVisible, newTitlePtr, newNamePtr, newFreeCompanyPtr, playerNameplateUpdatedArgs.IconId); if (hasNameChanged) { @@ -154,7 +126,7 @@ private IntPtr SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool is PluginLog.Error(ex, $"SetPlayerNameplateDetour"); } - return m_SetPlayerNameplateHook.Original(playerNameplateObjectPtr, isTitleAboveName, isTitleVisible, titlePtr, namePtr, freeCompanyPtr, iconId); + return hook_AddonNamePlate_SetPlayerNameplateDetour.Original(playerNameplateObjectPtr, isTitleAboveName, isTitleVisible, titlePtr, namePtr, freeCompanyPtr, iconId); } private T? GetNameplateGameObject(IntPtr nameplateObjectPtr) From 078649b3d9453b85749625d33d25e741cfa827bd Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 15 Sep 2022 09:07:00 +0200 Subject: [PATCH 062/174] update icon --- PlayerTags/Resources/images/icon.png | Bin 45313 -> 13541 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/PlayerTags/Resources/images/icon.png b/PlayerTags/Resources/images/icon.png index ef826b6fccec69b8a6c248e3252df4706229af56..5ca51a477f6e78cbcd189484687cbaaf319b8541 100644 GIT binary patch delta 10083 zcmbVybyOVBv+v^Wy1@g%f-btali*Hp5-bE+++h|E1Pe=oThO3^K!QskxI@t3!7aEg zaN+m8zxVDr@4j>Hx%0AivS19|!~bzk25AtPj1n=!Oqu72W26sA1S~ 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

Of0ePBy>bTbXk5w_c@vWXWzG`9& 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 j6z(cd$${#5{;W-g Date: Thu, 15 Sep 2022 13:10:23 +0200 Subject: [PATCH 063/174] change plugin name to "PlayerTags" (remove whitespace) --- PlayerTags/Plugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index 4b3384e..623430c 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -8,7 +8,7 @@ namespace PlayerTags { public sealed class Plugin : IDalamudPlugin { - public string Name => "Player Tags"; + public string Name => "PlayerTags"; private const string c_CommandName = "/playertags"; private PluginConfiguration m_PluginConfiguration; From 248ef429d47dc1cf7b07e905faa4d7fa9b3e174b Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 15 Sep 2022 20:20:31 +0200 Subject: [PATCH 064/174] keep TextPayload in LinkSelfInChatFeature if ChatTwo is installed -> Fix own player name not visible in Chat 2 when enabled the Link Self In Chat Feature --- PlayerTags/Features/LinkSelfInChatFeature.cs | 15 +++++++++++++-- PlayerTags/Plugin.cs | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs index 0346fd9..56eae2d 100644 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ b/PlayerTags/Features/LinkSelfInChatFeature.cs @@ -14,6 +14,9 @@ public class LinkSelfInChatFeature : IDisposable private PluginData m_PluginData; private ActivityContextManager activityContextManager; + public delegate bool ShouldRemovePlayerNameTextPayloadEventHandler(object sender); + public event ShouldRemovePlayerNameTextPayloadEventHandler ShouldRemovePlayerNameTextPayload; + public LinkSelfInChatFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) { m_PluginConfiguration = pluginConfiguration; @@ -102,12 +105,20 @@ private void ParsePayloads(SeString seString) // and links it with the player payload. When trying to make one of these manually, it displays the player payload separately, // effectively doubling up the player name. // For now, don't follow up with a text payload. Only use a player payload. + var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); var playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload); + + // Add the Player Link Payload seString.Payloads.Insert(playerPayloadIndex++, playerPayload); + + // Add the Link Terminator to end the Player Link. This should be done behind the Text Payload (display text). // Normally used to end PlayerPayload linking. But for the own player it has no affect. Anyway, use it, just because. Maybe it's needed in the future somewhere else. - seString.Payloads.Insert(playerPayloadIndex++, RawPayload.LinkTerminator); - seString.Payloads.Remove(playerTextPayload); + seString.Payloads.Insert(++playerPayloadIndex, RawPayload.LinkTerminator); + + // Remove the text payload (display text) + if (ShouldRemovePlayerNameTextPayload?.Invoke(this) ?? true) + seString.Payloads.Remove(playerTextPayload); } } } diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index 623430c..10b45ce 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -1,8 +1,13 @@ using Dalamud.Game.Command; using Dalamud.Plugin; +using Dalamud.Plugin.Internal; using PlayerTags.Configuration; using PlayerTags.Data; using PlayerTags.Features; +using System; +using System.IO; +using System.Linq; +using System.Reflection; namespace PlayerTags { @@ -10,6 +15,7 @@ public sealed class Plugin : IDalamudPlugin { public string Name => "PlayerTags"; private const string c_CommandName = "/playertags"; + private const string c_ChatTwo_InternalPluginName = "ChatTwo"; private PluginConfiguration m_PluginConfiguration; private PluginData m_PluginData; @@ -38,6 +44,7 @@ public Plugin(DalamudPluginInterface pluginInterface) UiBuilder_OpenConfigUi(); }) { HelpMessage = "Shows the config" }); m_LinkSelfInChatFeature = new LinkSelfInChatFeature(m_PluginConfiguration, m_PluginData); + m_LinkSelfInChatFeature.ShouldRemovePlayerNameTextPayload += LinkSelfInChatFeature_ShouldRemovePlayerNameTextPayload; m_CustomTagsContextMenuFeature = new CustomTagsContextMenuFeature(m_PluginConfiguration, m_PluginData); m_NameplatesTagTargetFeature = new NameplateTagTargetFeature(m_PluginConfiguration, m_PluginData); m_ChatTagTargetFeature = new ChatTagTargetFeature(m_PluginConfiguration, m_PluginData); @@ -55,6 +62,18 @@ public void Dispose() PluginServices.DalamudPluginInterface.UiBuilder.Draw -= UiBuilder_Draw; } + private bool LinkSelfInChatFeature_ShouldRemovePlayerNameTextPayload(object sender) + { + return !IsChatTwoActive(); + } + + private bool IsChatTwoActive() + { + var file = Path.Combine(Path.GetDirectoryName(PluginServices.DalamudPluginInterface.ConfigDirectory.FullName), @"ChatTwo\chat-log.db"); + var exists = File.Exists(file); + return exists; + } + private void DalamudPluginInterface_LanguageChanged(string langCode) { Localizer.SetLanguage(langCode); From 0ffc8450839c1ed4426d44a1c0e3c8f05efda9c2 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 15 Sep 2022 22:26:50 +0200 Subject: [PATCH 065/174] fully fix PlayerPayload problem for own character --- PlayerTags/Features/ChatTagTargetFeature.cs | 7 +++++++ PlayerTags/Features/LinkSelfInChatFeature.cs | 5 ++--- PlayerTags/Plugin.cs | 13 ------------- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 5906835..72508c7 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -257,6 +257,13 @@ void applyTextFormatting(Tag tag) ApplyStringChanges(message, stringChanges, stringMatch.PreferredPayload); } + + // Replace PlayerPayloads of your own character with TextPayloads + foreach (var payload in message.Payloads.ToArray()) + { + if (payload is PlayerPayload playerPayload && playerPayload.PlayerName.Contains(PluginServices.ClientState.LocalPlayer.Name.TextValue)) + message.Payloads.Remove(payload); + } } } } diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs index 56eae2d..85d0292 100644 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ b/PlayerTags/Features/LinkSelfInChatFeature.cs @@ -116,9 +116,8 @@ private void ParsePayloads(SeString seString) // Normally used to end PlayerPayload linking. But for the own player it has no affect. Anyway, use it, just because. Maybe it's needed in the future somewhere else. seString.Payloads.Insert(++playerPayloadIndex, RawPayload.LinkTerminator); - // Remove the text payload (display text) - if (ShouldRemovePlayerNameTextPayload?.Invoke(this) ?? true) - seString.Payloads.Remove(playerTextPayload); + // The PlayerPayload is just temporary. We keep the TextPayload. + // The PayerPayload gets removed at the ChatTagTargetFeature at the end. } } } diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index 10b45ce..908abb1 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -44,7 +44,6 @@ public Plugin(DalamudPluginInterface pluginInterface) UiBuilder_OpenConfigUi(); }) { HelpMessage = "Shows the config" }); m_LinkSelfInChatFeature = new LinkSelfInChatFeature(m_PluginConfiguration, m_PluginData); - m_LinkSelfInChatFeature.ShouldRemovePlayerNameTextPayload += LinkSelfInChatFeature_ShouldRemovePlayerNameTextPayload; m_CustomTagsContextMenuFeature = new CustomTagsContextMenuFeature(m_PluginConfiguration, m_PluginData); m_NameplatesTagTargetFeature = new NameplateTagTargetFeature(m_PluginConfiguration, m_PluginData); m_ChatTagTargetFeature = new ChatTagTargetFeature(m_PluginConfiguration, m_PluginData); @@ -62,18 +61,6 @@ public void Dispose() PluginServices.DalamudPluginInterface.UiBuilder.Draw -= UiBuilder_Draw; } - private bool LinkSelfInChatFeature_ShouldRemovePlayerNameTextPayload(object sender) - { - return !IsChatTwoActive(); - } - - private bool IsChatTwoActive() - { - var file = Path.Combine(Path.GetDirectoryName(PluginServices.DalamudPluginInterface.ConfigDirectory.FullName), @"ChatTwo\chat-log.db"); - var exists = File.Exists(file); - return exists; - } - private void DalamudPluginInterface_LanguageChanged(string langCode) { Localizer.SetLanguage(langCode); From 9e3cfa8f4f844494b46f267b7fcde1a6b414874c Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 15 Sep 2022 22:27:37 +0200 Subject: [PATCH 066/174] change version to v1.6.6 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 13ab654..9a3fa06 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.6.5.0 + 1.6.6.0 From 2911e5b1aaa9babf2d8b160fa9cf926885b7225f Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 16 Sep 2022 07:58:24 +0200 Subject: [PATCH 067/174] more comments and no linkterminator for linkselfinchatfeature --- PlayerTags/Features/LinkSelfInChatFeature.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs index 85d0292..07cec5c 100644 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ b/PlayerTags/Features/LinkSelfInChatFeature.cs @@ -114,10 +114,14 @@ private void ParsePayloads(SeString seString) // Add the Link Terminator to end the Player Link. This should be done behind the Text Payload (display text). // Normally used to end PlayerPayload linking. But for the own player it has no affect. Anyway, use it, just because. Maybe it's needed in the future somewhere else. - seString.Payloads.Insert(++playerPayloadIndex, RawPayload.LinkTerminator); + //seString.Payloads.Insert(++playerPayloadIndex, RawPayload.LinkTerminator); - // The PlayerPayload is just temporary. We keep the TextPayload. - // The PayerPayload gets removed at the ChatTagTargetFeature at the end. + // Remove TextPayload + //seString.Payloads.Remove(playerTextPayload); + + // I M P O R T A N T N O T I C E: + // The PlayerPayload is now just temporary. We keep the TextPayload don't add the LinkTerminator. + // The PayerPayload gets removed at the ChatTagTargetFeature at the end and the TextPayload will be keeped there. } } } From 35ce56a150f270d3dec9e4bce601822b4e8dfa80 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 16 Sep 2022 07:59:42 +0200 Subject: [PATCH 068/174] move things inside of the if in linkselfinchatfeature --- PlayerTags/Features/LinkSelfInChatFeature.cs | 114 +++++++++---------- 1 file changed, 56 insertions(+), 58 deletions(-) diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs index 07cec5c..05b6547 100644 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ b/PlayerTags/Features/LinkSelfInChatFeature.cs @@ -47,81 +47,79 @@ private void ParsePayloads(SeString seString) { foreach (var payload in seString.Payloads.ToArray()) { - if (payload is not TextPayload textPayload) + if (payload is TextPayload textPayload) { - continue; - } - - List playerTextPayloads = new List(); + List playerTextPayloads = new List(); - var playerName = PluginServices.ClientState.LocalPlayer.Name.TextValue; + var playerName = PluginServices.ClientState.LocalPlayer.Name.TextValue; - if (textPayload.Text == playerName) - { - playerTextPayloads.Add(textPayload); - textPayload.Text = textPayload.Text; - } - else - { - var textMatchIndex = textPayload.Text.IndexOf(playerName); - - while (textMatchIndex >= 0) + if (textPayload.Text == playerName) + { + playerTextPayloads.Add(textPayload); + textPayload.Text = textPayload.Text; + } + else { - var textPayloadIndex = seString.Payloads.IndexOf(payload); + var textMatchIndex = textPayload.Text.IndexOf(playerName); - // Chop text to the left and insert it as a new payload - if (textMatchIndex > 0) + while (textMatchIndex >= 0) { - // Add the content before the player - seString.Payloads.Insert(textPayloadIndex, new TextPayload(textPayload.Text.Substring(0, textMatchIndex))); + var textPayloadIndex = seString.Payloads.IndexOf(payload); + + // Chop text to the left and insert it as a new payload + if (textMatchIndex > 0) + { + // Add the content before the player + seString.Payloads.Insert(textPayloadIndex, new TextPayload(textPayload.Text.Substring(0, textMatchIndex))); + + // Remove from the chopped text from the original payload + textPayload.Text = textPayload.Text.Substring(textMatchIndex, textPayload.Text.Length - textMatchIndex); + } + + // This is the last reference to the local player in this payload + if (textPayload.Text.Length == playerName.Length) + { + playerTextPayloads.Add(textPayload); + break; + } + + // Create the new name payload and add it + var playerTextPayload = new TextPayload(playerName); + playerTextPayloads.Add(playerTextPayload); + seString.Payloads.Insert(textPayloadIndex, playerTextPayload); // Remove from the chopped text from the original payload - textPayload.Text = textPayload.Text.Substring(textMatchIndex, textPayload.Text.Length - textMatchIndex); - } + textPayload.Text = textPayload.Text.Substring(playerName.Length); - // This is the last reference to the local player in this payload - if (textPayload.Text.Length == playerName.Length) - { - playerTextPayloads.Add(textPayload); - break; + textMatchIndex = textPayload.Text.IndexOf(playerName); } - - // Create the new name payload and add it - var playerTextPayload = new TextPayload(playerName); - playerTextPayloads.Add(playerTextPayload); - seString.Payloads.Insert(textPayloadIndex, playerTextPayload); - - // Remove from the chopped text from the original payload - textPayload.Text = textPayload.Text.Substring(playerName.Length); - - textMatchIndex = textPayload.Text.IndexOf(playerName); } - } - foreach (var playerTextPayload in playerTextPayloads) - { - // This does some dodgy shit for an unknown reason. - // Typically when you receive a player payload followed by a text payload, it displays the text - // and links it with the player payload. When trying to make one of these manually, it displays the player payload separately, - // effectively doubling up the player name. - // For now, don't follow up with a text payload. Only use a player payload. + foreach (var playerTextPayload in playerTextPayloads) + { + // This does some dodgy shit for an unknown reason. + // Typically when you receive a player payload followed by a text payload, it displays the text + // and links it with the player payload. When trying to make one of these manually, it displays the player payload separately, + // effectively doubling up the player name. + // For now, don't follow up with a text payload. Only use a player payload. - var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); - var playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload); + var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); + var playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload); - // Add the Player Link Payload - seString.Payloads.Insert(playerPayloadIndex++, playerPayload); + // Add the Player Link Payload + seString.Payloads.Insert(playerPayloadIndex++, playerPayload); - // Add the Link Terminator to end the Player Link. This should be done behind the Text Payload (display text). - // Normally used to end PlayerPayload linking. But for the own player it has no affect. Anyway, use it, just because. Maybe it's needed in the future somewhere else. - //seString.Payloads.Insert(++playerPayloadIndex, RawPayload.LinkTerminator); + // Add the Link Terminator to end the Player Link. This should be done behind the Text Payload (display text). + // Normally used to end PlayerPayload linking. But for the own player it has no affect. Anyway, use it, just because. Maybe it's needed in the future somewhere else. + //seString.Payloads.Insert(++playerPayloadIndex, RawPayload.LinkTerminator); - // Remove TextPayload - //seString.Payloads.Remove(playerTextPayload); + // Remove TextPayload + //seString.Payloads.Remove(playerTextPayload); - // I M P O R T A N T N O T I C E: - // The PlayerPayload is now just temporary. We keep the TextPayload don't add the LinkTerminator. - // The PayerPayload gets removed at the ChatTagTargetFeature at the end and the TextPayload will be keeped there. + // I M P O R T A N T N O T I C E: + // The PlayerPayload is now just temporary. We keep the TextPayload don't add the LinkTerminator. + // The PayerPayload gets removed at the ChatTagTargetFeature at the end and the TextPayload will be keeped there. + } } } } From 072702fc219b7ee1fb5f80242d57077d724901ca Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 16 Sep 2022 15:54:35 +0200 Subject: [PATCH 069/174] remove obsulate event --- PlayerTags/Features/LinkSelfInChatFeature.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs index 05b6547..d1a078e 100644 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ b/PlayerTags/Features/LinkSelfInChatFeature.cs @@ -14,9 +14,6 @@ public class LinkSelfInChatFeature : IDisposable private PluginData m_PluginData; private ActivityContextManager activityContextManager; - public delegate bool ShouldRemovePlayerNameTextPayloadEventHandler(object sender); - public event ShouldRemovePlayerNameTextPayloadEventHandler ShouldRemovePlayerNameTextPayload; - public LinkSelfInChatFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) { m_PluginConfiguration = pluginConfiguration; From d04418fb2bce28832f3ca90198340caef15f6dc0 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 16 Sep 2022 15:57:57 +0200 Subject: [PATCH 070/174] improve position and coloring of party number prefix --- PlayerTags/Features/ChatTagTargetFeature.cs | 112 +++++++++++++------ PlayerTags/Features/LinkSelfInChatFeature.cs | 11 +- PlayerTags/Features/TagTargetFeature.cs | 34 +++--- 3 files changed, 102 insertions(+), 55 deletions(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 72508c7..aab575e 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -28,10 +28,7 @@ private class StringMatch ///

public SeString SeString { get; init; } - /// - /// The matching text payload. - /// - public TextPayload? TextPayload { get; init; } + public List DisplayTextPayloads { get; init; } = new(); /// /// The matching game object if one exists @@ -43,16 +40,18 @@ private class StringMatch /// public PlayerPayload? PlayerPayload { get; init; } - public Payload? PreferredPayload + public Payload? PlayerNamePayload { get { - if (TextPayload != null) - { - return TextPayload; - } + Payload textPayload = null; + string textMatch = GetMatchText(); + + textPayload = DisplayTextPayloads.FirstOrDefault(n => n is TextPayload textPayload && textPayload.Text.Contains(textMatch)); + textPayload ??= PlayerPayload; + textPayload ??= DisplayTextPayloads.FirstOrDefault(); - return PlayerPayload; + return textPayload; } } @@ -72,11 +71,6 @@ public string GetMatchText() return GameObject.Name.TextValue; } - if (TextPayload != null) - { - return TextPayload.Text; - } - if (PlayerPayload != null) { return PlayerPayload.PlayerName; @@ -107,8 +101,8 @@ private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString send { if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].IsApplyTagsToAllChatMessagesEnabled || Enum.IsDefined(type)) { - AddTagsToChat(sender); - AddTagsToChat(message); + AddTagsToChat(sender, type, true); + AddTagsToChat(message, type, false); } } @@ -139,31 +133,44 @@ protected override bool IsTextVisible(Tag tag) /// A list of matched game objects. private List GetStringMatches(SeString seString) { - List stringMatches = new List(); + List stringMatches = new(); + Stack curPlayerPayload = new(); + Stack> curRefPayloads = new(); + var defaultRawPayload = RawPayload.LinkTerminator.Data; - for (int payloadIndex = 0; payloadIndex < seString.Payloads.Count; ++payloadIndex) + foreach (var payload in seString.Payloads) { - var payload = seString.Payloads[payloadIndex]; + if (payload is PlayerPayload playerPayload) { - var gameObject = PluginServices.ObjectTable.FirstOrDefault(gameObject => gameObject.Name.TextValue == playerPayload.PlayerName); - - TextPayload? textPayload = null; + curPlayerPayload.Push(playerPayload); + curRefPayloads.Push(new List()); + } + else if (payload is RawPayload rawPayload) + { + if (defaultRawPayload.SequenceEqual(rawPayload.Data)) + finishCurrentMatch(); + } + else + { + if (curRefPayloads.TryPeek(out List result)) + result.Add(payload); + } + } - // The next payload MUST be a text payload - if (payloadIndex + 1 < seString.Payloads.Count) - { - textPayload = seString.Payloads[payloadIndex + 1] as TextPayload; - - // Don't handle the text payload twice - payloadIndex++; - } + // Finally finish, if not closed by RawPayload + finishCurrentMatch(); + void finishCurrentMatch() + { + if (curPlayerPayload.TryPop(out PlayerPayload playerPayload)) + { + var gameObject = PluginServices.ObjectTable.FirstOrDefault(gameObject => gameObject.Name.TextValue == playerPayload.PlayerName); var stringMatch = new StringMatch(seString) { GameObject = gameObject, PlayerPayload = playerPayload, - TextPayload = textPayload + DisplayTextPayloads = curRefPayloads.Pop() }; stringMatches.Add(stringMatch); } @@ -172,12 +179,45 @@ private List GetStringMatches(SeString seString) return stringMatches; } + private void SplitOffPartyNumberPrefix(SeString sender, XivChatType type) + { + if (type == XivChatType.Party || type == XivChatType.Alliance) + { + PlayerPayload lastPlayerPayload = null; + foreach (var payload in sender.Payloads.ToArray()) + { + if (payload is PlayerPayload playerPayload) + lastPlayerPayload = playerPayload; + else if (payload is TextPayload playerNamePayload && lastPlayerPayload != null) + { + // Get position of player name in payload + var indexOfPlayerName = playerNamePayload.Text.IndexOf(lastPlayerPayload.PlayerName); + + if (indexOfPlayerName > 0) + { + // Split off the name from the prefix number + var prefixPayload = new TextPayload(playerNamePayload.Text[..indexOfPlayerName]); + playerNamePayload.Text = playerNamePayload.Text[indexOfPlayerName..]; + + // Add prefix number before the player name payload + var playerNamePayloadIndex = sender.Payloads.IndexOf(playerNamePayload); + sender.Payloads.Insert(playerNamePayloadIndex, prefixPayload); + } + } + } + } + } + /// /// Adds all configured tags to a chat message. /// /// The message to change. - private void AddTagsToChat(SeString message) + private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender) { + // Split out the party/alliance number from the PlayerPayload + if (isSender) + SplitOffPartyNumberPrefix(message, chatType); + var stringMatches = GetStringMatches(message); foreach (var stringMatch in stringMatches) { @@ -235,7 +275,7 @@ private void AddTagsToChat(SeString message) } // An additional step to apply text color to additional locations - if (stringMatch.PlayerPayload != null && stringMatch.PreferredPayload != null) + if (stringMatch.PlayerPayload != null && stringMatch.DisplayTextPayloads.Any()) { Identity identity = m_PluginData.GetIdentity(stringMatch.PlayerPayload); foreach (var customTagId in identity.CustomTagIds) @@ -252,10 +292,10 @@ private void AddTagsToChat(SeString message) } void applyTextFormatting(Tag tag) - => ApplyTextFormatting(stringMatch.GameObject, tag, new[] { message }, new[] { tag.IsTextColorAppliedToChatName }, stringMatch.PreferredPayload); + => ApplyTextFormatting(stringMatch.GameObject, tag, new[] { message }, new[] { tag.IsTextColorAppliedToChatName }, stringMatch.DisplayTextPayloads); } - ApplyStringChanges(message, stringChanges, stringMatch.PreferredPayload); + ApplyStringChanges(message, stringChanges, stringMatch.DisplayTextPayloads, stringMatch.PlayerNamePayload); } // Replace PlayerPayloads of your own character with TextPayloads diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs index d1a078e..7f346cc 100644 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ b/PlayerTags/Features/LinkSelfInChatFeature.cs @@ -33,12 +33,12 @@ private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString send { if (m_PluginConfiguration.GeneralOptions[activityContextManager.CurrentActivityContext].IsLinkSelfInChatEnabled) { - ParsePayloads(sender); - ParsePayloads(message); + ParsePayloads(sender, type, true); + ParsePayloads(message, type, false); } } - private void ParsePayloads(SeString seString) + private void ParsePayloads(SeString seString, XivChatType chatType, bool isSender) { if (PluginServices.ClientState.LocalPlayer != null) { @@ -101,7 +101,10 @@ private void ParsePayloads(SeString seString) // For now, don't follow up with a text payload. Only use a player payload. var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); - var playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload); + int playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload); + + if (isSender && (chatType == XivChatType.Party || chatType == XivChatType.Alliance)) + playerPayloadIndex--; // Add the Player Link Payload seString.Payloads.Insert(playerPayloadIndex++, playerPayload); diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index 8261f53..911c697 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -240,7 +240,7 @@ protected void AddPayloadChanges(TagPosition tagPosition, IEnumerable p /// The string to apply changes to. /// The changes to apply. /// The payload in the string that changes should be anchored to. If there is no anchor, the changes will be applied to the entire string. - protected void ApplyStringChanges(SeString seString, Dictionary> stringChanges, Payload? anchorPayload = null) + protected void ApplyStringChanges(SeString seString, Dictionary> stringChanges, List anchorPayloads = null, Payload anchorReplacePayload = null) { if (stringChanges.Count == 0) { @@ -249,7 +249,7 @@ protected void ApplyStringChanges(SeString seString, Dictionary tagPositionsOrdered = new List(); // If there's no anchor payload, do replaces first so that befores and afters are based on the replaced data - if (anchorPayload == null) + if (anchorPayloads == null || !anchorPayloads.Any()) { tagPositionsOrdered.Add(TagPosition.Replace); } @@ -258,7 +258,7 @@ protected void ApplyStringChanges(SeString seString, Dictionary[] textColorApplied, Payload preferedPayload) + protected void ApplyTextFormatting(GameObject gameObject, Tag tag, SeString[] destStrings, InheritableValue[] textColorApplied, List preferedPayloads) { if (IsTagVisible(tag, gameObject)) { @@ -355,10 +357,10 @@ bool shouldApplyFormattingPayloads(SeString destPayload) void applyTextFormattingPayloads(SeString destPayload, Payload startPayload, Payload endPayload) { - if (preferedPayload == null) + if (preferedPayloads == null || !preferedPayloads.Any()) applyTextFormattingPayloadToStartAndEnd(destPayload, startPayload, endPayload); else - applyTextFormattingPayloadsToSpecificPosition(destPayload, startPayload, endPayload, preferedPayload); + applyTextFormattingPayloadsToSpecificPosition(destPayload, startPayload, endPayload, preferedPayloads); } void applyTextFormattingPayloadToStartAndEnd(SeString destPayload, Payload startPayload, Payload endPayload) @@ -367,11 +369,13 @@ void applyTextFormattingPayloadToStartAndEnd(SeString destPayload, Payload start destPayload.Payloads.Add(endPayload); } - void applyTextFormattingPayloadsToSpecificPosition(SeString destPayload, Payload startPayload, Payload endPayload, Payload preferedPayload) + void applyTextFormattingPayloadsToSpecificPosition(SeString destPayload, Payload startPayload, Payload endPayload, List preferedPayload) { - int payloadIndex = destPayload.Payloads.IndexOf(preferedPayload); - destPayload.Payloads.Insert(payloadIndex + 1, endPayload); - destPayload.Payloads.Insert(payloadIndex, startPayload); + int payloadStartIndex = destPayload.Payloads.IndexOf(preferedPayloads.First()); + destPayload.Payloads.Insert(payloadStartIndex, startPayload); + + int payloadEndIndex = destPayload.Payloads.IndexOf(preferedPayloads.Last()); + destPayload.Payloads.Insert(payloadEndIndex + 1, endPayload); } } } From 4eee0df1ff88168ee2e717153dc497515942e544 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 16 Sep 2022 16:38:01 +0200 Subject: [PATCH 071/174] insert tag and icon before party number in chat --- PlayerTags/Features/ChatTagTargetFeature.cs | 8 +-- .../Features/NameplateTagTargetFeature.cs | 12 ++-- PlayerTags/Features/TagTargetFeature.cs | 67 ++++++++++--------- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index aab575e..83e2517 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -221,7 +221,7 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender var stringMatches = GetStringMatches(message); foreach (var stringMatch in stringMatches) { - Dictionary> stringChanges = new Dictionary>(); + Dictionary stringChanges = new Dictionary(); if (stringMatch.GameObject is PlayerCharacter playerCharacter) { @@ -233,7 +233,7 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender var payloads = GetPayloads(jobTag, stringMatch.GameObject); if (payloads.Any()) { - AddPayloadChanges(jobTag.TagPositionInChat.InheritedValue.Value, payloads, stringChanges); + AddPayloadChanges(jobTag.TagPositionInChat.InheritedValue.Value, payloads, stringChanges, true); } } } @@ -247,7 +247,7 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender var generatedName = RandomNameGenerator.Generate(playerName); if (generatedName != null) { - AddPayloadChanges(TagPosition.Replace, Enumerable.Empty().Append(new TextPayload(generatedName)), stringChanges); + AddPayloadChanges(TagPosition.Replace, Enumerable.Empty().Append(new TextPayload(generatedName)), stringChanges, false); } } } @@ -267,7 +267,7 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender var customTagPayloads = GetPayloads(customTag, stringMatch.GameObject); if (customTagPayloads.Any()) { - AddPayloadChanges(customTag.TagPositionInChat.InheritedValue.Value, customTagPayloads, stringChanges); + AddPayloadChanges(customTag.TagPositionInChat.InheritedValue.Value, customTagPayloads, stringChanges, false); } } } diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index ff3a3b3..4146f05 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -128,7 +128,7 @@ private void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs args) /// The position of the changes. /// The payload changes to add. /// The dictionary to add changes to. - private void AddPayloadChanges(NameplateElement nameplateElement, TagPosition tagPosition, IEnumerable payloadChanges, Dictionary>> nameplateChanges) + private void AddPayloadChanges(NameplateElement nameplateElement, TagPosition tagPosition, IEnumerable payloadChanges, Dictionary> nameplateChanges, bool forceUsingSingleAnchorPayload) { if (!payloadChanges.Any()) { @@ -137,10 +137,10 @@ private void AddPayloadChanges(NameplateElement nameplateElement, TagPosition ta if (!nameplateChanges.Keys.Contains(nameplateElement)) { - nameplateChanges[nameplateElement] = new Dictionary>(); + nameplateChanges[nameplateElement] = new(); } - AddPayloadChanges(tagPosition, payloadChanges, nameplateChanges[nameplateElement]); + AddPayloadChanges(tagPosition, payloadChanges, nameplateChanges[nameplateElement], forceUsingSingleAnchorPayload); } /// @@ -152,7 +152,7 @@ private void AddPayloadChanges(NameplateElement nameplateElement, TagPosition ta /// The free company text to change. private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString title, SeString freeCompany) { - Dictionary>> nameplateChanges = new Dictionary>>(); + Dictionary> nameplateChanges = new(); if (gameObject is PlayerCharacter playerCharacter) { @@ -171,7 +171,7 @@ private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString t { var generatedName = RandomNameGenerator.Generate(characterName); if (generatedName != null) - AddPayloadChanges(NameplateElement.Name, TagPosition.Replace, Enumerable.Empty().Append(new TextPayload(generatedName)), nameplateChanges); + AddPayloadChanges(NameplateElement.Name, TagPosition.Replace, Enumerable.Empty().Append(new TextPayload(generatedName)), nameplateChanges, false); } } @@ -190,7 +190,7 @@ void checkTag(Tag tag) { var payloads = GetPayloads(tag, gameObject); if (payloads.Any()) - AddPayloadChanges(tag.TagTargetInNameplates.InheritedValue.Value, tag.TagPositionInNameplates.InheritedValue.Value, payloads, nameplateChanges); + AddPayloadChanges(tag.TagTargetInNameplates.InheritedValue.Value, tag.TagPositionInNameplates.InheritedValue.Value, payloads, nameplateChanges, false); } } } diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index 911c697..aace99e 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -19,6 +19,12 @@ namespace PlayerTags.Features /// public abstract class TagTargetFeature : IDisposable { + protected class StringChanges + { + public List Payloads { get; init; } = new(); + public bool ForceUsingSingleAnchorPayload { get; set; } = false; + } + public ActivityContextManager ActivityContextManager { get; init; } public TagTargetFeature() @@ -214,24 +220,17 @@ private void AddSpacesBetweenTextPayloads(List payloads, TagPosition ta /// The position to add changes to. /// The payloads to add. /// The dictionary to add the changes to. - protected void AddPayloadChanges(TagPosition tagPosition, IEnumerable payloads, Dictionary> stringChanges) + protected void AddPayloadChanges(TagPosition tagPosition, IEnumerable payloads, Dictionary stringChanges, bool forceUsingSingleAnchorPayload) { - if (payloads == null || !payloads.Any()) - { - return; - } - - if (stringChanges == null) + if (payloads != null && payloads.Any() && stringChanges != null) { - return; - } + if (!stringChanges.Keys.Contains(tagPosition)) + stringChanges[tagPosition] = new(); - if (!stringChanges.Keys.Contains(tagPosition)) - { - stringChanges[tagPosition] = new List(); + var changes = stringChanges[tagPosition]; + changes.Payloads.AddRange(payloads); + changes.ForceUsingSingleAnchorPayload = forceUsingSingleAnchorPayload; } - - stringChanges[tagPosition].AddRange(payloads); } /// @@ -240,7 +239,7 @@ protected void AddPayloadChanges(TagPosition tagPosition, IEnumerable p /// The string to apply changes to. /// The changes to apply. /// The payload in the string that changes should be anchored to. If there is no anchor, the changes will be applied to the entire string. - protected void ApplyStringChanges(SeString seString, Dictionary> stringChanges, List anchorPayloads = null, Payload anchorReplacePayload = null) + protected void ApplyStringChanges(SeString seString, Dictionary stringChanges, List anchorPayloads = null, Payload anchorReplacePayload = null) { if (stringChanges.Count == 0) { @@ -265,47 +264,51 @@ protected void ApplyStringChanges(SeString seString, Dictionary Date: Fri, 16 Sep 2022 17:14:54 +0200 Subject: [PATCH 072/174] add new options, but not use them yet --- .../Configuration/PluginConfigurationUI.cs | 12 +++++ PlayerTags/Data/DefaultPluginData.cs | 5 ++ PlayerTags/Data/Tag.cs | 9 ++++ PlayerTags/Resources/Strings.Designer.cs | 54 +++++++++++++++++++ PlayerTags/Resources/Strings.de.resx | 52 ++++++++++++------ PlayerTags/Resources/Strings.resx | 18 +++++++ 6 files changed, 133 insertions(+), 17 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index ae73ad4..eb868c5 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -679,6 +679,18 @@ public void DrawControls(Tag tag) { DrawInheritable(selectedInheritable.Inheritable.Key, true, false, inheritableNameplateElement); } + else if (selectedInheritable.Inheritable.Value is InheritableValue inheritableFreeCompanyVisibility) + { + DrawInheritable(selectedInheritable.Inheritable.Key, true, false, inheritableFreeCompanyVisibility); + } + else if (selectedInheritable.Inheritable.Value is InheritableValue inheritableNameplateTitleVisibility) + { + DrawInheritable(selectedInheritable.Inheritable.Key, true, false, inheritableNameplateTitleVisibility); + } + else if (selectedInheritable.Inheritable.Value is InheritableValue inheritableNameplateTitlePosition) + { + DrawInheritable(selectedInheritable.Inheritable.Key, true, false, inheritableNameplateTitlePosition); + } else if (selectedInheritable.Inheritable.Value is InheritableReference inheritableString) { DrawInheritable(selectedInheritable.Inheritable.Key, inheritableString); diff --git a/PlayerTags/Data/DefaultPluginData.cs b/PlayerTags/Data/DefaultPluginData.cs index 1d09d2d..3697a84 100644 --- a/PlayerTags/Data/DefaultPluginData.cs +++ b/PlayerTags/Data/DefaultPluginData.cs @@ -25,6 +25,7 @@ public DefaultPluginData() IsSelected = true, IsExpanded = true, TagPositionInChat = TagPosition.Before, + InsertBehindNumberPrefixInChat = true, TagPositionInNameplates = TagPosition.Replace, TagTargetInNameplates = NameplateElement.Title, IsTextItalic = true, @@ -33,6 +34,10 @@ public DefaultPluginData() IsVisibleInPveDuties = true, IsVisibleInPvpDuties = true, + NameplateFreeCompanyVisibility = NameplateFreeCompanyVisibility.Never, + NameplateTitleVisibility = NameplateTitleVisibility.Always, + NameplateTitlePosition = NameplateTitlePosition.AlwaysAboveName, + IsVisibleForSelf = true, IsVisibleForFriendPlayers = true, IsVisibleForPartyPlayers = true, diff --git a/PlayerTags/Data/Tag.cs b/PlayerTags/Data/Tag.cs index cadbccb..d96e16f 100644 --- a/PlayerTags/Data/Tag.cs +++ b/PlayerTags/Data/Tag.cs @@ -124,9 +124,18 @@ public Dictionary Inheritables [InheritableCategory("TextCategory")] public InheritableValue IsTextColorAppliedToNameplateFreeCompany = new InheritableValue(false); + [InheritableCategory("NameplateCategory")] + public InheritableValue NameplateFreeCompanyVisibility = new InheritableValue(Data.NameplateFreeCompanyVisibility.Default); + [InheritableCategory("NameplateCategory")] + public InheritableValue NameplateTitleVisibility = new InheritableValue(Data.NameplateTitleVisibility.Default); + [InheritableCategory("NameplateCategory")] + public InheritableValue NameplateTitlePosition = new InheritableValue(Data.NameplateTitlePosition.Default); + [InheritableCategory("PositionCategory")] public InheritableValue TagPositionInChat = new InheritableValue(TagPosition.Before); [InheritableCategory("PositionCategory")] + public InheritableValue InsertBehindNumberPrefixInChat = new InheritableValue(true); + [InheritableCategory("PositionCategory")] public InheritableValue TagPositionInNameplates = new InheritableValue(TagPosition.Before); [InheritableCategory("PositionCategory")] public InheritableValue TagTargetInNameplates = new InheritableValue(NameplateElement.Name); diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index cd33701..8d069b7 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -267,6 +267,24 @@ public static string Loc_IconCategory { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Insert behind group number prefix in chat ähnelt. + /// + public static string Loc_InsertBehindNumberPrefixInChat { + get { + return ResourceManager.GetString("Loc_InsertBehindNumberPrefixInChat", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die If enabled, the Tag and Icon will get insert behind the Group/Alliance number prefix in Chat instead of before. ähnelt. + /// + public static string Loc_InsertBehindNumberPrefixInChat_Description { + get { + return ResourceManager.GetString("Loc_InsertBehindNumberPrefixInChat_Description", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Apply tags to all chat messages ähnelt. /// @@ -861,6 +879,15 @@ public static string Loc_LandHandRole_Land { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Nameplate properties ähnelt. + /// + public static string Loc_NameplateCategory { + get { + return ResourceManager.GetString("Loc_NameplateCategory", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Free company ähnelt. /// @@ -942,6 +969,15 @@ public static string Loc_NameplateFreeCompanyVisibility_Default_Description { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Defines whenever the free company element of the nameplate should be visible or not. ähnelt. + /// + public static string Loc_NameplateFreeCompanyVisibility_Description { + get { + return ResourceManager.GetString("Loc_NameplateFreeCompanyVisibility_Description", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Never visible ähnelt. /// @@ -1023,6 +1059,15 @@ public static string Loc_NameplateTitlePosition_Default_Description { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Defines the position for the title element of the nameplate. Should it be above or below the name? You can decide! ähnelt. + /// + public static string Loc_NameplateTitlePosition_Description { + get { + return ResourceManager.GetString("Loc_NameplateTitlePosition_Description", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Title visibility ähnelt. /// @@ -1068,6 +1113,15 @@ public static string Loc_NameplateTitleVisibility_Default_Description { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Defines whenever the title element of the nameplate should be visible or not. ähnelt. + /// + public static string Loc_NameplateTitleVisibility_Description { + get { + return ResourceManager.GetString("Loc_NameplateTitleVisibility_Description", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Never visible ähnelt. /// diff --git a/PlayerTags/Resources/Strings.de.resx b/PlayerTags/Resources/Strings.de.resx index 422c6cf..0059a5e 100644 --- a/PlayerTags/Resources/Strings.de.resx +++ b/PlayerTags/Resources/Strings.de.resx @@ -59,46 +59,46 @@ : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> - - + + - + - - - - + + + + - - + + - - + + - - - - + + + + - + - + @@ -621,4 +621,22 @@ Andere (Experimentell) + + Nach der Gruppennummer im Chat hinzufügen + + + Wenn akiviert, dann wird der Tag und das Symbol hinter der Gruppen-/Allianznummer im Chat hinzugefügt, nicht davor. + + + Namensanzeige-Eigenschaften + + + Definiert, wann auch immer das Element zum Anzeigen der Freien Gesellschaft in der Namensanzeige sicht ist oder nicht. + + + Definiert, wo das Element zum Anzeigen der Titels in der Namensanzeige angezeigt werden soll. + + + Definiert, wann auch immer das Element zum Anzeigen der Titels in der Namensanzeige sicht ist oder nicht. + \ No newline at end of file diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 74fe9b7..7138a82 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -621,4 +621,22 @@ Other (Experimental) + + Insert behind group number prefix in chat + + + If enabled, the Tag and Icon will get insert behind the Group/Alliance number prefix in Chat instead of before. + + + Nameplate properties + + + Defines whenever the free company element of the nameplate should be visible or not. + + + Defines the position for the title element of the nameplate. Should it be above or below the name? You can decide! + + + Defines whenever the title element of the nameplate should be visible or not. + \ No newline at end of file From 71b9f0f01df7b5b8203b769d74f230e67669e68e Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 16 Sep 2022 17:23:06 +0200 Subject: [PATCH 073/174] disable nameplate category in tag properties again for now --- PlayerTags/Data/DefaultPluginData.cs | 6 +++--- PlayerTags/Data/Tag.cs | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/PlayerTags/Data/DefaultPluginData.cs b/PlayerTags/Data/DefaultPluginData.cs index 3697a84..143fc64 100644 --- a/PlayerTags/Data/DefaultPluginData.cs +++ b/PlayerTags/Data/DefaultPluginData.cs @@ -34,9 +34,9 @@ public DefaultPluginData() IsVisibleInPveDuties = true, IsVisibleInPvpDuties = true, - NameplateFreeCompanyVisibility = NameplateFreeCompanyVisibility.Never, - NameplateTitleVisibility = NameplateTitleVisibility.Always, - NameplateTitlePosition = NameplateTitlePosition.AlwaysAboveName, + //NameplateFreeCompanyVisibility = NameplateFreeCompanyVisibility.Never, + //NameplateTitleVisibility = NameplateTitleVisibility.Always, + //NameplateTitlePosition = NameplateTitlePosition.AlwaysAboveName, IsVisibleForSelf = true, IsVisibleForFriendPlayers = true, diff --git a/PlayerTags/Data/Tag.cs b/PlayerTags/Data/Tag.cs index d96e16f..51e9d0a 100644 --- a/PlayerTags/Data/Tag.cs +++ b/PlayerTags/Data/Tag.cs @@ -124,12 +124,12 @@ public Dictionary Inheritables [InheritableCategory("TextCategory")] public InheritableValue IsTextColorAppliedToNameplateFreeCompany = new InheritableValue(false); - [InheritableCategory("NameplateCategory")] - public InheritableValue NameplateFreeCompanyVisibility = new InheritableValue(Data.NameplateFreeCompanyVisibility.Default); - [InheritableCategory("NameplateCategory")] - public InheritableValue NameplateTitleVisibility = new InheritableValue(Data.NameplateTitleVisibility.Default); - [InheritableCategory("NameplateCategory")] - public InheritableValue NameplateTitlePosition = new InheritableValue(Data.NameplateTitlePosition.Default); + //[InheritableCategory("NameplateCategory")] + //public InheritableValue NameplateFreeCompanyVisibility = new InheritableValue(Data.NameplateFreeCompanyVisibility.Default); + //[InheritableCategory("NameplateCategory")] + //public InheritableValue NameplateTitleVisibility = new InheritableValue(Data.NameplateTitleVisibility.Default); + //[InheritableCategory("NameplateCategory")] + //public InheritableValue NameplateTitlePosition = new InheritableValue(Data.NameplateTitlePosition.Default); [InheritableCategory("PositionCategory")] public InheritableValue TagPositionInChat = new InheritableValue(TagPosition.Before); From 983b0902ed63804b6c6b543743350c06c877ba54 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 16 Sep 2022 17:29:07 +0200 Subject: [PATCH 074/174] update translation files --- PlayerTags/Resources/Strings.Designer.cs | 9 ++++++ PlayerTags/Resources/Strings.de.resx | 2 +- PlayerTags/Resources/Strings.es-ES.resx | 37 +++++++++++++----------- PlayerTags/Resources/Strings.resx | 3 ++ 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index 8d069b7..ceb3809 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -1248,6 +1248,15 @@ public static string Loc_Static_AddPropertyOverride_Description { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Chat ähnelt. + /// + public static string Loc_Static_Chat { + get { + return ResourceManager.GetString("Loc_Static_Chat", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Chat (Experimental) ähnelt. /// diff --git a/PlayerTags/Resources/Strings.de.resx b/PlayerTags/Resources/Strings.de.resx index 0059a5e..1208774 100644 --- a/PlayerTags/Resources/Strings.de.resx +++ b/PlayerTags/Resources/Strings.de.resx @@ -268,7 +268,7 @@ Versucht, deinen Chat-Namen mit deinem Charakter zu verknüpfen, was es erlaubt, Tags auf den eigenen Charakter im Chat anzuwenden. - Fügt Tags zu allen Chat-Nachrichten hinzu. + Fügt Tags zu allen Chat-Nachrichten hinzu Fügt Tags zu allen Chat-Nachrichten hinzu, einschließlich Nicht-Sozialer Nachrichten. diff --git a/PlayerTags/Resources/Strings.es-ES.resx b/PlayerTags/Resources/Strings.es-ES.resx index ddb61bf..07b4add 100644 --- a/PlayerTags/Resources/Strings.es-ES.resx +++ b/PlayerTags/Resources/Strings.es-ES.resx @@ -59,46 +59,46 @@ : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> - - + + - + - - - - + + + + - - + + - - + + - - - - + + + + - + - + @@ -621,4 +621,7 @@ Otros (Experimental) + + Chat + \ No newline at end of file diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 7138a82..c272ddc 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -639,4 +639,7 @@ Defines whenever the title element of the nameplate should be visible or not. + + Chat + \ No newline at end of file From 11619f95fde57dd3c6c3b59a95b8380cfe4801f1 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 16 Sep 2022 17:41:11 +0200 Subject: [PATCH 075/174] merge self linking feature into ChatTagTargetFeature --- .../Configuration/PluginConfiguration.cs | 11 -- .../Configuration/PluginConfigurationUI.cs | 7 +- PlayerTags/Features/ChatTagTargetFeature.cs | 90 ++++++++++++ PlayerTags/Features/LinkSelfInChatFeature.cs | 128 ------------------ PlayerTags/Plugin.cs | 3 - 5 files changed, 92 insertions(+), 147 deletions(-) delete mode 100644 PlayerTags/Features/LinkSelfInChatFeature.cs diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index 2d9efb7..245930d 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -108,16 +108,6 @@ private bool IsApplyTagsToAllChatMessagesEnabledV1 } } - [JsonProperty("IsLinkSelfInChatEnabled"), Obsolete] - private bool IsLinkSelfInChatEnabledV1 - { - set - { - foreach (var key in GeneralOptions.Keys) - GeneralOptions[key].IsLinkSelfInChatEnabled = value; - } - } - #endregion public event System.Action? Saved; @@ -229,6 +219,5 @@ public class GeneralOptionsClass public NameplateTitlePosition NameplateTitlePosition = NameplateTitlePosition.AlwaysAboveName; public bool IsApplyTagsToAllChatMessagesEnabled = true; - public bool IsLinkSelfInChatEnabled = false; } } diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index eb868c5..078c69a 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -80,8 +80,8 @@ public void Draw() ImGui.Spacing(); ImGui.Spacing(); - DrawHeading(Strings.Loc_Static_ChatExperimental); - DrawCheckbox(nameof(propertyProxy.IsLinkSelfInChatEnabled), true, ref propertyProxy.IsLinkSelfInChatEnabled, () => SaveSettings(true)); + DrawHeading(Strings.Loc_Static_Chat); + //DrawCheckbox(nameof(propertyProxy.IsLinkSelfInChatEnabled), true, ref propertyProxy.IsLinkSelfInChatEnabled, () => SaveSettings(true)); DrawCheckbox(nameof(propertyProxy.IsApplyTagsToAllChatMessagesEnabled), true, ref propertyProxy.IsApplyTagsToAllChatMessagesEnabled, () => SaveSettings(true)); @@ -1203,7 +1203,6 @@ private class PropertyProxy public NameplateTitleVisibility NameplateTitleVisibility; public NameplateTitlePosition NameplateTitlePosition; public bool IsApplyTagsToAllChatMessagesEnabled; - public bool IsLinkSelfInChatEnabled; public PropertyProxy(PluginConfiguration config) { @@ -1218,7 +1217,6 @@ public void LoadData() NameplateTitleVisibility = pluginConfig.GeneralOptions[currentActivityContext].NameplateTitleVisibility; NameplateTitlePosition = pluginConfig.GeneralOptions[currentActivityContext].NameplateTitlePosition; IsApplyTagsToAllChatMessagesEnabled = pluginConfig.GeneralOptions[currentActivityContext].IsApplyTagsToAllChatMessagesEnabled; - IsLinkSelfInChatEnabled = pluginConfig.GeneralOptions[currentActivityContext].IsLinkSelfInChatEnabled; } public void SaveData() @@ -1241,7 +1239,6 @@ void applyChanges(ActivityContext key) pluginConfig.GeneralOptions[key].NameplateTitleVisibility = NameplateTitleVisibility; pluginConfig.GeneralOptions[key].NameplateTitlePosition = NameplateTitlePosition; pluginConfig.GeneralOptions[key].IsApplyTagsToAllChatMessagesEnabled = IsApplyTagsToAllChatMessagesEnabled; - pluginConfig.GeneralOptions[key].IsLinkSelfInChatEnabled = IsLinkSelfInChatEnabled; } } diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 83e2517..0475bdc 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -208,12 +208,102 @@ private void SplitOffPartyNumberPrefix(SeString sender, XivChatType type) } } + private void ParsePayloadsForOwnPlayer(SeString seString, XivChatType chatType, bool isSender) + { + if (PluginServices.ClientState.LocalPlayer != null) + { + foreach (var payload in seString.Payloads.ToArray()) + { + if (payload is TextPayload textPayload) + { + List playerTextPayloads = new List(); + + var playerName = PluginServices.ClientState.LocalPlayer.Name.TextValue; + + if (textPayload.Text == playerName) + { + playerTextPayloads.Add(textPayload); + textPayload.Text = textPayload.Text; + } + else + { + var textMatchIndex = textPayload.Text.IndexOf(playerName); + + while (textMatchIndex >= 0) + { + var textPayloadIndex = seString.Payloads.IndexOf(payload); + + // Chop text to the left and insert it as a new payload + if (textMatchIndex > 0) + { + // Add the content before the player + seString.Payloads.Insert(textPayloadIndex, new TextPayload(textPayload.Text.Substring(0, textMatchIndex))); + + // Remove from the chopped text from the original payload + textPayload.Text = textPayload.Text.Substring(textMatchIndex, textPayload.Text.Length - textMatchIndex); + } + + // This is the last reference to the local player in this payload + if (textPayload.Text.Length == playerName.Length) + { + playerTextPayloads.Add(textPayload); + break; + } + + // Create the new name payload and add it + var playerTextPayload = new TextPayload(playerName); + playerTextPayloads.Add(playerTextPayload); + seString.Payloads.Insert(textPayloadIndex, playerTextPayload); + + // Remove from the chopped text from the original payload + textPayload.Text = textPayload.Text.Substring(playerName.Length); + + textMatchIndex = textPayload.Text.IndexOf(playerName); + } + } + + foreach (var playerTextPayload in playerTextPayloads) + { + // This does some dodgy shit for an unknown reason. + // Typically when you receive a player payload followed by a text payload, it displays the text + // and links it with the player payload. When trying to make one of these manually, it displays the player payload separately, + // effectively doubling up the player name. + // For now, don't follow up with a text payload. Only use a player payload. + + var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); + int playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload); + + if (isSender && (chatType == XivChatType.Party || chatType == XivChatType.Alliance)) + playerPayloadIndex--; + + // Add the Player Link Payload + seString.Payloads.Insert(playerPayloadIndex++, playerPayload); + + // Add the Link Terminator to end the Player Link. This should be done behind the Text Payload (display text). + // Normally used to end PlayerPayload linking. But for the own player it has no affect. Anyway, use it, just because. Maybe it's needed in the future somewhere else. + //seString.Payloads.Insert(++playerPayloadIndex, RawPayload.LinkTerminator); + + // Remove TextPayload + //seString.Payloads.Remove(playerTextPayload); + + // I M P O R T A N T N O T I C E: + // The PlayerPayload is now just temporary. We keep the TextPayload don't add the LinkTerminator. + // The PayerPayload gets removed at the ChatTagTargetFeature at the end and the TextPayload will be keeped there. + } + } + } + } + } + /// /// Adds all configured tags to a chat message. /// /// The message to change. private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender) { + // Parse Payloads for local player to be able to work with in the following code + ParsePayloadsForOwnPlayer(message, chatType, isSender); + // Split out the party/alliance number from the PlayerPayload if (isSender) SplitOffPartyNumberPrefix(message, chatType); diff --git a/PlayerTags/Features/LinkSelfInChatFeature.cs b/PlayerTags/Features/LinkSelfInChatFeature.cs deleted file mode 100644 index 7f346cc..0000000 --- a/PlayerTags/Features/LinkSelfInChatFeature.cs +++ /dev/null @@ -1,128 +0,0 @@ -using Dalamud.Game.Text; -using Dalamud.Game.Text.SeStringHandling; -using Dalamud.Game.Text.SeStringHandling.Payloads; -using PlayerTags.Configuration; -using PlayerTags.Data; -using System; -using System.Collections.Generic; - -namespace PlayerTags.Features -{ - public class LinkSelfInChatFeature : IDisposable - { - private PluginConfiguration m_PluginConfiguration; - private PluginData m_PluginData; - private ActivityContextManager activityContextManager; - - public LinkSelfInChatFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) - { - m_PluginConfiguration = pluginConfiguration; - m_PluginData = pluginData; - activityContextManager = new(); - - PluginServices.ChatGui.ChatMessage += Chat_ChatMessage; - } - - public void Dispose() - { - PluginServices.ChatGui.ChatMessage -= Chat_ChatMessage; - activityContextManager.Dispose(); - } - - private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) - { - if (m_PluginConfiguration.GeneralOptions[activityContextManager.CurrentActivityContext].IsLinkSelfInChatEnabled) - { - ParsePayloads(sender, type, true); - ParsePayloads(message, type, false); - } - } - - private void ParsePayloads(SeString seString, XivChatType chatType, bool isSender) - { - if (PluginServices.ClientState.LocalPlayer != null) - { - foreach (var payload in seString.Payloads.ToArray()) - { - if (payload is TextPayload textPayload) - { - List playerTextPayloads = new List(); - - var playerName = PluginServices.ClientState.LocalPlayer.Name.TextValue; - - if (textPayload.Text == playerName) - { - playerTextPayloads.Add(textPayload); - textPayload.Text = textPayload.Text; - } - else - { - var textMatchIndex = textPayload.Text.IndexOf(playerName); - - while (textMatchIndex >= 0) - { - var textPayloadIndex = seString.Payloads.IndexOf(payload); - - // Chop text to the left and insert it as a new payload - if (textMatchIndex > 0) - { - // Add the content before the player - seString.Payloads.Insert(textPayloadIndex, new TextPayload(textPayload.Text.Substring(0, textMatchIndex))); - - // Remove from the chopped text from the original payload - textPayload.Text = textPayload.Text.Substring(textMatchIndex, textPayload.Text.Length - textMatchIndex); - } - - // This is the last reference to the local player in this payload - if (textPayload.Text.Length == playerName.Length) - { - playerTextPayloads.Add(textPayload); - break; - } - - // Create the new name payload and add it - var playerTextPayload = new TextPayload(playerName); - playerTextPayloads.Add(playerTextPayload); - seString.Payloads.Insert(textPayloadIndex, playerTextPayload); - - // Remove from the chopped text from the original payload - textPayload.Text = textPayload.Text.Substring(playerName.Length); - - textMatchIndex = textPayload.Text.IndexOf(playerName); - } - } - - foreach (var playerTextPayload in playerTextPayloads) - { - // This does some dodgy shit for an unknown reason. - // Typically when you receive a player payload followed by a text payload, it displays the text - // and links it with the player payload. When trying to make one of these manually, it displays the player payload separately, - // effectively doubling up the player name. - // For now, don't follow up with a text payload. Only use a player payload. - - var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); - int playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload); - - if (isSender && (chatType == XivChatType.Party || chatType == XivChatType.Alliance)) - playerPayloadIndex--; - - // Add the Player Link Payload - seString.Payloads.Insert(playerPayloadIndex++, playerPayload); - - // Add the Link Terminator to end the Player Link. This should be done behind the Text Payload (display text). - // Normally used to end PlayerPayload linking. But for the own player it has no affect. Anyway, use it, just because. Maybe it's needed in the future somewhere else. - //seString.Payloads.Insert(++playerPayloadIndex, RawPayload.LinkTerminator); - - // Remove TextPayload - //seString.Payloads.Remove(playerTextPayload); - - // I M P O R T A N T N O T I C E: - // The PlayerPayload is now just temporary. We keep the TextPayload don't add the LinkTerminator. - // The PayerPayload gets removed at the ChatTagTargetFeature at the end and the TextPayload will be keeped there. - } - } - } - } - } - } -} diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index 908abb1..98d87e2 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -21,7 +21,6 @@ public sealed class Plugin : IDalamudPlugin private PluginData m_PluginData; private PluginConfigurationUI m_PluginConfigurationUI; - private LinkSelfInChatFeature m_LinkSelfInChatFeature; private CustomTagsContextMenuFeature m_CustomTagsContextMenuFeature; private NameplateTagTargetFeature m_NameplatesTagTargetFeature; private ChatTagTargetFeature m_ChatTagTargetFeature; @@ -43,7 +42,6 @@ public Plugin(DalamudPluginInterface pluginInterface) { UiBuilder_OpenConfigUi(); }) { HelpMessage = "Shows the config" }); - m_LinkSelfInChatFeature = new LinkSelfInChatFeature(m_PluginConfiguration, m_PluginData); m_CustomTagsContextMenuFeature = new CustomTagsContextMenuFeature(m_PluginConfiguration, m_PluginData); m_NameplatesTagTargetFeature = new NameplateTagTargetFeature(m_PluginConfiguration, m_PluginData); m_ChatTagTargetFeature = new ChatTagTargetFeature(m_PluginConfiguration, m_PluginData); @@ -54,7 +52,6 @@ public void Dispose() m_ChatTagTargetFeature.Dispose(); m_NameplatesTagTargetFeature.Dispose(); m_CustomTagsContextMenuFeature.Dispose(); - m_LinkSelfInChatFeature.Dispose(); PluginServices.DalamudPluginInterface.LanguageChanged -= DalamudPluginInterface_LanguageChanged; PluginServices.CommandManager.RemoveHandler(c_CommandName); PluginServices.DalamudPluginInterface.UiBuilder.OpenConfigUi -= UiBuilder_OpenConfigUi; From 15d5f34f7b3117aab8d941006fdb6cafa63f7f0e Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 16 Sep 2022 17:41:23 +0200 Subject: [PATCH 076/174] change version to v1.6.7.0 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 9a3fa06..bb65ff4 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.6.6.0 + 1.6.7.0 From 8993da87f4526f927b9d55a844a7d73d46c1e4a4 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Fri, 16 Sep 2022 17:50:03 +0200 Subject: [PATCH 077/174] handle "insert behind number prefix" --- PlayerTags/Features/ChatTagTargetFeature.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 0475bdc..c9a23d6 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -323,7 +323,8 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender var payloads = GetPayloads(jobTag, stringMatch.GameObject); if (payloads.Any()) { - AddPayloadChanges(jobTag.TagPositionInChat.InheritedValue.Value, payloads, stringChanges, true); + var insertBehindNumberPrefix = jobTag.InsertBehindNumberPrefixInChat?.Value ?? true; + AddPayloadChanges(jobTag.TagPositionInChat.InheritedValue.Value, payloads, stringChanges, insertBehindNumberPrefix); } } } From b78a54c7c5b259b5330ddd3126c8b2fb80c04546 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 17 Sep 2022 13:36:19 +0200 Subject: [PATCH 078/174] change version to v1.7 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index bb65ff4..2580ba9 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.6.7.0 + 1.7.0.0 From f53df9734a38fbef44ccfde0ceac526730b5973b Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 18 Sep 2022 17:14:09 +0200 Subject: [PATCH 079/174] update translation files --- PlayerTags/Resources/Strings.de.resx | 47 +- PlayerTags/Resources/Strings.es-ES.resx | 52 +- PlayerTags/Resources/Strings.fr.resx | 645 ++++++++++++++++++++++++ 3 files changed, 705 insertions(+), 39 deletions(-) create mode 100644 PlayerTags/Resources/Strings.fr.resx diff --git a/PlayerTags/Resources/Strings.de.resx b/PlayerTags/Resources/Strings.de.resx index 1208774..96de658 100644 --- a/PlayerTags/Resources/Strings.de.resx +++ b/PlayerTags/Resources/Strings.de.resx @@ -59,46 +59,46 @@ : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> - - + + - + - - - - + + + + - - + + - - + + - - - - + + + + - + - + @@ -268,7 +268,7 @@ Versucht, deinen Chat-Namen mit deinem Charakter zu verknüpfen, was es erlaubt, Tags auf den eigenen Charakter im Chat anzuwenden. - Fügt Tags zu allen Chat-Nachrichten hinzu + Fügt Tags zu allen Chat-Nachrichten hinzu. Fügt Tags zu allen Chat-Nachrichten hinzu, einschließlich Nicht-Sozialer Nachrichten. @@ -625,18 +625,21 @@ Nach der Gruppennummer im Chat hinzufügen - Wenn akiviert, dann wird der Tag und das Symbol hinter der Gruppen-/Allianznummer im Chat hinzugefügt, nicht davor. + Wenn aktiviert, dann wird der Tag und das Symbol hinter der Gruppen-/Allianznummer im Chat hinzugefügt, nicht davor. Namensanzeige-Eigenschaften - Definiert, wann auch immer das Element zum Anzeigen der Freien Gesellschaft in der Namensanzeige sicht ist oder nicht. + Definiert, wann auch immer das Element zum Anzeigen der Freien Gesellschaft in der Namensanzeige sichtbar ist oder nicht. - Definiert, wo das Element zum Anzeigen der Titels in der Namensanzeige angezeigt werden soll. + Definiert, wo das Element zum Anzeigen des Titels in der Namensanzeige angezeigt werden soll. - Definiert, wann auch immer das Element zum Anzeigen der Titels in der Namensanzeige sicht ist oder nicht. + Definiert, wann auch immer das Element zum Anzeigen des Titels in der Namensanzeige sichtbar ist oder nicht. + + + Chat \ No newline at end of file diff --git a/PlayerTags/Resources/Strings.es-ES.resx b/PlayerTags/Resources/Strings.es-ES.resx index 07b4add..35cfbd2 100644 --- a/PlayerTags/Resources/Strings.es-ES.resx +++ b/PlayerTags/Resources/Strings.es-ES.resx @@ -59,46 +59,46 @@ : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> - - + + - + - - - - + + + + - - + + - - + + - - - - + + + + - + - + @@ -621,6 +621,24 @@ Otros (Experimental) + + Insert behind group number prefix in chat + + + If enabled, the Tag and Icon will get insert behind the Group/Alliance number prefix in Chat instead of before. + + + Nameplate properties + + + Defines whenever the free company element of the nameplate should be visible or not. + + + Defines the position for the title element of the nameplate. Should it be above or below the name? You can decide! + + + Defines whenever the title element of the nameplate should be visible or not. + Chat diff --git a/PlayerTags/Resources/Strings.fr.resx b/PlayerTags/Resources/Strings.fr.resx new file mode 100644 index 0000000..a894726 --- /dev/null +++ b/PlayerTags/Resources/Strings.fr.resx @@ -0,0 +1,645 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Player Tags + + + Ce plugin vous permet de modifier les plaques de noms et le chat de votre fenêtre de log. Lorsqu'il est combiné à d'autres plugins qui les altèrent également, il est probable que cela provoque des interactions inattendues. L'ordre de chargement de vos plugins peut également affecter ces dites interactions. + + + Général + + + Tag Rapide + + + Personnages tagués + + + Personnage + + + Ajouter un tag : {0} + + + Retirer un tag : {0} + + + Plaques de nom + + + Ajouter '{0}' à {1}. + + + <Hérité> + + + Sélectionné + + + Étendu + + + Intégration dans les menus contextuels + + + Si cette option est activée, des menus supplémentaires sont ajoutées dans les menus contextuels pour ajouter ou retirer des tags personnalisés aux personnages. + + + Afficher les propriétés héritées + + + Les propriétés héritées des nœuds parents seront affichées dans l'éditeur. + + + Visibilité des tags de Compagnie Libre + + + Par défaut + + + Le tag de Compagnie Libre dans les plaques de noms sera affiché si le personnage appartient à une Compagnie Libre. + + + Jamais visible + + + Le tag de Compagnie Libre ne sera jamais affiché. + + + Visibilité des titres + + + Toujours visible + + + Le titre dans les plaques de noms sera toujours visible, même si le personnage n'a pas de titre. + + + Par défaut + + + Le titre dans les plaques de noms ne sera visible que si le personnage a un titre. + + + Jamais visible + + + Le titre des personnages ne sera jamais affiché dans les plaques de noms. + + + Visible uniquement si le personnage est tagué + + + Le titre dans les plaques de noms ne sera visible que si le personnage a un ou plusieurs tags associé(s). + + + Position du titre + + + Toujours au-dessus du nom + + + Le titre sera toujours positionné au-dessus du nom du personnage dans les plaques de noms. + + + Toujours en dessous du nom + + + Le titre sera toujours positionné en dessous du nom du personnage dans les plaques de noms. + + + Par défaut + + + La position du titre dans les plaques de nom dépendra de sa position par défaut en jeu. + + + Compagnie Libre + + + La partie contenant le tag de Compagnie Libre sur les plaques de noms. + + + Nom + + + La partie contenant le nom du personnage sur les plaques de noms. + + + Titre + + + La partie contenant le titre du joueur sur les plaques de noms. + + + Développement + + + Expérimental + + + Générer aléatoirement les noms des personnages + + + Remplace le nom de chaque personnage par un nom généré aléatoirement. + + + Appliquer les tags à soi-même dans le chat + + + Tente d'associer votre nom de chat à votre personnage, permettant d'appliquer des tags à soi-même au sein du chat. + + + Appliquer les tags à tous les messages du chat + + + Applique les tags à tous les messages de chat, y compris les messages non sociaux. + + + Réinitialiser cet élément à ses valeurs par défaut. + + + Réinitialiser tous les éléments à leurs valeurs par défaut. Les tags personnalisés ne seront pas affectés. + + + Tags + + + <Pas de texte> + + + Tous + + + Rôles + + + Terre/Main + + + Tank + + + Healer + + + DPS + + + Mêlée + + + Distance + + + Magique + + + Physique + + + Main + + + Terre + + + Personnalisé + + + Personnalisé + + + Activer la valeur de cette surcharge. + + + Ajouter une surcharge de propriété. + + + Supprimer cette propriété de surcharge. La valeur sera héritée de l'élément parent. + + + Nouveau tag + + + Ajouter un tag personnalisé. + + + Supprimer ce tag personnalisé. + + + Icône + + + L'icône qui doit être affichée. + + + Afficher dans le chat + + + Si l'icône doit être affichée dans le chat. + + + Afficher dans les plaques de noms + + + Si l'icône doit être affichée dans les plaques de noms. + + + Texte + + + Le texte qui doit être affiché. + + + Couleur  + + + La couleur du texte. + + + Couleur de surbrillance + + + La couleur de surbrillance du texte. + + + Italique + + + Si le texte doit être affiché en italique. + + + Afficher dans le chat + + + Si le texte doit être affiché dans le chat. + + + Afficher dans les plaques de noms + + + Si le texte doit être affiché dans les plaques de noms. + + + Position dans le chat + + + Là où le tag sera positionné dans le chat. + + + Position dans les plaques de noms + + + Là où le tag sera positionné dans les plaques de noms. + + + Cible dans les plaques de noms + + + L'élément que le tag doit affecter dans les plaques de nom. + + + Ajouter aux personnages + + + Une liste de personnages à qui ajouter des tags, séparés par des virgules ou des points virgules. Par exemple : "Cloud Strife, Tifa Lockhart". + + + Après + + + Afficher le tag après l'élément concerné. + + + Avant + + + Afficher le tag avant l'élément concerné. + + + Remplacer + + + Remplace l'élément cible par le tag. + + + Activé + + + ID personnalisé + + + Propriétés générales + + + Propriétés de l'icône + + + Propriétés du texte + + + Propriétés de position + + + Propriétés de contenu + + + Propriétés des personnages + + + Afficher dans les contenus PvE + + + Si le tag doit être visible ou non dans les missions de type PvE. + + + Afficher dans les missions JcJ + + + Si le tag doit être visible ou non dans les missions de type PvP. + + + Afficher ailleurs + + + Si le tag doit être visible dans d'autres circonstances pour lesquelles il n'y a pas d'option spécifique. + + + Afficher pour soi-même + + + Si le tag doit être visible ou non pour le personnage que vous jouez. + + + Afficher pour les équipiers + + + Si le tag doit être visible ou non pour les membres d'équipe. + + + Afficher pour les membres de l'alliance + + + Si le tag doit être visible pour les membres d'alliance qui ne sont pas dans votre équipe. + + + Afficher pour les amis + + + Si le tag doit être visible ou non pour les ami·e·s. + + + Afficher pour les ennemis + + + Si le tag doit être visible ou non pour les ennemis en JcJ. + + + Afficher pour les autres + + + Si le tag doit être visible pour les personnages dans d'autres circonstances pour lesquelles il n'y a pas d'option spécifique. + + + Trier par proximité + + + Les personnages qui sont les plus proches de vous seront listés en premier. + + + Afficher son propre personnage + + + Afficher votre personnage dans la liste des personnages. + + + Afficher les amis + + + Afficher vos amis dans la liste des personnages. + + + Afficher les équipiers + + + Afficher vos équipiers dans la liste des personnages. + + + Afficher les membres de votre alliance + + + Afficher les membres de votre alliance dans la liste des personnages. + + + Afficher les ennemis + + + Afficher vos ennemis dans la liste des personnages. + + + Afficher les autres + + + Afficher les autres personnages dans la liste des personnages. + + + Appliquer la couleur au nom dans le chat + + + Si la couleur doit être appliquée au nom des personnages dans le chat. + + + Appliquer la couleur au nom dans la plaque de nom + + + Si la couleur doit être appliquée au nom des personnages dans leur plaque de nom. + + + Appliquer la couleur au titre dans la plaque de nom + + + Si la couleur doit être appliquée au titre des personnages dans leur plaque de nom. + + + Appliquer la couleur à la Compagnie Libre dans la plaque de nom + + + Si la couleur doit être appliquée au tag de Compagnie Libre ou non dans les plaques de nom. + + + Partout + + + Aucune mission + + + Missions PvE + + + Missions PvP + + + Profil d'activité actuel + + + Les options ci-dessous doivent seulement être appliquées dans les contenus suivants + + + La plupart des options ci-dessous s'appliqueront partout où vous êtes. Elles seront les mêmes hors-missions, en missions PvE et en missions PvP. Vos options définies spécifiquement pour un autre contexte seront supplantées. + + + La plupart des options ci-dessous ne s'appliqueront qu'en dehors des Missions. + + + La plupart des options ci-dessous ne s'appliqueront qu'aux Missions JcE. + + + La plupart des options ci-dessous ne s'appliqueront qu'aux Missions JcJ. + + + Chat (expérimental) + + + Autre (expérimental) + + + Insert behind group number prefix in chat + + + If enabled, the Tag and Icon will get insert behind the Group/Alliance number prefix in Chat instead of before. + + + Nameplate properties + + + Defines whenever the free company element of the nameplate should be visible or not. + + + Defines the position for the title element of the nameplate. Should it be above or below the name? You can decide! + + + Defines whenever the title element of the nameplate should be visible or not. + + + Chat + + \ No newline at end of file From 0a7a76aff1b36891398e828e57f4ede8bdd67c8e Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 18 Sep 2022 17:15:17 +0200 Subject: [PATCH 080/174] change version to v1.7.1 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 2580ba9..7bd075c 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.7.0.0 + 1.7.1.0 From d42095f1d9f88df8fef4fbe10efae863dfb0d801 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 18 Sep 2022 19:01:42 +0200 Subject: [PATCH 081/174] build abbreviated own username in chat self --- .../GameConfig/GameConfigHelper.cs | 74 +++++++++++++++++++ .../Configuration/GameConfig/LogNameType.cs | 16 ++++ PlayerTags/Features/ChatTagTargetFeature.cs | 47 +++++++++++- PlayerTags/Plugin.cs | 1 + 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 PlayerTags/Configuration/GameConfig/GameConfigHelper.cs create mode 100644 PlayerTags/Configuration/GameConfig/LogNameType.cs diff --git a/PlayerTags/Configuration/GameConfig/GameConfigHelper.cs b/PlayerTags/Configuration/GameConfig/GameConfigHelper.cs new file mode 100644 index 0000000..c10df56 --- /dev/null +++ b/PlayerTags/Configuration/GameConfig/GameConfigHelper.cs @@ -0,0 +1,74 @@ +using FFXIVClientStructs.FFXIV.Client.UI.Misc; +using Lumina.Excel.GeneratedSheets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PlayerTags.Configuration.GameConfig +{ + public class GameConfigHelper + { + private static GameConfigHelper instance = null; + private unsafe static ConfigModule* configModule = null; + + public static GameConfigHelper Instance + { + get + { + instance ??= new GameConfigHelper(); + return instance; + } + } + + private GameConfigHelper() + { + unsafe + { + configModule = ConfigModule.Instance(); + } + } + + private int? GetIntValue(ConfigOption option) + { + int? value = null; + + unsafe + { + var index = configModule->GetIndex(option); + if (index.HasValue) + value = configModule->GetIntValue(index.Value); + } + + return value; + } + + public LogNameType? GetLogNameType() + { + LogNameType? logNameType = null; + int? value = GetIntValue(ConfigOption.LogNameType); + + if (value.HasValue) + { + switch (value) + { + case 0: + logNameType = LogNameType.FullName; + break; + case 1: + logNameType = LogNameType.LastNameShorted; + break; + case 2: + logNameType = LogNameType.FirstNameShorted; + break; + case 3: + logNameType = LogNameType.Initials; + break; + } + } + + return logNameType; + } + } +} diff --git a/PlayerTags/Configuration/GameConfig/LogNameType.cs b/PlayerTags/Configuration/GameConfig/LogNameType.cs new file mode 100644 index 0000000..3605357 --- /dev/null +++ b/PlayerTags/Configuration/GameConfig/LogNameType.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PlayerTags.Configuration.GameConfig +{ + public enum LogNameType + { + FullName, + LastNameShorted, + FirstNameShorted, + Initials + } +} diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index c9a23d6..3c9142b 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -3,11 +3,14 @@ using Dalamud.Game.Text; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; +using FFXIVClientStructs.FFXIV.Client.UI.Misc; using Lumina.Excel.GeneratedSheets; using PlayerTags.Configuration; +using PlayerTags.Configuration.GameConfig; using PlayerTags.Data; using System; using System.Collections.Generic; +using System.Data; using System.Linq; using Action = System.Action; @@ -179,6 +182,44 @@ void finishCurrentMatch() return stringMatches; } + private string BuildPlayername(string name) + { + var logNameType = GameConfigHelper.Instance.GetLogNameType(); + var result = string.Empty; + + if (logNameType != null) + { + var nameSplitted = name.Split(' '); + + if (nameSplitted.Length > 1) + { + var firstName = nameSplitted[0]; + var lastName = nameSplitted[1]; + + switch (logNameType) + { + case LogNameType.FullName: + result = $"{firstName} {lastName}"; + break; + case LogNameType.LastNameShorted: + result = $"{firstName} {lastName[..1]}."; + break; + case LogNameType.FirstNameShorted: + result = $"{firstName[..1]}. {lastName}"; + break; + case LogNameType.Initials: + result = $"{firstName[..1]}. {lastName[..1]}."; + break; + } + } + } + + if (string.IsNullOrEmpty(result)) + result = name; + + return result; + } + private void SplitOffPartyNumberPrefix(SeString sender, XivChatType type) { if (type == XivChatType.Party || type == XivChatType.Alliance) @@ -223,7 +264,8 @@ private void ParsePayloadsForOwnPlayer(SeString seString, XivChatType chatType, if (textPayload.Text == playerName) { playerTextPayloads.Add(textPayload); - textPayload.Text = textPayload.Text; + //textPayload.Text = textPayload.Text; + textPayload.Text = playerName; } else { @@ -264,6 +306,9 @@ private void ParsePayloadsForOwnPlayer(SeString seString, XivChatType chatType, foreach (var playerTextPayload in playerTextPayloads) { + // Fix displaying of abbreviated own player name as the game does this after the chat message handler + playerTextPayload.Text = BuildPlayername(playerTextPayload.Text); + // This does some dodgy shit for an unknown reason. // Typically when you receive a player payload followed by a text payload, it displays the text // and links it with the player payload. When trying to make one of these manually, it displays the player payload separately, diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index 98d87e2..4d4017d 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -1,6 +1,7 @@ using Dalamud.Game.Command; using Dalamud.Plugin; using Dalamud.Plugin.Internal; +using FFXIVClientStructs.FFXIV.Client.UI.Misc; using PlayerTags.Configuration; using PlayerTags.Data; using PlayerTags.Features; From 111682bb773df77be3492eed76be2530a6aae4f4 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 19 Sep 2022 10:18:15 +0200 Subject: [PATCH 082/174] Add info about french translation --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 923da71..dfdbfd3 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ If you want to contribute to a language that isn't listed, just tell me with an | English | Pilzinsel64 | Source Language | German | Pilzinsel64, xEbony | Spanish | Risu +| French | Khayle | ... | You? # Credits From 8cb900da614829b6c3789c976c97b3e4bc0d710b Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 19 Sep 2022 10:19:00 +0200 Subject: [PATCH 083/174] change version to v1.7.2 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 7bd075c..a345218 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.7.1.0 + 1.7.2.0 From 0c89d947f79418d18eef2daf92438ced1730921d Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 20 Sep 2022 07:52:22 +0200 Subject: [PATCH 084/174] optimize handling in groups and allicance chat --- PlayerTags/Features/ChatTagTargetFeature.cs | 94 ++++++++------------- PlayerTags/Features/TagTargetFeature.cs | 39 +++++++++ 2 files changed, 72 insertions(+), 61 deletions(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 3c9142b..86fd932 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -48,9 +48,10 @@ public Payload? PlayerNamePayload get { Payload textPayload = null; - string textMatch = GetMatchText(); + string textMatch = GetMatchTextInternal(); + string textMatchShort = BuildPlayername(textMatch); - textPayload = DisplayTextPayloads.FirstOrDefault(n => n is TextPayload textPayload && textPayload.Text.Contains(textMatch)); + textPayload = DisplayTextPayloads.FirstOrDefault(n => n is TextPayload textPayload && (textPayload.Text.Contains(textMatch) || ((!string.IsNullOrEmpty(textMatchShort)) && textPayload.Text.Contains(textMatchShort)))); textPayload ??= PlayerPayload; textPayload ??= DisplayTextPayloads.FirstOrDefault(); @@ -63,23 +64,29 @@ public StringMatch(SeString seString) SeString = seString; } + private string GetMatchTextInternal() + { + if (GameObject != null) + return GameObject.Name.TextValue; + else if (PlayerPayload != null) + return PlayerPayload.PlayerName; + else + return SeString.TextValue; + } + /// /// Gets the matches text. /// /// The match text. public string GetMatchText() { - if (GameObject != null) - { - return GameObject.Name.TextValue; - } - - if (PlayerPayload != null) - { - return PlayerPayload.PlayerName; - } - - return SeString.TextValue; + var playerNamePayload = PlayerNamePayload; + if (playerNamePayload is PlayerPayload pp) + return pp.PlayerName; + else if (playerNamePayload is TextPayload tp) + return tp.Text; + else + return SeString.TextValue; } } @@ -182,44 +189,6 @@ void finishCurrentMatch() return stringMatches; } - private string BuildPlayername(string name) - { - var logNameType = GameConfigHelper.Instance.GetLogNameType(); - var result = string.Empty; - - if (logNameType != null) - { - var nameSplitted = name.Split(' '); - - if (nameSplitted.Length > 1) - { - var firstName = nameSplitted[0]; - var lastName = nameSplitted[1]; - - switch (logNameType) - { - case LogNameType.FullName: - result = $"{firstName} {lastName}"; - break; - case LogNameType.LastNameShorted: - result = $"{firstName} {lastName[..1]}."; - break; - case LogNameType.FirstNameShorted: - result = $"{firstName[..1]}. {lastName}"; - break; - case LogNameType.Initials: - result = $"{firstName[..1]}. {lastName[..1]}."; - break; - } - } - } - - if (string.IsNullOrEmpty(result)) - result = name; - - return result; - } - private void SplitOffPartyNumberPrefix(SeString sender, XivChatType type) { if (type == XivChatType.Party || type == XivChatType.Alliance) @@ -232,7 +201,10 @@ private void SplitOffPartyNumberPrefix(SeString sender, XivChatType type) else if (payload is TextPayload playerNamePayload && lastPlayerPayload != null) { // Get position of player name in payload - var indexOfPlayerName = playerNamePayload.Text.IndexOf(lastPlayerPayload.PlayerName); + var indexOfPlayerName = playerNamePayload.Text.IndexOf(BuildPlayername(lastPlayerPayload.PlayerName)); + + if (indexOfPlayerName == -1) + indexOfPlayerName = playerNamePayload.Text.IndexOf(lastPlayerPayload.PlayerName); if (indexOfPlayerName > 0) { @@ -260,16 +232,16 @@ private void ParsePayloadsForOwnPlayer(SeString seString, XivChatType chatType, List playerTextPayloads = new List(); var playerName = PluginServices.ClientState.LocalPlayer.Name.TextValue; + var playerNameShorted = BuildPlayername(playerName); - if (textPayload.Text == playerName) + if (textPayload.Text == playerName || textPayload.Text == playerNameShorted) { playerTextPayloads.Add(textPayload); - //textPayload.Text = textPayload.Text; - textPayload.Text = playerName; } else { - var textMatchIndex = textPayload.Text.IndexOf(playerName); + var usedPlayerName = chatType == XivChatType.Party || chatType == XivChatType.Alliance ? playerNameShorted : playerName; + var textMatchIndex = textPayload.Text.IndexOf(usedPlayerName); while (textMatchIndex >= 0) { @@ -286,21 +258,21 @@ private void ParsePayloadsForOwnPlayer(SeString seString, XivChatType chatType, } // This is the last reference to the local player in this payload - if (textPayload.Text.Length == playerName.Length) + if (textPayload.Text.Length == usedPlayerName.Length) { playerTextPayloads.Add(textPayload); break; } // Create the new name payload and add it - var playerTextPayload = new TextPayload(playerName); + var playerTextPayload = new TextPayload(usedPlayerName); playerTextPayloads.Add(playerTextPayload); seString.Payloads.Insert(textPayloadIndex, playerTextPayload); // Remove from the chopped text from the original payload - textPayload.Text = textPayload.Text.Substring(playerName.Length); + textPayload.Text = textPayload.Text.Substring(usedPlayerName.Length); - textMatchIndex = textPayload.Text.IndexOf(playerName); + textMatchIndex = textPayload.Text.IndexOf(usedPlayerName); } } @@ -380,7 +352,7 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender var playerName = stringMatch.GetMatchText(); if (playerName != null) { - var generatedName = RandomNameGenerator.Generate(playerName); + var generatedName = BuildPlayername(RandomNameGenerator.Generate(playerName)); if (generatedName != null) { AddPayloadChanges(TagPosition.Replace, Enumerable.Empty().Append(new TextPayload(generatedName)), stringChanges, false); diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index aace99e..34255c0 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -4,6 +4,7 @@ using Dalamud.Game.Text.SeStringHandling.Payloads; using FFXIVClientStructs.FFXIV.Client.Game.Object; using Lumina.Excel.GeneratedSheets; +using PlayerTags.Configuration.GameConfig; using PlayerTags.Data; using PlayerTags.Inheritables; using System; @@ -214,6 +215,44 @@ private void AddSpacesBetweenTextPayloads(List payloads, TagPosition ta } } + protected static string BuildPlayername(string name) + { + var logNameType = GameConfigHelper.Instance.GetLogNameType(); + var result = string.Empty; + + if (logNameType != null && !string.IsNullOrEmpty(name)) + { + var nameSplitted = name.Split(' '); + + if (nameSplitted.Length > 1) + { + var firstName = nameSplitted[0]; + var lastName = nameSplitted[1]; + + switch (logNameType) + { + case LogNameType.FullName: + result = $"{firstName} {lastName}"; + break; + case LogNameType.LastNameShorted: + result = $"{firstName} {lastName[..1]}."; + break; + case LogNameType.FirstNameShorted: + result = $"{firstName[..1]}. {lastName}"; + break; + case LogNameType.Initials: + result = $"{firstName[..1]}. {lastName[..1]}."; + break; + } + } + } + + if (string.IsNullOrEmpty(result)) + result = name; + + return result; + } + /// /// Adds the given payload changes to the dictionary. /// From d6e4b2cbd982b48dfba6730c088ac23523321834 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 20 Sep 2022 07:52:58 +0200 Subject: [PATCH 085/174] change version to v1.7.3 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index a345218..37ad440 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.7.2.0 + 1.7.3.0 From feea8fb43d137f3242ec4eaa5862e53d2e363c41 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 21 Sep 2022 07:21:44 +0200 Subject: [PATCH 086/174] add comment --- PlayerTags/Features/ChatTagTargetFeature.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 86fd932..c39be45 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -290,6 +290,7 @@ private void ParsePayloadsForOwnPlayer(SeString seString, XivChatType chatType, var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); int playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload); + // Ensure to include the group number prefix within the player link if (isSender && (chatType == XivChatType.Party || chatType == XivChatType.Alliance)) playerPayloadIndex--; From 08a3d37f987a9ad77a2b49770c6c67feee00cae1 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 21 Sep 2022 12:09:27 +0200 Subject: [PATCH 087/174] fix: falsly inserted own player name one index postion to low --- PlayerTags/Features/ChatTagTargetFeature.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index c39be45..6cdebc6 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -251,7 +251,7 @@ private void ParsePayloadsForOwnPlayer(SeString seString, XivChatType chatType, if (textMatchIndex > 0) { // Add the content before the player - seString.Payloads.Insert(textPayloadIndex, new TextPayload(textPayload.Text.Substring(0, textMatchIndex))); + seString.Payloads.Insert(textPayloadIndex++, new TextPayload(textPayload.Text.Substring(0, textMatchIndex))); // Remove from the chopped text from the original payload textPayload.Text = textPayload.Text.Substring(textMatchIndex, textPayload.Text.Length - textMatchIndex); From 3f0a533b071e2af59ce1725e919277cbc70f6eb5 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 21 Sep 2022 12:10:36 +0200 Subject: [PATCH 088/174] always remove own player link terminator & workaround for List.Remove() not working as expected --> Fix ExtraChat compatibility --- PlayerTags/Extensions.cs | 41 +++++++++++++++++++++ PlayerTags/Features/ChatTagTargetFeature.cs | 37 +++++++++++++------ PlayerTags/Features/TagTargetFeature.cs | 2 +- 3 files changed, 67 insertions(+), 13 deletions(-) create mode 100644 PlayerTags/Extensions.cs diff --git a/PlayerTags/Extensions.cs b/PlayerTags/Extensions.cs new file mode 100644 index 0000000..964b8e5 --- /dev/null +++ b/PlayerTags/Extensions.cs @@ -0,0 +1,41 @@ +using Dalamud.Game.Text.SeStringHandling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PlayerTags +{ + internal static class Extensions + { + /// + /// Removes a Payload from a given SeString. + /// Using SeString.Payloads.Remove() does not use the reference to compare for some reason. Tis is a workaround. + /// + /// + /// + public static void Remove(this SeString seString, Payload payload) + { + Remove(seString.Payloads, payload); + } + + /// + /// Removes a Payload from a given list. + /// Using List.Remove() does not use the reference to compare for some reason. Tis is a workaround. + /// + /// + /// + public static void Remove(this List payloads, Payload payload) + { + for (int i = 0; i < payloads.Count; i++) + { + if (ReferenceEquals(payloads[i], payload)) + { + payloads.RemoveAt(i); + break; + } + } + } + } +} diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 6cdebc6..22678ba 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -43,6 +43,8 @@ private class StringMatch /// public PlayerPayload? PlayerPayload { get; init; } + public RawPayload LinkTerminatorPayload { get; init; } + public Payload? PlayerNamePayload { get @@ -59,6 +61,14 @@ public Payload? PlayerNamePayload } } + public bool IsLocalPlayer + { + get + { + return GetMatchTextInternal() == PluginServices.ClientState.LocalPlayer.Name.TextValue; + } + } + public StringMatch(SeString seString) { SeString = seString; @@ -159,7 +169,7 @@ private List GetStringMatches(SeString seString) else if (payload is RawPayload rawPayload) { if (defaultRawPayload.SequenceEqual(rawPayload.Data)) - finishCurrentMatch(); + finishCurrentMatch(rawPayload); } else { @@ -169,9 +179,9 @@ private List GetStringMatches(SeString seString) } // Finally finish, if not closed by RawPayload - finishCurrentMatch(); + finishCurrentMatch(null); - void finishCurrentMatch() + void finishCurrentMatch(RawPayload linkTerminatorPayload) { if (curPlayerPayload.TryPop(out PlayerPayload playerPayload)) { @@ -180,6 +190,7 @@ void finishCurrentMatch() { GameObject = gameObject, PlayerPayload = playerPayload, + LinkTerminatorPayload = linkTerminatorPayload, DisplayTextPayloads = curRefPayloads.Pop() }; stringMatches.Add(stringMatch); @@ -299,13 +310,13 @@ private void ParsePayloadsForOwnPlayer(SeString seString, XivChatType chatType, // Add the Link Terminator to end the Player Link. This should be done behind the Text Payload (display text). // Normally used to end PlayerPayload linking. But for the own player it has no affect. Anyway, use it, just because. Maybe it's needed in the future somewhere else. - //seString.Payloads.Insert(++playerPayloadIndex, RawPayload.LinkTerminator); + seString.Payloads.Insert(++playerPayloadIndex, RawPayload.LinkTerminator); // Remove TextPayload - //seString.Payloads.Remove(playerTextPayload); + //seString.Remove(playerTextPayload); // I M P O R T A N T N O T I C E: - // The PlayerPayload is now just temporary. We keep the TextPayload don't add the LinkTerminator. + // The PlayerPayload is now just temporary. We keep the TextPayload. // The PayerPayload gets removed at the ChatTagTargetFeature at the end and the TextPayload will be keeped there. } } @@ -405,13 +416,15 @@ void applyTextFormatting(Tag tag) } ApplyStringChanges(message, stringChanges, stringMatch.DisplayTextPayloads, stringMatch.PlayerNamePayload); - } - // Replace PlayerPayloads of your own character with TextPayloads - foreach (var payload in message.Payloads.ToArray()) - { - if (payload is PlayerPayload playerPayload && playerPayload.PlayerName.Contains(PluginServices.ClientState.LocalPlayer.Name.TextValue)) - message.Payloads.Remove(payload); + // Remove PlayerPayload and LinkTerminator if it's your own character (they just got added temporary) + if (stringMatch.IsLocalPlayer) + { + if (stringMatch.PlayerPayload != null) + message.Remove(stringMatch.PlayerPayload); + if (stringMatch.LinkTerminatorPayload != null) + message.Remove(stringMatch.LinkTerminatorPayload); + } } } } diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index 34255c0..eb2be97 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -342,7 +342,7 @@ protected void ApplyStringChanges(SeString seString, Dictionary Date: Wed, 21 Sep 2022 12:57:29 +0200 Subject: [PATCH 089/174] update some comments --- PlayerTags/Features/ChatTagTargetFeature.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 22678ba..7e61442 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -292,12 +292,6 @@ private void ParsePayloadsForOwnPlayer(SeString seString, XivChatType chatType, // Fix displaying of abbreviated own player name as the game does this after the chat message handler playerTextPayload.Text = BuildPlayername(playerTextPayload.Text); - // This does some dodgy shit for an unknown reason. - // Typically when you receive a player payload followed by a text payload, it displays the text - // and links it with the player payload. When trying to make one of these manually, it displays the player payload separately, - // effectively doubling up the player name. - // For now, don't follow up with a text payload. Only use a player payload. - var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); int playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload); @@ -312,9 +306,6 @@ private void ParsePayloadsForOwnPlayer(SeString seString, XivChatType chatType, // Normally used to end PlayerPayload linking. But for the own player it has no affect. Anyway, use it, just because. Maybe it's needed in the future somewhere else. seString.Payloads.Insert(++playerPayloadIndex, RawPayload.LinkTerminator); - // Remove TextPayload - //seString.Remove(playerTextPayload); - // I M P O R T A N T N O T I C E: // The PlayerPayload is now just temporary. We keep the TextPayload. // The PayerPayload gets removed at the ChatTagTargetFeature at the end and the TextPayload will be keeped there. From 6612c13a7a08a0a26ce68fbf119050333c73680b Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 21 Sep 2022 12:58:20 +0200 Subject: [PATCH 090/174] add more comments --- PlayerTags/Features/ChatTagTargetFeature.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 7e61442..eb2778f 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -406,6 +406,7 @@ void applyTextFormatting(Tag tag) => ApplyTextFormatting(stringMatch.GameObject, tag, new[] { message }, new[] { tag.IsTextColorAppliedToChatName }, stringMatch.DisplayTextPayloads); } + // Finally apply the all the changes to the message ApplyStringChanges(message, stringChanges, stringMatch.DisplayTextPayloads, stringMatch.PlayerNamePayload); // Remove PlayerPayload and LinkTerminator if it's your own character (they just got added temporary) From 71d0c9e77199c5fdd3d5c8a7d1cf613eef86ec42 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 21 Sep 2022 13:38:05 +0200 Subject: [PATCH 091/174] change version to v1.7.4 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 37ad440..0cb8b8b 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.7.3.0 + 1.7.4.0 From 84332da133f753b0b8437cabdef3ad9057ea2af4 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 21 Sep 2022 14:32:39 +0200 Subject: [PATCH 092/174] rename plugin to "PlayerTags" --- PlayerTags/PlayerTags.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PlayerTags/PlayerTags.json b/PlayerTags/PlayerTags.json index 60d41a1..51d3bb4 100644 --- a/PlayerTags/PlayerTags.json +++ b/PlayerTags/PlayerTags.json @@ -1,6 +1,6 @@ { - "Author": "r00telement, Pilzinsel64", - "Name": "Player Tags", + "Author": "Pilzinsel64", + "Name": "PlayerTags", "Description": "Lightweight job visibility in nameplates and chat. Create custom tags and add them to players with the context menu.\n\nYou want to contribute and help developing new features or want to extend existing? Feel free to open Fork and open a Pull Request!\n\nThis plugin was originally developed by r00telement but forked and continued by Pilzinsel64.", "Punchline": "Lightweight job visibility in nameplates and chat.", "Tags": [ "Jobs", "UI" ], From aab6cb781c3d962759fb65b5a91ecf3011ca0bf0 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 21 Sep 2022 14:32:39 +0200 Subject: [PATCH 093/174] rename plugin to "PlayerTags" --- PlayerTags/PlayerTags.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PlayerTags/PlayerTags.json b/PlayerTags/PlayerTags.json index 60d41a1..797210d 100644 --- a/PlayerTags/PlayerTags.json +++ b/PlayerTags/PlayerTags.json @@ -1,6 +1,6 @@ { - "Author": "r00telement, Pilzinsel64", - "Name": "Player Tags", + "Author": "Pilzinsel64, r00telement", + "Name": "PlayerTags", "Description": "Lightweight job visibility in nameplates and chat. Create custom tags and add them to players with the context menu.\n\nYou want to contribute and help developing new features or want to extend existing? Feel free to open Fork and open a Pull Request!\n\nThis plugin was originally developed by r00telement but forked and continued by Pilzinsel64.", "Punchline": "Lightweight job visibility in nameplates and chat.", "Tags": [ "Jobs", "UI" ], From b0210a940fe30eee482b8bf75498a2ed6a847e50 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 21 Sep 2022 15:02:31 +0200 Subject: [PATCH 094/174] ensure +1 with number prefix at own name --- PlayerTags/Features/ChatTagTargetFeature.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index eb2778f..53268b1 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -294,14 +294,19 @@ private void ParsePayloadsForOwnPlayer(SeString seString, XivChatType chatType, var playerPayload = new PlayerPayload(playerName, PluginServices.ClientState.LocalPlayer.HomeWorld.Id); int playerPayloadIndex = seString.Payloads.IndexOf(playerTextPayload); + var hasNumberPrefix = isSender && (chatType == XivChatType.Party || chatType == XivChatType.Alliance); // Ensure to include the group number prefix within the player link - if (isSender && (chatType == XivChatType.Party || chatType == XivChatType.Alliance)) + if (hasNumberPrefix) playerPayloadIndex--; // Add the Player Link Payload seString.Payloads.Insert(playerPayloadIndex++, playerPayload); + // Same as above, but reverse + if (hasNumberPrefix) + playerPayloadIndex++; + // Add the Link Terminator to end the Player Link. This should be done behind the Text Payload (display text). // Normally used to end PlayerPayload linking. But for the own player it has no affect. Anyway, use it, just because. Maybe it's needed in the future somewhere else. seString.Payloads.Insert(++playerPayloadIndex, RawPayload.LinkTerminator); From 2a18141c3591e6abb12b990c192f2c986702efa5 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 25 Sep 2022 10:22:30 +0200 Subject: [PATCH 095/174] simplyfy Nameplate_PlayerNameplateUpdated --- PlayerTags/Features/NameplateTagTargetFeature.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index 4146f05..1bd6379 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -101,23 +101,24 @@ private void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs args) { var beforeTitleBytes = args.Title.Encode(); AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany); - - if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].NameplateTitlePosition == NameplateTitlePosition.AlwaysAboveName) + var generalOptions = m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext]; + + if (generalOptions.NameplateTitlePosition == NameplateTitlePosition.AlwaysAboveName) args.IsTitleAboveName = true; - else if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].NameplateTitlePosition == NameplateTitlePosition.AlwaysBelowName) + else if (generalOptions.NameplateTitlePosition == NameplateTitlePosition.AlwaysBelowName) args.IsTitleAboveName = false; - if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].NameplateTitleVisibility == NameplateTitleVisibility.Always) + if (generalOptions.NameplateTitleVisibility == NameplateTitleVisibility.Always) args.IsTitleVisible = true; - else if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].NameplateTitleVisibility == NameplateTitleVisibility.Never) + else if (generalOptions.NameplateTitleVisibility == NameplateTitleVisibility.Never) args.IsTitleVisible = false; - else if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].NameplateTitleVisibility == NameplateTitleVisibility.WhenHasTags) + else if (generalOptions.NameplateTitleVisibility == NameplateTitleVisibility.WhenHasTags) { bool hasTitleChanged = !beforeTitleBytes.SequenceEqual(args.Title.Encode()); args.IsTitleVisible = hasTitleChanged; } - if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].NameplateFreeCompanyVisibility == NameplateFreeCompanyVisibility.Never) + if (generalOptions.NameplateFreeCompanyVisibility == NameplateFreeCompanyVisibility.Never) args.FreeCompany.Payloads.Clear(); } From 299c741bb6036e658959c5bd7fad792c7efada06 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 25 Sep 2022 11:43:44 +0200 Subject: [PATCH 096/174] force custom tag color in chat for name --- PlayerTags/Features/ChatTagTargetFeature.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 53268b1..7dae7be 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -394,12 +394,6 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender if (stringMatch.PlayerPayload != null && stringMatch.DisplayTextPayloads.Any()) { Identity identity = m_PluginData.GetIdentity(stringMatch.PlayerPayload); - foreach (var customTagId in identity.CustomTagIds) - { - var customTag = m_PluginData.CustomTags.FirstOrDefault(tag => tag.CustomId.Value == customTagId); - if (customTag != null) - applyTextFormatting(customTag); - } if (stringMatch.GameObject is PlayerCharacter playerCharacter1) { @@ -407,6 +401,13 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender applyTextFormatting(jobTag); } + foreach (var customTagId in identity.CustomTagIds) + { + var customTag = m_PluginData.CustomTags.FirstOrDefault(tag => tag.CustomId.Value == customTagId); + if (customTag != null) + applyTextFormatting(customTag); + } + void applyTextFormatting(Tag tag) => ApplyTextFormatting(stringMatch.GameObject, tag, new[] { message }, new[] { tag.IsTextColorAppliedToChatName }, stringMatch.DisplayTextPayloads); } From 755faa6f8136018a03a3d82571374093740e4add Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 25 Sep 2022 14:24:51 +0200 Subject: [PATCH 097/174] fix not inserting at number prefix for custom tags --- PlayerTags/Features/ChatTagTargetFeature.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 7dae7be..a3518b3 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -8,6 +8,7 @@ using PlayerTags.Configuration; using PlayerTags.Configuration.GameConfig; using PlayerTags.Data; +using PlayerTags.Inheritables; using System; using System.Collections.Generic; using System.Data; @@ -349,7 +350,7 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender if (payloads.Any()) { var insertBehindNumberPrefix = jobTag.InsertBehindNumberPrefixInChat?.Value ?? true; - AddPayloadChanges(jobTag.TagPositionInChat.InheritedValue.Value, payloads, stringChanges, insertBehindNumberPrefix); + addPayloadChanges(jobTag, payloads); } } } @@ -383,13 +384,21 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender var customTagPayloads = GetPayloads(customTag, stringMatch.GameObject); if (customTagPayloads.Any()) { - AddPayloadChanges(customTag.TagPositionInChat.InheritedValue.Value, customTagPayloads, stringChanges, false); + var insertBehindNumberPrefix = customTag.InsertBehindNumberPrefixInChat?.Value ?? true; + addPayloadChanges(customTag, customTagPayloads); } } } } } + void addPayloadChanges(Tag tag, IEnumerable payloads) + { + var insertBehindNumberPrefix = tag.InsertBehindNumberPrefixInChat?.Value ?? true; + var insertPositionInChat = tag.TagPositionInChat.InheritedValue.Value; + AddPayloadChanges(insertPositionInChat, payloads, stringChanges, insertBehindNumberPrefix); + } + // An additional step to apply text color to additional locations if (stringMatch.PlayerPayload != null && stringMatch.DisplayTextPayloads.Any()) { From 6784cd3405a2b65d8e1d071e54507a275d634243 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 25 Sep 2022 14:25:08 +0200 Subject: [PATCH 098/174] change version to v1.7.5 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 0cb8b8b..3a09638 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.7.4.0 + 1.7.5.0 From 454231842c62debf71edeb8656bb8da654ee282e Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 30 Oct 2022 09:24:37 +0100 Subject: [PATCH 099/174] completely remove ChatTwo references --- PlayerTags/Plugin.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index 4d4017d..3c19836 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -16,7 +16,6 @@ public sealed class Plugin : IDalamudPlugin { public string Name => "PlayerTags"; private const string c_CommandName = "/playertags"; - private const string c_ChatTwo_InternalPluginName = "ChatTwo"; private PluginConfiguration m_PluginConfiguration; private PluginData m_PluginData; From 2d485b5e6612270776f3978a37429c08a2b3db32 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 30 Oct 2022 09:26:57 +0100 Subject: [PATCH 100/174] rename plugin to "Player Tags" for better searchability --- PlayerTags/Plugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index 3c19836..293885d 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -14,7 +14,7 @@ namespace PlayerTags { public sealed class Plugin : IDalamudPlugin { - public string Name => "PlayerTags"; + public string Name => "Player Tags"; private const string c_CommandName = "/playertags"; private PluginConfiguration m_PluginConfiguration; From 75d12c93139775712369fd7055e69b1fde61a24b Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 30 Oct 2022 09:27:45 +0100 Subject: [PATCH 101/174] change version to v1.7.5.1 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 3a09638..f1a8fd5 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.7.5.0 + 1.7.5.1 From ae5f2b8a5551734dbec804017e831081a3f3c067 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 30 Oct 2022 09:29:06 +0100 Subject: [PATCH 102/174] change title to "Player Tags" in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dfdbfd3..61f58dc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# PlayerTags +# Player Tags Lightweight job visibility in nameplates and chat. Create custom tags and add them to players with the context menu. From 8e1567a24047398370b23edb0b6aa44d2efbc0d4 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 30 Oct 2022 09:33:17 +0100 Subject: [PATCH 103/174] adjust "name" in PlayerTags.json --- PlayerTags/PlayerTags.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.json b/PlayerTags/PlayerTags.json index 797210d..88fc079 100644 --- a/PlayerTags/PlayerTags.json +++ b/PlayerTags/PlayerTags.json @@ -1,6 +1,6 @@ { "Author": "Pilzinsel64, r00telement", - "Name": "PlayerTags", + "Name": "Player Tags", "Description": "Lightweight job visibility in nameplates and chat. Create custom tags and add them to players with the context menu.\n\nYou want to contribute and help developing new features or want to extend existing? Feel free to open Fork and open a Pull Request!\n\nThis plugin was originally developed by r00telement but forked and continued by Pilzinsel64.", "Punchline": "Lightweight job visibility in nameplates and chat.", "Tags": [ "Jobs", "UI" ], From d19dbe4d09c2507d0718b7d7f051b878f7926180 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 2 Nov 2022 06:43:52 +0100 Subject: [PATCH 104/174] remove unused delegate --- PlayerTags/GameInterface/Nameplates/Nameplate.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/PlayerTags/GameInterface/Nameplates/Nameplate.cs b/PlayerTags/GameInterface/Nameplates/Nameplate.cs index 468c37e..f2bbb38 100644 --- a/PlayerTags/GameInterface/Nameplates/Nameplate.cs +++ b/PlayerTags/GameInterface/Nameplates/Nameplate.cs @@ -15,8 +15,6 @@ namespace PlayerTags.GameInterface.Nameplates /// public class Nameplate : IDisposable { - private delegate IntPtr SetPlayerNameplateDelegate_Unmanaged(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId); - [Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 56 41 57 48 83 EC 40 44 0F B6 E2", DetourName = nameof(SetPlayerNameplateDetour))] private readonly Hook? hook_AddonNamePlate_SetPlayerNameplateDetour = null; private unsafe delegate IntPtr AddonNamePlate_SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId); From 74ddb9e7c69278d680ded1be5993e463296e3bed Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 5 Nov 2022 15:17:26 +0100 Subject: [PATCH 105/174] integrate new ActivityContext --- PlayerTags.sln | 10 +++- .../Configuration/PluginConfiguration.cs | 22 ++++++-- .../Configuration/PluginConfigurationUI.cs | 13 ++--- PlayerTags/Data/ActivityContext.cs | 1 + PlayerTags/Data/ActivityContextHelper.cs | 18 +++---- PlayerTags/Data/ActivityContextManager.cs | 50 ------------------- PlayerTags/Features/ChatTagTargetFeature.cs | 2 +- .../Features/NameplateTagTargetFeature.cs | 2 +- PlayerTags/Features/TagTargetFeature.cs | 3 +- PlayerTags/PlayerTags.csproj | 1 + PlayerTags/packages.lock.json | 3 ++ 11 files changed, 49 insertions(+), 76 deletions(-) delete mode 100644 PlayerTags/Data/ActivityContextManager.cs diff --git a/PlayerTags.sln b/PlayerTags.sln index c058c5e..0219690 100644 --- a/PlayerTags.sln +++ b/PlayerTags.sln @@ -1,10 +1,12 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29709.97 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32929.385 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlayerTags", "PlayerTags\PlayerTags.csproj", "{13C812E9-0D42-4B95-8646-40EEBF30636F}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pilz.Dalamud", "..\Pilz.Dalamud\Pilz.Dalamud\Pilz.Dalamud.csproj", "{A92D2FFC-FDB8-4F28-B5DD-4A1B3EB0B1BB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -15,6 +17,10 @@ Global {13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|x64.Build.0 = Debug|x64 {13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.ActiveCfg = Release|x64 {13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.Build.0 = Release|x64 + {A92D2FFC-FDB8-4F28-B5DD-4A1B3EB0B1BB}.Debug|x64.ActiveCfg = Debug|x64 + {A92D2FFC-FDB8-4F28-B5DD-4A1B3EB0B1BB}.Debug|x64.Build.0 = Debug|x64 + {A92D2FFC-FDB8-4F28-B5DD-4A1B3EB0B1BB}.Release|x64.ActiveCfg = Release|x64 + {A92D2FFC-FDB8-4F28-B5DD-4A1B3EB0B1BB}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index 245930d..7c66f13 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -1,5 +1,6 @@ using Dalamud.Configuration; using Newtonsoft.Json; +using Pilz.Dalamud.ActivityContexts; using PlayerTags.Data; using PlayerTags.Inheritables; using System; @@ -19,11 +20,24 @@ public class PluginConfiguration : IPluginConfiguration private const NameplateTitlePosition DefaultNameplateTitlePosition = Data.NameplateTitlePosition.AlwaysAboveName; private const bool DefaultIsApplyTagsToAllChatMessagesEnabled = true; - public Dictionary GeneralOptions = new Dictionary() + [Obsolete] + [JsonProperty("GeneralOptions")] + private Dictionary GeneralOptionsV1 { - { ActivityContext.None, new GeneralOptionsClass() }, - { ActivityContext.PveDuty, new GeneralOptionsClass() }, - { ActivityContext.PvpDuty, new GeneralOptionsClass() } + set + { + GeneralOptions.Clear(); + foreach (var kvp in value) + GeneralOptions.Add((ActivityType)kvp.Key, kvp.Value); + } + } + + [JsonProperty("GeneralOptionsV2")] + public Dictionary GeneralOptions = new() + { + { ActivityType.None, new GeneralOptionsClass() }, + { ActivityType.PveDuty, new GeneralOptionsClass() }, + { ActivityType.PvpDuty, new GeneralOptionsClass() } }; public bool IsPlayerNameRandomlyGenerated = false; diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index 078c69a..9f2f923 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -5,6 +5,7 @@ using Dalamud.Logging; using ImGuiNET; using Lumina.Excel.GeneratedSheets; +using Pilz.Dalamud.ActivityContexts; using PlayerTags.Data; using PlayerTags.Inheritables; using PlayerTags.PluginStrings; @@ -1233,7 +1234,7 @@ public void SaveData() applyChanges(GetActivityContext(CurrentActivityContext)); } - void applyChanges(ActivityContext key) + void applyChanges(ActivityType key) { pluginConfig.GeneralOptions[key].NameplateFreeCompanyVisibility = NameplateFreeCompanyVisibility; pluginConfig.GeneralOptions[key].NameplateTitleVisibility = NameplateTitleVisibility; @@ -1242,22 +1243,22 @@ void applyChanges(ActivityContext key) } } - private ActivityContext GetActivityContext(ActivityContextSelection selection) + private ActivityType GetActivityContext(ActivityContextSelection selection) { - ActivityContext result; + ActivityType result; switch (selection) { case ActivityContextSelection.PveDuty: - result = ActivityContext.PveDuty; + result = ActivityType.PveDuty; break; case ActivityContextSelection.PvpDuty: - result = ActivityContext.PvpDuty; + result = ActivityType.PvpDuty; break; case ActivityContextSelection.All: case ActivityContextSelection.None: default: - result = ActivityContext.None; + result = ActivityType.None; break; } diff --git a/PlayerTags/Data/ActivityContext.cs b/PlayerTags/Data/ActivityContext.cs index 6b5ef7c..ec78386 100644 --- a/PlayerTags/Data/ActivityContext.cs +++ b/PlayerTags/Data/ActivityContext.cs @@ -3,6 +3,7 @@ namespace PlayerTags.Data { + [Obsolete] [Flags] [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum ActivityContext diff --git a/PlayerTags/Data/ActivityContextHelper.cs b/PlayerTags/Data/ActivityContextHelper.cs index c843b33..cf82c52 100644 --- a/PlayerTags/Data/ActivityContextHelper.cs +++ b/PlayerTags/Data/ActivityContextHelper.cs @@ -1,25 +1,21 @@ -namespace PlayerTags.Data +using Pilz.Dalamud.ActivityContexts; + +namespace PlayerTags.Data { public static class ActivityContextHelper { - public static bool GetIsVisible(ActivityContext playerContext, bool desiredPveDutyVisibility, bool desiredPvpDutyVisibility, bool desiredOthersVisibility) + public static bool GetIsVisible(ActivityType playerContext, bool desiredPveDutyVisibility, bool desiredPvpDutyVisibility, bool desiredOthersVisibility) { bool isVisible = false; - if (playerContext.HasFlag(ActivityContext.PveDuty)) - { + if (playerContext.HasFlag(ActivityType.PveDuty)) isVisible |= desiredPveDutyVisibility; - } - if (playerContext.HasFlag(ActivityContext.PvpDuty)) - { + if (playerContext.HasFlag(ActivityType.PvpDuty)) isVisible |= desiredPvpDutyVisibility; - } - if (playerContext == ActivityContext.None) - { + if (playerContext == ActivityType.None) isVisible |= desiredOthersVisibility; - } return isVisible; } diff --git a/PlayerTags/Data/ActivityContextManager.cs b/PlayerTags/Data/ActivityContextManager.cs deleted file mode 100644 index 2225db0..0000000 --- a/PlayerTags/Data/ActivityContextManager.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Dalamud.Plugin; -using Lumina.Excel.GeneratedSheets; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace PlayerTags.Data -{ - public class ActivityContextManager : IDisposable - { - private ActivityContext m_CurrentActivityContext; - - public ActivityContext CurrentActivityContext => m_CurrentActivityContext; - - public ActivityContextManager() - { - m_CurrentActivityContext = ActivityContext.None; - PluginServices.ClientState.TerritoryChanged += ClientState_TerritoryChanged; - } - - private void ClientState_TerritoryChanged(object? sender, ushort e) - { - m_CurrentActivityContext = ActivityContext.None; - - var contentFinderConditionsSheet = PluginServices.DataManager.GameData.GetExcelSheet(); - if (contentFinderConditionsSheet != null) - { - var foundContentFinderCondition = contentFinderConditionsSheet.FirstOrDefault(contentFinderCondition => contentFinderCondition.TerritoryType.Row == PluginServices.ClientState.TerritoryType); - if (foundContentFinderCondition != null) - { - if (foundContentFinderCondition.PvP) - { - m_CurrentActivityContext = ActivityContext.PvpDuty; - } - else - { - m_CurrentActivityContext = ActivityContext.PveDuty; - } - } - } - } - - public void Dispose() - { - PluginServices.ClientState.TerritoryChanged -= ClientState_TerritoryChanged; - } - } -} diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index a3518b3..22d1560 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -120,7 +120,7 @@ public override void Dispose() private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) { - if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext].IsApplyTagsToAllChatMessagesEnabled || Enum.IsDefined(type)) + if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType].IsApplyTagsToAllChatMessagesEnabled || Enum.IsDefined(type)) { AddTagsToChat(sender, type, true); AddTagsToChat(message, type, false); diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index 1bd6379..9e30923 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -101,7 +101,7 @@ private void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs args) { var beforeTitleBytes = args.Title.Encode(); AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany); - var generalOptions = m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext]; + var generalOptions = m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType]; if (generalOptions.NameplateTitlePosition == NameplateTitlePosition.AlwaysAboveName) args.IsTitleAboveName = true; diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index eb2be97..ae5d457 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -4,6 +4,7 @@ using Dalamud.Game.Text.SeStringHandling.Payloads; using FFXIVClientStructs.FFXIV.Client.Game.Object; using Lumina.Excel.GeneratedSheets; +using Pilz.Dalamud.ActivityContexts; using PlayerTags.Configuration.GameConfig; using PlayerTags.Data; using PlayerTags.Inheritables; @@ -44,7 +45,7 @@ public virtual void Dispose() protected bool IsTagVisible(Tag tag, GameObject? gameObject) { - bool isVisibleForActivity = ActivityContextHelper.GetIsVisible(ActivityContextManager.CurrentActivityContext, + bool isVisibleForActivity = ActivityContextHelper.GetIsVisible(ActivityContextManager.CurrentActivityContext.ActivityType, tag.IsVisibleInPveDuties.InheritedValue ?? false, tag.IsVisibleInPvpDuties.InheritedValue ?? false, tag.IsVisibleInOverworld.InheritedValue ?? false); diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index f1a8fd5..b16c921 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -26,6 +26,7 @@ + $(DalamudLibPath)FFXIVClientStructs.dll false diff --git a/PlayerTags/packages.lock.json b/PlayerTags/packages.lock.json index abf5900..d25458d 100644 --- a/PlayerTags/packages.lock.json +++ b/PlayerTags/packages.lock.json @@ -13,6 +13,9 @@ "requested": "[2.1.8, )", "resolved": "2.1.8", "contentHash": "YqagNXs9InxmqkXzq7kLveImxnodkBEicAhydMXVp7dFjC7xb76U6zGgAax4/BWIWfZeWzr5DJyQSev31kj81A==" + }, + "pilz.dalamud": { + "type": "Project" } } } From b81fe05e5372e3fe03a4848c10d22ce133cbd141 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 5 Nov 2022 15:17:45 +0100 Subject: [PATCH 106/174] remove obsulate default constants --- PlayerTags/Configuration/PluginConfiguration.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index 245930d..7f80754 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -14,11 +14,6 @@ public class PluginConfiguration : IPluginConfiguration public int Version { get; set; } = 0; public bool IsVisible = false; - private const NameplateFreeCompanyVisibility DefaultNameplateFreeCompanyVisibility = Data.NameplateFreeCompanyVisibility.Default; - private const NameplateTitleVisibility DefaultNameplateTitleVisibility = Data.NameplateTitleVisibility.WhenHasTags; - private const NameplateTitlePosition DefaultNameplateTitlePosition = Data.NameplateTitlePosition.AlwaysAboveName; - private const bool DefaultIsApplyTagsToAllChatMessagesEnabled = true; - public Dictionary GeneralOptions = new Dictionary() { { ActivityContext.None, new GeneralOptionsClass() }, From 1b672513ae95924eece10c5614d27734b6efc2a8 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 5 Nov 2022 15:19:40 +0100 Subject: [PATCH 107/174] fix merge conflicts --- PlayerTags/Configuration/PluginConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index 6c1b5c6..7c66f13 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -33,7 +33,7 @@ public class PluginConfiguration : IPluginConfiguration } [JsonProperty("GeneralOptionsV2")] - public Dictionary GeneralOptions = new Dictionary() + public Dictionary GeneralOptions = new() { { ActivityType.None, new GeneralOptionsClass() }, { ActivityType.PveDuty, new GeneralOptionsClass() }, From d38d974aa62dd31a92c7e6a9ea3be095daa24b08 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 5 Nov 2022 15:27:10 +0100 Subject: [PATCH 108/174] initialize Pilz.Dalamud lib --- PlayerTags/Plugin.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index 293885d..97efc53 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -28,6 +28,7 @@ public sealed class Plugin : IDalamudPlugin public Plugin(DalamudPluginInterface pluginInterface) { PluginServices.Initialize(pluginInterface); + Pilz.Dalamud.PluginServices.Initialize(pluginInterface); m_PluginConfiguration = PluginServices.DalamudPluginInterface.GetPluginConfig() as PluginConfiguration ?? new PluginConfiguration(); m_PluginData = new PluginData(m_PluginConfiguration); From 6644b1edb823069fa4e0e3b2e66c69c191c298ac Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 5 Nov 2022 20:27:23 +0100 Subject: [PATCH 109/174] some work --- .../Configuration/PluginConfiguration.cs | 5 - .../GameInterface/Nameplates/Nameplate.cs | 127 ++---------------- .../Nameplates/PlayerNameplateUpdatedArgs.cs | 45 +++++-- 3 files changed, 44 insertions(+), 133 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index 7c66f13..3c5761b 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -15,11 +15,6 @@ public class PluginConfiguration : IPluginConfiguration public int Version { get; set; } = 0; public bool IsVisible = false; - private const NameplateFreeCompanyVisibility DefaultNameplateFreeCompanyVisibility = Data.NameplateFreeCompanyVisibility.Default; - private const NameplateTitleVisibility DefaultNameplateTitleVisibility = Data.NameplateTitleVisibility.WhenHasTags; - private const NameplateTitlePosition DefaultNameplateTitlePosition = Data.NameplateTitlePosition.AlwaysAboveName; - private const bool DefaultIsApplyTagsToAllChatMessagesEnabled = true; - [Obsolete] [JsonProperty("GeneralOptions")] private Dictionary GeneralOptionsV1 diff --git a/PlayerTags/GameInterface/Nameplates/Nameplate.cs b/PlayerTags/GameInterface/Nameplates/Nameplate.cs index f2bbb38..62c5350 100644 --- a/PlayerTags/GameInterface/Nameplates/Nameplate.cs +++ b/PlayerTags/GameInterface/Nameplates/Nameplate.cs @@ -4,7 +4,9 @@ using Dalamud.Logging; using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.UI; +using Pilz.Dalamud.Nameplates; using System; +using System.Diagnostics.Tracing; using System.Linq; using System.Runtime.InteropServices; @@ -15,9 +17,7 @@ namespace PlayerTags.GameInterface.Nameplates /// public class Nameplate : IDisposable { - [Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 56 41 57 48 83 EC 40 44 0F B6 E2", DetourName = nameof(SetPlayerNameplateDetour))] - private readonly Hook? hook_AddonNamePlate_SetPlayerNameplateDetour = null; - private unsafe delegate IntPtr AddonNamePlate_SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId); + public NameplateManager NameplateManager { get; init; } /// /// Occurs when a player nameplate is updated by the game. @@ -29,140 +29,37 @@ public class Nameplate : IDisposable /// public bool IsValid { - get - { - return hook_AddonNamePlate_SetPlayerNameplateDetour != null - && hook_AddonNamePlate_SetPlayerNameplateDetour.IsEnabled; - } + get => NameplateManager != null && NameplateManager.IsValid; } public Nameplate() { - SignatureHelper.Initialise(this); - hook_AddonNamePlate_SetPlayerNameplateDetour?.Enable(); + NameplateManager = new(); + NameplateManager.Hooks.AddonNamePlate_SetPlayerNameManaged += Hooks_AddonNamePlate_SetPlayerNameManaged; } public void Dispose() { - hook_AddonNamePlate_SetPlayerNameplateDetour?.Disable(); + NameplateManager.Hooks.AddonNamePlate_SetPlayerNameManaged -= Hooks_AddonNamePlate_SetPlayerNameManaged; + NameplateManager.Dispose(); } - private IntPtr SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId) + private void Hooks_AddonNamePlate_SetPlayerNameManaged(Pilz.Dalamud.Nameplates.EventArgs.AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs) { - if (hook_AddonNamePlate_SetPlayerNameplateDetour == null) - { - return IntPtr.Zero; - } - try { - PlayerCharacter? playerCharacter = GetNameplateGameObject(playerNameplateObjectPtr); + PlayerCharacter? playerCharacter = NameplateManager.GetNameplateGameObject(eventArgs.SafeNameplateObject); + if (playerCharacter != null) { - PlayerNameplateUpdatedArgs playerNameplateUpdatedArgs = new PlayerNameplateUpdatedArgs( - playerCharacter, - GameInterfaceHelper.ReadSeString(namePtr), - GameInterfaceHelper.ReadSeString(titlePtr), - GameInterfaceHelper.ReadSeString(freeCompanyPtr), - isTitleVisible, - isTitleAboveName, - iconId); - - byte[] beforeNameBytes = playerNameplateUpdatedArgs.Name.Encode(); - byte[] beforeTitleBytes = playerNameplateUpdatedArgs.Title.Encode(); - byte[] beforeFreeCompanyBytes = playerNameplateUpdatedArgs.FreeCompany.Encode(); - + var playerNameplateUpdatedArgs = new PlayerNameplateUpdatedArgs(playerCharacter, eventArgs); PlayerNameplateUpdated?.Invoke(playerNameplateUpdatedArgs); - - byte[] afterNameBytes = playerNameplateUpdatedArgs.Name.Encode(); - byte[] afterTitleBytes = playerNameplateUpdatedArgs.Title.Encode(); - byte[] afterFreeCompanyBytes = playerNameplateUpdatedArgs.FreeCompany.Encode(); - - IntPtr newNamePtr = namePtr; - bool hasNameChanged = !beforeNameBytes.SequenceEqual(afterNameBytes); - if (hasNameChanged) - { - newNamePtr = GameInterfaceHelper.PluginAllocate(afterNameBytes); - } - - IntPtr newTitlePtr = titlePtr; - bool hasTitleChanged = !beforeTitleBytes.SequenceEqual(afterTitleBytes); - if (hasTitleChanged) - { - newTitlePtr = GameInterfaceHelper.PluginAllocate(afterTitleBytes); - } - - IntPtr newFreeCompanyPtr = freeCompanyPtr; - bool hasFreeCompanyChanged = !beforeFreeCompanyBytes.SequenceEqual(afterFreeCompanyBytes); - if (hasFreeCompanyChanged) - { - newFreeCompanyPtr = GameInterfaceHelper.PluginAllocate(afterFreeCompanyBytes); - } - - var result = hook_AddonNamePlate_SetPlayerNameplateDetour.Original(playerNameplateObjectPtr, playerNameplateUpdatedArgs.IsTitleAboveName, playerNameplateUpdatedArgs.IsTitleVisible, newTitlePtr, newNamePtr, newFreeCompanyPtr, playerNameplateUpdatedArgs.IconId); - - if (hasNameChanged) - { - GameInterfaceHelper.PluginFree(ref newNamePtr); - } - - if (hasTitleChanged) - { - GameInterfaceHelper.PluginFree(ref newTitlePtr); - } - - if (hasFreeCompanyChanged) - { - GameInterfaceHelper.PluginFree(ref newFreeCompanyPtr); - } - - return result; } } catch (Exception ex) { PluginLog.Error(ex, $"SetPlayerNameplateDetour"); } - - return hook_AddonNamePlate_SetPlayerNameplateDetour.Original(playerNameplateObjectPtr, isTitleAboveName, isTitleVisible, titlePtr, namePtr, freeCompanyPtr, iconId); - } - - private T? GetNameplateGameObject(IntPtr nameplateObjectPtr) - where T : GameObject - { - // Get the nameplate object array - var nameplateAddonPtr = PluginServices.GameGui.GetAddonByName("NamePlate", 1); - var nameplateObjectArrayPtrPtr = nameplateAddonPtr + Marshal.OffsetOf(typeof(AddonNamePlate), nameof(AddonNamePlate.NamePlateObjectArray)).ToInt32(); - var nameplateObjectArrayPtr = Marshal.ReadIntPtr(nameplateObjectArrayPtrPtr); - if (nameplateObjectArrayPtr == IntPtr.Zero) - { - return null; - } - - // Determine the index of the nameplate object within the nameplate object array - var namePlateObjectSize = Marshal.SizeOf(typeof(AddonNamePlate.NamePlateObject)); - var namePlateObjectPtr0 = nameplateObjectArrayPtr + namePlateObjectSize * 0; - var namePlateIndex = (nameplateObjectPtr.ToInt64() - namePlateObjectPtr0.ToInt64()) / namePlateObjectSize; - if (namePlateIndex < 0 || namePlateIndex >= AddonNamePlate.NumNamePlateObjects) - { - return null; - } - - // Get the nameplate info array - IntPtr nameplateInfoArrayPtr = IntPtr.Zero; - unsafe - { - var framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance(); - nameplateInfoArrayPtr = new IntPtr(&framework->GetUiModule()->GetRaptureAtkModule()->NamePlateInfoArray); - } - - // Get the nameplate info for the nameplate object - var namePlateInfoPtr = new IntPtr(nameplateInfoArrayPtr.ToInt64() + Marshal.SizeOf(typeof(RaptureAtkModule.NamePlateInfo)) * namePlateIndex); - RaptureAtkModule.NamePlateInfo namePlateInfo = Marshal.PtrToStructure(namePlateInfoPtr); - - // Return the object for its object id - var objectId = namePlateInfo.ObjectID.ObjectID; - return PluginServices.ObjectTable.SearchById(objectId) as T; } } } diff --git a/PlayerTags/GameInterface/Nameplates/PlayerNameplateUpdatedArgs.cs b/PlayerTags/GameInterface/Nameplates/PlayerNameplateUpdatedArgs.cs index 517410a..8621f90 100644 --- a/PlayerTags/GameInterface/Nameplates/PlayerNameplateUpdatedArgs.cs +++ b/PlayerTags/GameInterface/Nameplates/PlayerNameplateUpdatedArgs.cs @@ -1,33 +1,52 @@ using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.Text.SeStringHandling; +using Pilz.Dalamud.Nameplates.EventArgs; namespace PlayerTags.GameInterface.Nameplates { public class PlayerNameplateUpdatedArgs { + private readonly AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs; + public PlayerCharacter PlayerCharacter { get; } - public SeString Name { get; } + public SeString Name + { + get => eventArgs.Name; + } - public SeString Title { get; } + public SeString Title + { + get => eventArgs.Title; + } - public SeString FreeCompany { get; } + public SeString FreeCompany + { + get => eventArgs.FreeCompany; + } - public bool IsTitleVisible { get; set; } + public bool IsTitleVisible + { + get => eventArgs.IsTitleVisible; + set => eventArgs.IsTitleVisible = value; + } - public bool IsTitleAboveName { get; set; } + public bool IsTitleAboveName + { + get => eventArgs.IsTitleAboveName; + set => eventArgs.IsTitleAboveName = value; + } - public int IconId { get; set; } + public int IconId + { + get => eventArgs.IconID; + set => eventArgs.IconID = value; + } - public PlayerNameplateUpdatedArgs(PlayerCharacter playerCharacter, SeString name, SeString title, SeString freeCompany, bool isTitleVisible, bool isTitleAboveName, int iconId) + public PlayerNameplateUpdatedArgs(PlayerCharacter playerCharacter, AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs) { PlayerCharacter = playerCharacter; - Name = name; - Title = title; - FreeCompany = freeCompany; - IsTitleVisible = isTitleVisible; - IsTitleAboveName = isTitleAboveName; - IconId = iconId; + this.eventArgs = eventArgs; } } } From 4025887ac136dbd826efad61fdcbcf538c348548 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 5 Nov 2022 21:15:14 +0100 Subject: [PATCH 110/174] some more teststing code --- PlayerTags/Plugin.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index 97efc53..f71fca2 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -28,7 +28,12 @@ public sealed class Plugin : IDalamudPlugin public Plugin(DalamudPluginInterface pluginInterface) { PluginServices.Initialize(pluginInterface); - Pilz.Dalamud.PluginServices.Initialize(pluginInterface); + Pilz.Dalamud.PluginServices.PluginInterface = pluginInterface; + Pilz.Dalamud.PluginServices.ClientState = PluginServices.ClientState; + Pilz.Dalamud.PluginServices.DataManager = PluginServices.DataManager; + Pilz.Dalamud.PluginServices.GameGui = PluginServices.GameGui; + Pilz.Dalamud.PluginServices.ObjectTable = PluginServices.ObjectTable; + //Pilz.Dalamud.PluginServices.Initialize(pluginInterface); m_PluginConfiguration = PluginServices.DalamudPluginInterface.GetPluginConfig() as PluginConfiguration ?? new PluginConfiguration(); m_PluginData = new PluginData(m_PluginConfiguration); From 1629b973620e658c16e1e91238d0138cc66a01d1 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 5 Nov 2022 21:44:59 +0100 Subject: [PATCH 111/174] use pluginservices initialise again --- PlayerTags/Plugin.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index f71fca2..97efc53 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -28,12 +28,7 @@ public sealed class Plugin : IDalamudPlugin public Plugin(DalamudPluginInterface pluginInterface) { PluginServices.Initialize(pluginInterface); - Pilz.Dalamud.PluginServices.PluginInterface = pluginInterface; - Pilz.Dalamud.PluginServices.ClientState = PluginServices.ClientState; - Pilz.Dalamud.PluginServices.DataManager = PluginServices.DataManager; - Pilz.Dalamud.PluginServices.GameGui = PluginServices.GameGui; - Pilz.Dalamud.PluginServices.ObjectTable = PluginServices.ObjectTable; - //Pilz.Dalamud.PluginServices.Initialize(pluginInterface); + Pilz.Dalamud.PluginServices.Initialize(pluginInterface); m_PluginConfiguration = PluginServices.DalamudPluginInterface.GetPluginConfig() as PluginConfiguration ?? new PluginConfiguration(); m_PluginData = new PluginData(m_PluginConfiguration); From c4baba304e4d7585cc6950d00d1742647db6fb20 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 5 Nov 2022 22:52:44 +0100 Subject: [PATCH 112/174] integrate new StringUpdateFactory and NameplateUpdateFactory --- PlayerTags/Features/ChatTagTargetFeature.cs | 7 +- .../Features/NameplateTagTargetFeature.cs | 45 +++-- PlayerTags/Features/TagTargetFeature.cs | 154 ++---------------- 3 files changed, 35 insertions(+), 171 deletions(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 22d1560..9e25e90 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -5,6 +5,7 @@ using Dalamud.Game.Text.SeStringHandling.Payloads; using FFXIVClientStructs.FFXIV.Client.UI.Misc; using Lumina.Excel.GeneratedSheets; +using Pilz.Dalamud.Tools.Strings; using PlayerTags.Configuration; using PlayerTags.Configuration.GameConfig; using PlayerTags.Data; @@ -337,7 +338,7 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender var stringMatches = GetStringMatches(message); foreach (var stringMatch in stringMatches) { - Dictionary stringChanges = new Dictionary(); + StringChanges stringChanges = new(); if (stringMatch.GameObject is PlayerCharacter playerCharacter) { @@ -364,7 +365,7 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender var generatedName = BuildPlayername(RandomNameGenerator.Generate(playerName)); if (generatedName != null) { - AddPayloadChanges(TagPosition.Replace, Enumerable.Empty().Append(new TextPayload(generatedName)), stringChanges, false); + AddPayloadChanges(StringPosition.Replace, Enumerable.Empty().Append(new TextPayload(generatedName)), stringChanges, false); } } } @@ -396,7 +397,7 @@ void addPayloadChanges(Tag tag, IEnumerable payloads) { var insertBehindNumberPrefix = tag.InsertBehindNumberPrefixInChat?.Value ?? true; var insertPositionInChat = tag.TagPositionInChat.InheritedValue.Value; - AddPayloadChanges(insertPositionInChat, payloads, stringChanges, insertBehindNumberPrefix); + AddPayloadChanges((StringPosition)insertPositionInChat, payloads, stringChanges, insertBehindNumberPrefix); } // An additional step to apply text color to additional locations diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index 9e30923..869e968 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -3,6 +3,8 @@ using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; using Lumina.Excel.GeneratedSheets; +using Pilz.Dalamud.Nameplates.Tools; +using Pilz.Dalamud.Tools.Strings; using PlayerTags.Configuration; using PlayerTags.Data; using PlayerTags.GameInterface.Nameplates; @@ -129,19 +131,13 @@ private void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs args) /// The position of the changes. /// The payload changes to add. /// The dictionary to add changes to. - private void AddPayloadChanges(NameplateElement nameplateElement, TagPosition tagPosition, IEnumerable payloadChanges, Dictionary> nameplateChanges, bool forceUsingSingleAnchorPayload) + private void AddPayloadChanges(NameplateElement nameplateElement, TagPosition tagPosition, IEnumerable payloadChanges, NameplateChanges nameplateChanges, bool forceUsingSingleAnchorPayload) { - if (!payloadChanges.Any()) + if (payloadChanges.Any()) { - return; + var changes = nameplateChanges.GetChanges((NameplateElements)nameplateElement); + AddPayloadChanges((StringPosition)tagPosition, payloadChanges, changes, forceUsingSingleAnchorPayload); } - - if (!nameplateChanges.Keys.Contains(nameplateElement)) - { - nameplateChanges[nameplateElement] = new(); - } - - AddPayloadChanges(tagPosition, payloadChanges, nameplateChanges[nameplateElement], forceUsingSingleAnchorPayload); } /// @@ -153,7 +149,10 @@ private void AddPayloadChanges(NameplateElement nameplateElement, TagPosition ta /// The free company text to change. private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString title, SeString freeCompany) { - Dictionary> nameplateChanges = new(); + NameplateChanges nameplateChanges = new(); + nameplateChanges.GetProps(NameplateElements.Name).Destination = name; + nameplateChanges.GetProps(NameplateElements.Title).Destination = title; + nameplateChanges.GetProps(NameplateElements.FreeCompany).Destination = freeCompany; if (gameObject is PlayerCharacter playerCharacter) { @@ -197,20 +196,7 @@ void checkTag(Tag tag) } // Build the final strings out of the payloads - foreach ((var nameplateElement, var stringChanges) in nameplateChanges) - { - SeString? seString = null; - - if (nameplateElement == NameplateElement.Name) - seString = name; - else if (nameplateElement == NameplateElement.Title) - seString = title; - else if (nameplateElement == NameplateElement.FreeCompany) - seString = freeCompany; - - if (seString != null) - ApplyStringChanges(seString, stringChanges); - } + ApplyNameplateChanges(nameplateChanges); if (gameObject is PlayerCharacter playerCharacter1) { @@ -234,5 +220,14 @@ void applyTextFormatting(Tag tag) } } } + + protected void ApplyNameplateChanges(NameplateChanges nameplateChanges) + { + var props = new NameplateChangesProps + { + Changes = nameplateChanges + }; + NameplateUpdateFactory.ApplyNameplateChanges(props); + } } } diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index ae5d457..7773da5 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -5,6 +5,7 @@ using FFXIVClientStructs.FFXIV.Client.Game.Object; using Lumina.Excel.GeneratedSheets; using Pilz.Dalamud.ActivityContexts; +using Pilz.Dalamud.Tools.Strings; using PlayerTags.Configuration.GameConfig; using PlayerTags.Data; using PlayerTags.Inheritables; @@ -21,12 +22,6 @@ namespace PlayerTags.Features /// public abstract class TagTargetFeature : IDisposable { - protected class StringChanges - { - public List Payloads { get; init; } = new(); - public bool ForceUsingSingleAnchorPayload { get; set; } = false; - } - public ActivityContextManager ActivityContextManager { get; init; } public TagTargetFeature() @@ -154,68 +149,6 @@ private Payload[] CreatePayloads(Tag tag) return newPayloads.ToArray(); } - /// - /// Adds an additional space text payload in between any existing text payloads. If there is an icon payload between two text payloads then the space is skipped. - /// Also adds an extra space to the beginning or end depending on the tag position and whether the most significant payload in either direction is a text payload. - /// In spirit, this is to ensure there is always a space between 2 text payloads, including between these payloads and the target payload. - /// - /// The payloads to add spaces between. - private void AddSpacesBetweenTextPayloads(List payloads, TagPosition tagPosition) - { - if (payloads == null) - { - return; - } - - if (!payloads.Any()) - { - return; - } - - List indicesToInsertSpacesAt = new List(); - int lastTextPayloadIndex = -1; - foreach (var payload in payloads.Reverse()) - { - if (payload is IconPayload iconPayload) - { - lastTextPayloadIndex = -1; - } - else if (payload is TextPayload textPayload) - { - if (lastTextPayloadIndex != -1) - { - indicesToInsertSpacesAt.Add(payloads.IndexOf(textPayload) + 1); - } - - lastTextPayloadIndex = payloads.IndexOf(textPayload); - } - } - - foreach (var indexToInsertSpaceAt in indicesToInsertSpacesAt) - { - payloads.Insert(indexToInsertSpaceAt, new TextPayload($" ")); - } - - // Decide whether to add a space to the end - if (tagPosition == TagPosition.Before) - { - var significantPayloads = payloads.Where(payload => payload is TextPayload || payload is IconPayload); - if (significantPayloads.Last() is TextPayload) - { - payloads.Add(new TextPayload($" ")); - } - } - // Decide whether to add a space to the beginning - else if (tagPosition == TagPosition.After) - { - var significantPayloads = payloads.Where(payload => payload is TextPayload || payload is IconPayload); - if (significantPayloads.First() is TextPayload) - { - payloads.Insert(0, new TextPayload($" ")); - } - } - } - protected static string BuildPlayername(string name) { var logNameType = GameConfigHelper.Instance.GetLogNameType(); @@ -260,14 +193,11 @@ protected static string BuildPlayername(string name) /// The position to add changes to. /// The payloads to add. /// The dictionary to add the changes to. - protected void AddPayloadChanges(TagPosition tagPosition, IEnumerable payloads, Dictionary stringChanges, bool forceUsingSingleAnchorPayload) + protected void AddPayloadChanges(StringPosition tagPosition, IEnumerable payloads, StringChanges stringChanges, bool forceUsingSingleAnchorPayload) { if (payloads != null && payloads.Any() && stringChanges != null) { - if (!stringChanges.Keys.Contains(tagPosition)) - stringChanges[tagPosition] = new(); - - var changes = stringChanges[tagPosition]; + var changes = stringChanges.GetChange(tagPosition); changes.Payloads.AddRange(payloads); changes.ForceUsingSingleAnchorPayload = forceUsingSingleAnchorPayload; } @@ -279,80 +209,18 @@ protected void AddPayloadChanges(TagPosition tagPosition, IEnumerable p /// The string to apply changes to. /// The changes to apply. /// The payload in the string that changes should be anchored to. If there is no anchor, the changes will be applied to the entire string. - protected void ApplyStringChanges(SeString seString, Dictionary stringChanges, List anchorPayloads = null, Payload anchorReplacePayload = null) + protected void ApplyStringChanges(SeString seString, StringChanges stringChanges, List anchorPayloads = null, Payload anchorReplacePayload = null) { - if (stringChanges.Count == 0) - { - return; - } - - List tagPositionsOrdered = new List(); - // If there's no anchor payload, do replaces first so that befores and afters are based on the replaced data - if (anchorPayloads == null || !anchorPayloads.Any()) + var props = new StringChangesProps { - tagPositionsOrdered.Add(TagPosition.Replace); - } + Destination = seString, + AnchorPayload = anchorReplacePayload + }; - tagPositionsOrdered.Add(TagPosition.Before); - tagPositionsOrdered.Add(TagPosition.After); + props.AnchorPayloads = anchorPayloads; + props.StringChanges = stringChanges; - // If there is an anchor payload, do replaces last so that we still know which payload needs to be removed - if (anchorPayloads != null && anchorPayloads.Any()) - { - tagPositionsOrdered.Add(TagPosition.Replace); - } - - foreach (var tagPosition in tagPositionsOrdered) - { - if (stringChanges.TryGetValue(tagPosition, out var payloads) && payloads.Payloads.Any()) - { - AddSpacesBetweenTextPayloads(stringChanges[tagPosition].Payloads, tagPosition); - if (tagPosition == TagPosition.Before) - { - Payload anchorFirst = payloads.ForceUsingSingleAnchorPayload ? anchorReplacePayload : anchorPayloads?.FirstOrDefault(); - - if (anchorFirst != null) - { - var anchorPayloadIndex = seString.Payloads.IndexOf(anchorFirst); - seString.Payloads.InsertRange(anchorPayloadIndex, payloads.Payloads); - } - else - { - seString.Payloads.InsertRange(0, payloads.Payloads); - } - } - else if (tagPosition == TagPosition.After) - { - Payload anchorLast = payloads.ForceUsingSingleAnchorPayload? anchorReplacePayload : anchorPayloads?.LastOrDefault(); - - if (anchorLast != null) - { - var anchorPayloadIndex = seString.Payloads.IndexOf(anchorLast); - seString.Payloads.InsertRange(anchorPayloadIndex + 1, payloads.Payloads); - } - else - { - seString.Payloads.AddRange(payloads.Payloads); - } - } - else if (tagPosition == TagPosition.Replace) - { - Payload anchorReplace = anchorReplacePayload; - - if (anchorReplace != null) - { - var anchorPayloadIndex = seString.Payloads.IndexOf(anchorReplace); - seString.Payloads.InsertRange(anchorPayloadIndex, payloads.Payloads); - seString.Remove(anchorReplace); - } - else - { - seString.Payloads.Clear(); - seString.Payloads.AddRange(payloads.Payloads); - } - } - } - } + StringUpdateFactory.ApplyStringChanges(props); } protected void ApplyTextFormatting(GameObject gameObject, Tag tag, SeString[] destStrings, InheritableValue[] textColorApplied, List preferedPayloads) From 1e3380cbd112f9e7f7e494a6540715eb3bb7a6a7 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 6 Nov 2022 11:32:02 +0100 Subject: [PATCH 113/174] implement job icon feature --- .../Configuration/PluginConfiguration.cs | 4 +- .../Configuration/PluginConfigurationUI.cs | 5 ++ PlayerTags/Data/DefaultPluginData.cs | 4 +- PlayerTags/Data/Tag.cs | 9 ++- PlayerTags/Features/ChatTagTargetFeature.cs | 4 +- .../Features/NameplateTagTargetFeature.cs | 37 +++++++-- PlayerTags/Resources/Strings.Designer.cs | 75 +++++++++++++++---- PlayerTags/Resources/Strings.resx | 27 +++++-- 8 files changed, 130 insertions(+), 35 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index 3c5761b..bc340e4 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -1,6 +1,7 @@ using Dalamud.Configuration; using Newtonsoft.Json; using Pilz.Dalamud.ActivityContexts; +using Pilz.Dalamud.Nameplates.Tools; using PlayerTags.Data; using PlayerTags.Inheritables; using System; @@ -35,12 +36,13 @@ public class PluginConfiguration : IPluginConfiguration { ActivityType.PvpDuty, new GeneralOptionsClass() } }; + public StatusIconPriorizerSettings StatusIconPriorizerSettings = new(); public bool IsPlayerNameRandomlyGenerated = false; public bool IsCustomTagsContextMenuEnabled = true; public bool IsShowInheritedPropertiesEnabled = true; public bool IsPlayersTabOrderedByProximity = false; public bool IsPlayersTabSelfVisible = true; - public bool IsPlayersTabFriendsVisible = true; + public bool IsPlayersTabFriendsVisible = true; public bool IsPlayersTabPartyVisible = true; public bool IsPlayersTabAllianceVisible = true; public bool IsPlayersTabEnemiesVisible = true; diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index 9f2f923..d012e00 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -6,6 +6,7 @@ using ImGuiNET; using Lumina.Excel.GeneratedSheets; using Pilz.Dalamud.ActivityContexts; +using Pilz.Dalamud.Icons; using PlayerTags.Data; using PlayerTags.Inheritables; using PlayerTags.PluginStrings; @@ -692,6 +693,10 @@ public void DrawControls(Tag tag) { DrawInheritable(selectedInheritable.Inheritable.Key, true, false, inheritableNameplateTitlePosition); } + else if (selectedInheritable.Inheritable.Value is InheritableValue inheritableJobIconSetName) + { + DrawInheritable(selectedInheritable.Inheritable.Key, false, false, inheritableJobIconSetName); + } else if (selectedInheritable.Inheritable.Value is InheritableReference inheritableString) { DrawInheritable(selectedInheritable.Inheritable.Key, inheritableString); diff --git a/PlayerTags/Data/DefaultPluginData.cs b/PlayerTags/Data/DefaultPluginData.cs index 143fc64..48263ae 100644 --- a/PlayerTags/Data/DefaultPluginData.cs +++ b/PlayerTags/Data/DefaultPluginData.cs @@ -50,9 +50,9 @@ public DefaultPluginData() { IsSelected = false, IsExpanded = true, - IsIconVisibleInChat = true, + IsRoleIconVisibleInChat = true, IsTextVisibleInChat = true, - IsIconVisibleInNameplates = true, + IsRoleIconVisibleInNameplates = true, IsTextVisibleInNameplates = true, IsTextColorAppliedToChatName = true, }; diff --git a/PlayerTags/Data/Tag.cs b/PlayerTags/Data/Tag.cs index 51e9d0a..e32fe59 100644 --- a/PlayerTags/Data/Tag.cs +++ b/PlayerTags/Data/Tag.cs @@ -1,4 +1,5 @@ using Dalamud.Game.Text.SeStringHandling; +using Pilz.Dalamud.Icons; using PlayerTags.Inheritables; using PlayerTags.PluginStrings; using System; @@ -99,9 +100,13 @@ public Dictionary Inheritables [InheritableCategory("IconCategory")] public InheritableValue Icon = new InheritableValue(BitmapFontIcon.Aethernet); [InheritableCategory("IconCategory")] - public InheritableValue IsIconVisibleInChat = new InheritableValue(false); + public InheritableValue IsRoleIconVisibleInChat = new InheritableValue(false); [InheritableCategory("IconCategory")] - public InheritableValue IsIconVisibleInNameplates = new InheritableValue(false); + public InheritableValue IsRoleIconVisibleInNameplates = new InheritableValue(false); + [InheritableCategory("IconCategory")] + public InheritableValue IsJobIconVisibleInNameplates = new InheritableValue(false); + [InheritableCategory("IconCategory")] + public InheritableValue JobIconSet = new InheritableValue(JobIconSetName.Framed); [InheritableCategory("TextCategory")] public InheritableReference Text = new InheritableReference(""); diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 9e25e90..4239425 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -130,9 +130,9 @@ private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString send protected override bool IsIconVisible(Tag tag) { - if (tag.IsIconVisibleInChat.InheritedValue != null) + if (tag.IsRoleIconVisibleInChat.InheritedValue != null) { - return tag.IsIconVisibleInChat.InheritedValue.Value; + return tag.IsRoleIconVisibleInChat.InheritedValue.Value; } return false; diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index 869e968..c73205f 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -3,6 +3,7 @@ using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; using Lumina.Excel.GeneratedSheets; +using Pilz.Dalamud.Icons; using Pilz.Dalamud.Nameplates.Tools; using Pilz.Dalamud.Tools.Strings; using PlayerTags.Configuration; @@ -20,25 +21,31 @@ namespace PlayerTags.Features /// public class NameplateTagTargetFeature : TagTargetFeature { - private PluginConfiguration m_PluginConfiguration; - private PluginData m_PluginData; + private readonly PluginConfiguration m_PluginConfiguration; + private readonly PluginData m_PluginData; + private readonly StatusIconPriorizer statusiconPriorizer; + private readonly JobIconSets jobIconSets = new(); private Nameplate? m_Nameplate; public NameplateTagTargetFeature(PluginConfiguration pluginConfiguration, PluginData pluginData) { m_PluginConfiguration = pluginConfiguration; m_PluginData = pluginData; + statusiconPriorizer = new(pluginConfiguration.StatusIconPriorizerSettings); PluginServices.ClientState.Login += ClientState_Login; PluginServices.ClientState.Logout += ClientState_Logout; + Hook(); } public override void Dispose() { Unhook(); + PluginServices.ClientState.Logout -= ClientState_Logout; PluginServices.ClientState.Login -= ClientState_Login; + base.Dispose(); } @@ -81,9 +88,9 @@ private void ClientState_Logout(object? sender, EventArgs e) protected override bool IsIconVisible(Tag tag) { - if (tag.IsIconVisibleInNameplates.InheritedValue != null) + if (tag.IsRoleIconVisibleInNameplates.InheritedValue != null) { - return tag.IsIconVisibleInNameplates.InheritedValue.Value; + return tag.IsRoleIconVisibleInNameplates.InheritedValue.Value; } return false; @@ -102,9 +109,12 @@ protected override bool IsTextVisible(Tag tag) private void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs args) { var beforeTitleBytes = args.Title.Encode(); - AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany); + var iconID = args.IconId; var generalOptions = m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType]; + AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID); + args.IconId = iconID; + if (generalOptions.NameplateTitlePosition == NameplateTitlePosition.AlwaysAboveName) args.IsTitleAboveName = true; else if (generalOptions.NameplateTitlePosition == NameplateTitlePosition.AlwaysBelowName) @@ -147,8 +157,9 @@ private void AddPayloadChanges(NameplateElement nameplateElement, TagPosition ta /// The name text to change. /// The title text to change. /// The free company text to change. - private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString title, SeString freeCompany) + private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString title, SeString freeCompany, ref int statusIcon) { + int? newStatusIcon = null; NameplateChanges nameplateChanges = new(); nameplateChanges.GetProps(NameplateElements.Name).Destination = name; nameplateChanges.GetProps(NameplateElements.Title).Destination = title; @@ -156,8 +167,11 @@ private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString t if (gameObject is PlayerCharacter playerCharacter) { + var classJob = playerCharacter.ClassJob; + var classJobGameData = classJob?.GameData; + // Add the job tags - if (playerCharacter.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter.ClassJob.GameData.Abbreviation, out var jobTag)) + if (classJobGameData != null && m_PluginData.JobTags.TryGetValue(classJobGameData.Abbreviation, out var jobTag)) { if (jobTag.TagTargetInNameplates.InheritedValue != null && jobTag.TagPositionInNameplates.InheritedValue != null) checkTag(jobTag); @@ -192,9 +206,18 @@ void checkTag(Tag tag) if (payloads.Any()) AddPayloadChanges(tag.TagTargetInNameplates.InheritedValue.Value, tag.TagPositionInNameplates.InheritedValue.Value, payloads, nameplateChanges, false); } + if (newStatusIcon == null && classJob != null && (tag.IsJobIconVisibleInNameplates?.InheritedValue ?? false)) + newStatusIcon = jobIconSets.GetJobIcon(JobIconSetName.Framed, classJob.Id); } } + // Apply new status icon + if (newStatusIcon != null) + { + var change = nameplateChanges.GetChange(NameplateElements.Name, StringPosition.Before); + NameplateUpdateFactory.ApplyStatusIconWithPrio(ref statusIcon, (int)newStatusIcon, change, ActivityContextManager.CurrentActivityContext, statusiconPriorizer); + } + // Build the final strings out of the payloads ApplyNameplateChanges(nameplateChanges); diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index ceb3809..a7e101f 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -358,29 +358,20 @@ public static string Loc_IsIconVisibleInChat { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Whether the icon will be shown in chat. ähnelt. + /// Sucht eine lokalisierte Zeichenfolge, die Show job icon in nameplates ähnelt. /// - public static string Loc_IsIconVisibleInChat_Description { + public static string Loc_IsJobIconVisibleInNameplates { get { - return ResourceManager.GetString("Loc_IsIconVisibleInChat_Description", resourceCulture); + return ResourceManager.GetString("Loc_IsJobIconVisibleInNameplates", resourceCulture); } } /// - /// Sucht eine lokalisierte Zeichenfolge, die Show in nameplates ähnelt. + /// Sucht eine lokalisierte Zeichenfolge, die Whether the job icon will be shown in nameplates. ähnelt. /// - public static string Loc_IsIconVisibleInNameplates { + public static string Loc_IsJobIconVisibleInNameplates_Description { get { - return ResourceManager.GetString("Loc_IsIconVisibleInNameplates", resourceCulture); - } - } - - /// - /// Sucht eine lokalisierte Zeichenfolge, die Whether the icon will be shown in nameplates. ähnelt. - /// - public static string Loc_IsIconVisibleInNameplates_Description { - get { - return ResourceManager.GetString("Loc_IsIconVisibleInNameplates_Description", resourceCulture); + return ResourceManager.GetString("Loc_IsJobIconVisibleInNameplates_Description", resourceCulture); } } @@ -546,6 +537,42 @@ public static string Loc_IsPlayersTabSelfVisible_Description { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Whether the role icon will be shown in chat. ähnelt. + /// + public static string Loc_IsRoleIconVisibleInChat_Description { + get { + return ResourceManager.GetString("Loc_IsRoleIconVisibleInChat_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Show role icon in nameplates ähnelt. + /// + public static string Loc_IsRoleIconVisibleInNameplates { + get { + return ResourceManager.GetString("Loc_IsRoleIconVisibleInNameplates", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Whether the role icon will be shown in nameplates. ähnelt. + /// + public static string Loc_IsRoleIconVisibleInNameplates_Description { + get { + return ResourceManager.GetString("Loc_IsRoleIconVisibleInNameplates_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Show role icon in nameplate ähnelt. + /// + public static string Loc_IsRoleJobIconVisibleInNameplates { + get { + return ResourceManager.GetString("Loc_IsRoleJobIconVisibleInNameplates", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Selected ähnelt. /// @@ -861,6 +888,24 @@ public static string Loc_IsVisibleInPvpDuties_Description { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Job icon set ähnelt. + /// + public static string Loc_JobIconSet { + get { + return ResourceManager.GetString("Loc_JobIconSet", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die The icon set to use for displaying the job icon. You can also choose the role icon set to display the role icon instead. ähnelt. + /// + public static string Loc_JobIconSet_Description { + get { + return ResourceManager.GetString("Loc_JobIconSet_Description", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Hand ähnelt. /// diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index c272ddc..c5639a9 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -354,14 +354,14 @@ Show in chat - - Whether the icon will be shown in chat. + + Whether the role icon will be shown in chat. - - Show in nameplates + + Show role icon in nameplates - - Whether the icon will be shown in nameplates. + + Whether the role icon will be shown in nameplates. Text @@ -642,4 +642,19 @@ Chat + + Show role icon in nameplate + + + Show job icon in nameplates + + + Whether the job icon will be shown in nameplates. + + + Job icon set + + + The icon set to use for displaying the job icon. You can also choose the role icon set to display the role icon instead. + \ No newline at end of file From 9c927d91f3f79560e7080b1a62c2ffed3bac4675 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 8 Nov 2022 07:42:58 +0100 Subject: [PATCH 114/174] set some json attributes for eventually changes of configuraiton in the future --- .../Configuration/PluginConfiguration.cs | 28 ++++++++++--------- PlayerTags/Data/Tag.cs | 9 ++++++ .../Inheritables/InheritableReference.cs | 6 +++- PlayerTags/Inheritables/InheritableValue.cs | 3 ++ 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index bc340e4..0bc50ac 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -13,21 +13,9 @@ namespace PlayerTags.Configuration [Serializable] public class PluginConfiguration : IPluginConfiguration { - public int Version { get; set; } = 0; + public int Version { get; set; } = 1; public bool IsVisible = false; - [Obsolete] - [JsonProperty("GeneralOptions")] - private Dictionary GeneralOptionsV1 - { - set - { - GeneralOptions.Clear(); - foreach (var kvp in value) - GeneralOptions.Add((ActivityType)kvp.Key, kvp.Value); - } - } - [JsonProperty("GeneralOptionsV2")] public Dictionary GeneralOptions = new() { @@ -49,6 +37,8 @@ public class PluginConfiguration : IPluginConfiguration public bool IsPlayersTabOthersVisible = false; public bool IsGeneralOptionsAllTheSameEnabled = true; + public Tag AllTags = null; + [JsonProperty(TypeNameHandling = TypeNameHandling.None, ItemTypeNameHandling = TypeNameHandling.None)] public Dictionary AllTagsChanges = new Dictionary(); @@ -81,6 +71,18 @@ public class PluginConfiguration : IPluginConfiguration #region Obsulate Properties + [Obsolete] + [JsonProperty("GeneralOptions")] + private Dictionary GeneralOptionsV1 + { + set + { + GeneralOptions.Clear(); + foreach (var kvp in value) + GeneralOptions.Add((ActivityType)kvp.Key, kvp.Value); + } + } + [JsonProperty("NameplateFreeCompanyVisibility"), Obsolete] private NameplateFreeCompanyVisibility NameplateFreeCompanyVisibilityV1 { diff --git a/PlayerTags/Data/Tag.cs b/PlayerTags/Data/Tag.cs index e32fe59..5f427e6 100644 --- a/PlayerTags/Data/Tag.cs +++ b/PlayerTags/Data/Tag.cs @@ -1,4 +1,5 @@ using Dalamud.Game.Text.SeStringHandling; +using Newtonsoft.Json; using Pilz.Dalamud.Icons; using PlayerTags.Inheritables; using PlayerTags.PluginStrings; @@ -12,7 +13,10 @@ public class Tag { public IPluginString Name { get; init; } + [JsonProperty("Parent")] private Tag? m_Parent = null; + + [JsonIgnore] public Tag? Parent { get => m_Parent; @@ -43,6 +47,7 @@ public Tag? Parent public List Children { get; } = new List(); + [JsonIgnore] public IEnumerable Descendents { get @@ -58,7 +63,9 @@ public IEnumerable Descendents } } + [JsonIgnore] private Dictionary? m_Inheritables = null; + [JsonIgnore] public Dictionary Inheritables { get @@ -165,6 +172,7 @@ public Dictionary Inheritables [InheritableCategory("PlayerCategory")] public InheritableValue IsVisibleForOtherPlayers = new InheritableValue(false); + [JsonIgnore] public string[] IdentitiesToAddTo { get @@ -179,6 +187,7 @@ public string[] IdentitiesToAddTo } private Tag? m_Defaults; + [JsonIgnore] public bool HasDefaults { get { return m_Defaults != null; } diff --git a/PlayerTags/Inheritables/InheritableReference.cs b/PlayerTags/Inheritables/InheritableReference.cs index abc101f..ea3c5e2 100644 --- a/PlayerTags/Inheritables/InheritableReference.cs +++ b/PlayerTags/Inheritables/InheritableReference.cs @@ -1,4 +1,6 @@ -namespace PlayerTags.Inheritables +using Newtonsoft.Json; + +namespace PlayerTags.Inheritables { public class InheritableReference : IInheritable where T : class @@ -7,8 +9,10 @@ public class InheritableReference : IInheritable public InheritableBehavior Behavior { get; set; } + [JsonProperty] public T Value; + [JsonIgnore] public T? InheritedValue { get diff --git a/PlayerTags/Inheritables/InheritableValue.cs b/PlayerTags/Inheritables/InheritableValue.cs index e49e304..f17e55a 100644 --- a/PlayerTags/Inheritables/InheritableValue.cs +++ b/PlayerTags/Inheritables/InheritableValue.cs @@ -1,4 +1,5 @@ using Dalamud.Logging; +using Newtonsoft.Json; using System; namespace PlayerTags.Inheritables @@ -10,8 +11,10 @@ public class InheritableValue : IInheritable public InheritableBehavior Behavior { get; set; } + [JsonProperty] public T Value; + [JsonIgnore] public T? InheritedValue { get From 2770797ada2b91c2d4319f062123f7980fc2df4c Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 8 Nov 2022 07:52:11 +0100 Subject: [PATCH 115/174] remove currently unneeded configuration --- PlayerTags/Configuration/PluginConfiguration.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index 0bc50ac..34cb5cf 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -37,8 +37,6 @@ public class PluginConfiguration : IPluginConfiguration public bool IsPlayersTabOthersVisible = false; public bool IsGeneralOptionsAllTheSameEnabled = true; - public Tag AllTags = null; - [JsonProperty(TypeNameHandling = TypeNameHandling.None, ItemTypeNameHandling = TypeNameHandling.None)] public Dictionary AllTagsChanges = new Dictionary(); From c2b2fa86a4dff4235d5f4f5ccbaaa5614da2ae82 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 8 Nov 2022 07:57:21 +0100 Subject: [PATCH 116/174] maybe fix wrong(?) operator -> Chat messages should not be processed anymore when disabled --- PlayerTags/Features/ChatTagTargetFeature.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 4239425..cfb29da 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -121,7 +121,7 @@ public override void Dispose() private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) { - if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType].IsApplyTagsToAllChatMessagesEnabled || Enum.IsDefined(type)) + if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType].IsApplyTagsToAllChatMessagesEnabled && Enum.IsDefined(type)) { AddTagsToChat(sender, type, true); AddTagsToChat(message, type, false); From 5501d1ecc47a331ad28c40e9bfaa9d6d49bf46fc Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 9 Nov 2022 12:57:23 +0100 Subject: [PATCH 117/174] add settings for chat target types (broken state yet) --- PlayerTags.sln | 6 - .../Configuration/PluginConfiguration.cs | 61 +++++++++- .../Configuration/PluginConfigurationUI.cs | 107 ++++++++++++++++++ PlayerTags/Data/DefaultPluginData.cs | 6 +- PlayerTags/Data/Tag.cs | 7 +- PlayerTags/Data/XivChatTypeList.cs | 56 +++++++++ PlayerTags/Features/ChatTagTargetFeature.cs | 2 +- PlayerTags/GeneralConverter.cs | 30 ----- .../Inheritables/InheritableBehavior.cs | 5 +- PlayerTags/Inheritables/InheritableData.cs | 1 - .../Inheritables/InheritableReference.cs | 1 + PlayerTags/PlayerTags.csproj | 2 +- PlayerTags/Plugin.cs | 3 +- PlayerTags/Resources/Strings.Designer.cs | 27 +++++ PlayerTags/Resources/Strings.resx | 9 ++ PlayerTags/packages.lock.json | 7 +- 16 files changed, 282 insertions(+), 48 deletions(-) create mode 100644 PlayerTags/Data/XivChatTypeList.cs delete mode 100644 PlayerTags/GeneralConverter.cs diff --git a/PlayerTags.sln b/PlayerTags.sln index 0219690..d0f9aff 100644 --- a/PlayerTags.sln +++ b/PlayerTags.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 17.3.32929.385 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlayerTags", "PlayerTags\PlayerTags.csproj", "{13C812E9-0D42-4B95-8646-40EEBF30636F}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pilz.Dalamud", "..\Pilz.Dalamud\Pilz.Dalamud\Pilz.Dalamud.csproj", "{A92D2FFC-FDB8-4F28-B5DD-4A1B3EB0B1BB}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -17,10 +15,6 @@ Global {13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|x64.Build.0 = Debug|x64 {13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.ActiveCfg = Release|x64 {13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.Build.0 = Release|x64 - {A92D2FFC-FDB8-4F28-B5DD-4A1B3EB0B1BB}.Debug|x64.ActiveCfg = Debug|x64 - {A92D2FFC-FDB8-4F28-B5DD-4A1B3EB0B1BB}.Debug|x64.Build.0 = Debug|x64 - {A92D2FFC-FDB8-4F28-B5DD-4A1B3EB0B1BB}.Release|x64.ActiveCfg = Release|x64 - {A92D2FFC-FDB8-4F28-B5DD-4A1B3EB0B1BB}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index 34cb5cf..6d3a2a9 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -1,19 +1,27 @@ using Dalamud.Configuration; using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using Pilz.Dalamud.ActivityContexts; using Pilz.Dalamud.Nameplates.Tools; using PlayerTags.Data; using PlayerTags.Inheritables; using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Reflection.Metadata.Ecma335; +using System.Runtime.CompilerServices; namespace PlayerTags.Configuration { [Serializable] public class PluginConfiguration : IPluginConfiguration { - public int Version { get; set; } = 1; + private const int DEFAULT_CONFIG_VERSION = 1; + + [JsonProperty] + public int RootVersion { get; private set; } = DEFAULT_CONFIG_VERSION; + public int Version { get; set; } = DEFAULT_CONFIG_VERSION; public bool IsVisible = false; [JsonProperty("GeneralOptionsV2")] @@ -24,7 +32,7 @@ public class PluginConfiguration : IPluginConfiguration { ActivityType.PvpDuty, new GeneralOptionsClass() } }; - public StatusIconPriorizerSettings StatusIconPriorizerSettings = new(); + public StatusIconPriorizerSettings StatusIconPriorizerSettings = new(true); public bool IsPlayerNameRandomlyGenerated = false; public bool IsCustomTagsContextMenuEnabled = true; public bool IsShowInheritedPropertiesEnabled = true; @@ -218,9 +226,56 @@ public void Save(PluginData pluginData) Identities = pluginData.Identities; - PluginServices.DalamudPluginInterface.SavePluginConfig(this); + SavePluginConfig(); + Saved?.Invoke(); } + + private void SavePluginConfig() + { + Version = DEFAULT_CONFIG_VERSION; + var configFilePath = GetConfigFilePath(); + var configFileContent = JsonConvert.SerializeObject(this, Formatting.Indented, GetJsonSettings()); + File.WriteAllText(configFilePath, configFileContent); + } + + public static PluginConfiguration LoadPluginConfig() + { + var configFilePath = GetConfigFilePath(); + object config = null; + + if (File.Exists(configFilePath)) + { + var configFileContent = File.ReadAllText(configFilePath); + config = JsonConvert.DeserializeObject(configFileContent, GetJsonSettings()); + } + else + { + // Try loading the old settings, if possible + configFilePath = PluginServices.DalamudPluginInterface.ConfigFile.FullName; + config = PluginServices.DalamudPluginInterface.GetPluginConfig(); + } + + return config as PluginConfiguration; + } + + private static string GetConfigFilePath() + { + return Path.Combine(PluginServices.DalamudPluginInterface.ConfigDirectory.FullName, "Config.json"); + } + + private static JsonSerializerSettings GetJsonSettings() + { + var jsonSettings = new JsonSerializerSettings + { + TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple, + TypeNameHandling = TypeNameHandling.Auto, + }; + + jsonSettings.Converters.Add(new StringEnumConverter()); + + return jsonSettings; + } } public class GeneralOptionsClass diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index d012e00..9f09e0f 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -1,8 +1,11 @@ using Dalamud.Configuration; using Dalamud.Game.ClientState.Objects.SubKinds; +using Dalamud.Game.Text; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Interface; using Dalamud.Logging; +using FFXIVClientStructs.FFXIV.Client.Game.UI; +using FFXIVClientStructs.Havok; using ImGuiNET; using Lumina.Excel.GeneratedSheets; using Pilz.Dalamud.ActivityContexts; @@ -15,6 +18,8 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; +using System.Threading.Tasks; +using System.Transactions; namespace PlayerTags.Configuration { @@ -31,6 +36,7 @@ private struct PlayerInfo private PropertyProxy propertyProxy; private InheritableValue? m_ColorPickerPopupDataContext; + private Dictionary inheritableTEnumProxies = new(); public PluginConfigurationUI(PluginConfiguration config, PluginData pluginData) { @@ -697,6 +703,10 @@ public void DrawControls(Tag tag) { DrawInheritable(selectedInheritable.Inheritable.Key, false, false, inheritableJobIconSetName); } + else if (selectedInheritable.Inheritable.Value is InheritableReference> inheritableXivChatType) + { + DrawMultiselect(selectedInheritable.Inheritable.Key, inheritableXivChatType); + } else if (selectedInheritable.Inheritable.Value is InheritableReference inheritableString) { DrawInheritable(selectedInheritable.Inheritable.Key, inheritableString); @@ -1058,6 +1068,66 @@ private void DrawHeading(string label) ImGui.TextColored(new Vector4(0.7f, 0.6f, 1f, 1f), label); } + private void DrawMultiselect(string localizedStringName, InheritableReference> inheritable) where TEnum : Enum + { + bool isDisabled = inheritable.Behavior == InheritableBehavior.Inherit; + EnumList proxyKey = isDisabled ? inheritable.InheritedValue : inheritable.Value; + + if (isDisabled) + proxyKey = inheritable.InheritedValue; + if (proxyKey == null) + proxyKey = inheritable.Value; + + if (isDisabled) + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.25f); + + var isExpanded = ImGui.CollapsingHeader(Localizer.GetString(localizedStringName, false)); + + if (ImGui.IsItemHovered()) + ImGui.SetTooltip(Localizer.GetString(localizedStringName, true)); + + if (isDisabled) + { + ImGui.SameLine(); + ImGui.Text(Strings.Loc_Static_Inherited); + } + else + DrawRemovePropertyOverrideButton(inheritable); + + if (isExpanded) + { + bool isClicked = false; + var typeofEnum = typeof(TEnum); + EnumMultiselectProxy proxy; + + if (inheritableTEnumProxies.ContainsKey(proxyKey)) + proxy = inheritableTEnumProxies[proxyKey] as EnumMultiselectProxy; + else + { + proxy = new EnumMultiselectProxy(proxyKey); + inheritableTEnumProxies.Add(proxyKey, proxy); + } + + foreach (var entry in proxy.Entries) + { + var entryName = Enum.GetName(typeofEnum, entry.Value); + var tempval = entry.Enabled; + isClicked = ImGui.Checkbox(Localizer.GetString(entryName), ref isDisabled ? ref tempval : ref entry.Enabled); + if (ImGui.IsItemHovered()) + ImGui.SetTooltip(Localizer.GetString(entryName, true)); + } + + if (!isDisabled && isClicked) + { + proxy.ApplyTo(proxyKey); + SaveSettings(); + } + } + + if (isDisabled) + ImGui.PopStyleVar(); + } + private void DrawComboBox(bool isLabelVisible, bool shouldLocalizeNames, bool shouldOrderNames, ref TEnum currentValue, System.Action changed) where TEnum : Enum { @@ -1278,5 +1348,42 @@ private enum ActivityContextSelection PveDuty, PvpDuty } + + private class EnumMultiselectProxy where TEnum : Enum + { + public List Entries { get; } = new(); + + public EnumMultiselectProxy(EnumList target) + { + foreach (TEnum value in Enum.GetValues(typeof(TEnum))) + Entries.Add(new(value, target.Contains(value))); + } + + public void ApplyTo(EnumList target) + { + foreach (var entry in Entries) + { + if (entry.Enabled) + { + if (!target.Contains(entry.Value)) + target.Add(entry.Value); + } + else if (target.Contains(entry.Value)) + target.Remove(entry.Value); + } + } + + public class Entry + { + public TEnum Value { get; set; } + public bool Enabled; + + public Entry(TEnum value, bool enabled) + { + Value = value; + Enabled = enabled; + } + } + } } } diff --git a/PlayerTags/Data/DefaultPluginData.cs b/PlayerTags/Data/DefaultPluginData.cs index 48263ae..71a43ea 100644 --- a/PlayerTags/Data/DefaultPluginData.cs +++ b/PlayerTags/Data/DefaultPluginData.cs @@ -1,5 +1,7 @@ -using Dalamud.Game.Text.SeStringHandling; +using Dalamud.Game.Text; +using Dalamud.Game.Text.SeStringHandling; using Lumina.Excel.GeneratedSheets; +using System; using System.Collections.Generic; using System.Linq; @@ -44,6 +46,8 @@ public DefaultPluginData() IsVisibleForAlliancePlayers = true, IsVisibleForEnemyPlayers = true, IsVisibleForOtherPlayers = true, + + TargetChatTypes = new EnumList(Enum.GetValues()), }; AllRoleTags = new Tag() diff --git a/PlayerTags/Data/Tag.cs b/PlayerTags/Data/Tag.cs index 5f427e6..6338078 100644 --- a/PlayerTags/Data/Tag.cs +++ b/PlayerTags/Data/Tag.cs @@ -1,5 +1,7 @@ -using Dalamud.Game.Text.SeStringHandling; +using Dalamud.Game.Text; +using Dalamud.Game.Text.SeStringHandling; using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using Pilz.Dalamud.Icons; using PlayerTags.Inheritables; using PlayerTags.PluginStrings; @@ -172,6 +174,9 @@ public Dictionary Inheritables [InheritableCategory("PlayerCategory")] public InheritableValue IsVisibleForOtherPlayers = new InheritableValue(false); + [InheritableCategory("ChatFeatureCategory")] + public InheritableReference> TargetChatTypes = new(new EnumList(Enum.GetValues())); + [JsonIgnore] public string[] IdentitiesToAddTo { diff --git a/PlayerTags/Data/XivChatTypeList.cs b/PlayerTags/Data/XivChatTypeList.cs new file mode 100644 index 0000000..e05fdb8 --- /dev/null +++ b/PlayerTags/Data/XivChatTypeList.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PlayerTags.Data +{ + public class EnumList : List where TEnum : Enum + { + public EnumList() : base() + { + } + + public EnumList(IEnumerable collection) : base(collection) + { + } + + //// this is first one '==' + //public static bool operator ==(EnumList obj1, EnumList obj2) + //{ + + //} + + //// this is second one '!=' + //public static bool operator !=(EnumList obj1, EnumList obj2) + //{ + // return !(obj1 == obj2); + //} + + public override bool Equals(object? obj) + { + var obj1 = this; + var obj2 = obj as EnumList; + + if (obj1 is not null && obj2 is not null) + { + if (obj1.Count != obj2.Count) + return false; + + for (int i = 0; i < obj1.Count; i++) + { + if (!obj1[i]?.Equals(obj2[i]) ?? true) + return false; + } + } + + return true; + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + } +} diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index cfb29da..57d9da8 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -345,7 +345,7 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender // Add the job tag if (playerCharacter.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter.ClassJob.GameData.Abbreviation, out var jobTag)) { - if (jobTag.TagPositionInChat.InheritedValue != null) + if (jobTag.TagPositionInChat.InheritedValue != null && jobTag.TargetChatTypes.InheritedValue != null && jobTag.TargetChatTypes.Value.Contains(chatType)) { var payloads = GetPayloads(jobTag, stringMatch.GameObject); if (payloads.Any()) diff --git a/PlayerTags/GeneralConverter.cs b/PlayerTags/GeneralConverter.cs deleted file mode 100644 index eca30aa..0000000 --- a/PlayerTags/GeneralConverter.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Newtonsoft.Json; -using System; - -namespace PlayerTags -{ - public class GeneralConverter : JsonConverter - { - public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) - { - if (value != null && value.GetType().IsEnum) - { - writer.WriteValue(Enum.GetName(value.GetType(), value)); - } - else - { - writer.WriteValue(value); - } - } - - public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) - { - return reader.Value; - } - - public override bool CanConvert(Type objectType) - { - return true; - } - } -} diff --git a/PlayerTags/Inheritables/InheritableBehavior.cs b/PlayerTags/Inheritables/InheritableBehavior.cs index 752c2e1..1691864 100644 --- a/PlayerTags/Inheritables/InheritableBehavior.cs +++ b/PlayerTags/Inheritables/InheritableBehavior.cs @@ -1,4 +1,7 @@ -namespace PlayerTags.Inheritables +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace PlayerTags.Inheritables { public enum InheritableBehavior { diff --git a/PlayerTags/Inheritables/InheritableData.cs b/PlayerTags/Inheritables/InheritableData.cs index 88d8d9b..9b95b85 100644 --- a/PlayerTags/Inheritables/InheritableData.cs +++ b/PlayerTags/Inheritables/InheritableData.cs @@ -12,7 +12,6 @@ public struct InheritableData public InheritableBehavior Behavior; [JsonProperty("Value")] - [JsonConverter(typeof(GeneralConverter))] public object Value; } } diff --git a/PlayerTags/Inheritables/InheritableReference.cs b/PlayerTags/Inheritables/InheritableReference.cs index ea3c5e2..21bab63 100644 --- a/PlayerTags/Inheritables/InheritableReference.cs +++ b/PlayerTags/Inheritables/InheritableReference.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using Newtonsoft.Json.Converters; namespace PlayerTags.Inheritables { diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index b16c921..352f895 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -26,7 +26,7 @@ - + $(DalamudLibPath)FFXIVClientStructs.dll false diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index 97efc53..a1d6d1a 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -1,4 +1,5 @@ using Dalamud.Game.Command; +using Dalamud.Logging; using Dalamud.Plugin; using Dalamud.Plugin.Internal; using FFXIVClientStructs.FFXIV.Client.UI.Misc; @@ -30,7 +31,7 @@ public Plugin(DalamudPluginInterface pluginInterface) PluginServices.Initialize(pluginInterface); Pilz.Dalamud.PluginServices.Initialize(pluginInterface); - m_PluginConfiguration = PluginServices.DalamudPluginInterface.GetPluginConfig() as PluginConfiguration ?? new PluginConfiguration(); + m_PluginConfiguration = PluginConfiguration.LoadPluginConfig() ?? new PluginConfiguration(); m_PluginData = new PluginData(m_PluginConfiguration); m_PluginConfigurationUI = new PluginConfigurationUI(m_PluginConfiguration, m_PluginData); diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index a7e101f..7b45161 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -177,6 +177,15 @@ public static string Loc_AllTags { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Advanced Chat Options ähnelt. + /// + public static string Loc_ChatFeatureCategory { + get { + return ResourceManager.GetString("Loc_ChatFeatureCategory", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Custom id ähnelt. /// @@ -1617,6 +1626,24 @@ public static string Loc_TagTargetInNameplates_Description { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Target Chat Types ähnelt. + /// + public static string Loc_TargetChatTypes { + get { + return ResourceManager.GetString("Loc_TargetChatTypes", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Defines for which chat type the chat features of this tag should be enabled for. ähnelt. + /// + public static string Loc_TargetChatTypes_Description { + get { + return ResourceManager.GetString("Loc_TargetChatTypes_Description", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Text ähnelt. /// diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index c5639a9..f5d3dda 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -657,4 +657,13 @@ The icon set to use for displaying the job icon. You can also choose the role icon set to display the role icon instead. + + Advanced Chat Options + + + Target Chat Types + + + Defines for which chat type the chat features of this tag should be enabled for. + \ No newline at end of file diff --git a/PlayerTags/packages.lock.json b/PlayerTags/packages.lock.json index d25458d..fc36ed7 100644 --- a/PlayerTags/packages.lock.json +++ b/PlayerTags/packages.lock.json @@ -14,8 +14,11 @@ "resolved": "2.1.8", "contentHash": "YqagNXs9InxmqkXzq7kLveImxnodkBEicAhydMXVp7dFjC7xb76U6zGgAax4/BWIWfZeWzr5DJyQSev31kj81A==" }, - "pilz.dalamud": { - "type": "Project" + "Pilz.Dalamud": { + "type": "Direct", + "requested": "[0.1.0, )", + "resolved": "0.1.0", + "contentHash": "n22WXrCzA+EAQHi4ve4PgTZYDzr0f0qsQ/1ApBBQjoCKJcwFox2rO692/2davRWiUQiNv9B56ikcnHocLp75tQ==" } } } From fb4ffd3f2236ede632681c4ad02c6390136e7a81 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 9 Nov 2022 15:56:05 +0100 Subject: [PATCH 118/174] fix settings finally --- .../Configuration/PluginConfigurationUI.cs | 24 ++++---- PlayerTags/Data/DefaultPluginData.cs | 2 +- PlayerTags/Data/Tag.cs | 30 +++++++++- PlayerTags/Data/XivChatTypeList.cs | 56 ------------------- .../Inheritables/InheritableReference.cs | 1 + 5 files changed, 44 insertions(+), 69 deletions(-) delete mode 100644 PlayerTags/Data/XivChatTypeList.cs diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index 9f09e0f..aba314f 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -703,7 +703,7 @@ public void DrawControls(Tag tag) { DrawInheritable(selectedInheritable.Inheritable.Key, false, false, inheritableJobIconSetName); } - else if (selectedInheritable.Inheritable.Value is InheritableReference> inheritableXivChatType) + else if (selectedInheritable.Inheritable.Value is InheritableReference> inheritableXivChatType) { DrawMultiselect(selectedInheritable.Inheritable.Key, inheritableXivChatType); } @@ -1068,10 +1068,10 @@ private void DrawHeading(string label) ImGui.TextColored(new Vector4(0.7f, 0.6f, 1f, 1f), label); } - private void DrawMultiselect(string localizedStringName, InheritableReference> inheritable) where TEnum : Enum + private void DrawMultiselect(string localizedStringName, InheritableReference> inheritable) where TEnum : Enum { bool isDisabled = inheritable.Behavior == InheritableBehavior.Inherit; - EnumList proxyKey = isDisabled ? inheritable.InheritedValue : inheritable.Value; + List proxyKey = isDisabled ? inheritable.InheritedValue : inheritable.Value; if (isDisabled) proxyKey = inheritable.InheritedValue; @@ -1112,15 +1112,19 @@ private void DrawMultiselect(string localizedStringName, InheritableRefer { var entryName = Enum.GetName(typeofEnum, entry.Value); var tempval = entry.Enabled; + isClicked = ImGui.Checkbox(Localizer.GetString(entryName), ref isDisabled ? ref tempval : ref entry.Enabled); + if (ImGui.IsItemHovered()) ImGui.SetTooltip(Localizer.GetString(entryName, true)); - } - if (!isDisabled && isClicked) - { - proxy.ApplyTo(proxyKey); - SaveSettings(); + if (isClicked && !isDisabled) + { + var newList = proxyKey.ToList(); + proxy.ApplyTo(newList); + inheritable.Value = newList; + SaveSettings(); + } } } @@ -1353,13 +1357,13 @@ private class EnumMultiselectProxy where TEnum : Enum { public List Entries { get; } = new(); - public EnumMultiselectProxy(EnumList target) + public EnumMultiselectProxy(List target) { foreach (TEnum value in Enum.GetValues(typeof(TEnum))) Entries.Add(new(value, target.Contains(value))); } - public void ApplyTo(EnumList target) + public void ApplyTo(List target) { foreach (var entry in Entries) { diff --git a/PlayerTags/Data/DefaultPluginData.cs b/PlayerTags/Data/DefaultPluginData.cs index 71a43ea..1ee8fb9 100644 --- a/PlayerTags/Data/DefaultPluginData.cs +++ b/PlayerTags/Data/DefaultPluginData.cs @@ -47,7 +47,7 @@ public DefaultPluginData() IsVisibleForEnemyPlayers = true, IsVisibleForOtherPlayers = true, - TargetChatTypes = new EnumList(Enum.GetValues()), + TargetChatTypes = new List(Enum.GetValues()), }; AllRoleTags = new Tag() diff --git a/PlayerTags/Data/Tag.cs b/PlayerTags/Data/Tag.cs index 6338078..a168890 100644 --- a/PlayerTags/Data/Tag.cs +++ b/PlayerTags/Data/Tag.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace PlayerTags.Data { @@ -175,7 +176,7 @@ public Dictionary Inheritables public InheritableValue IsVisibleForOtherPlayers = new InheritableValue(false); [InheritableCategory("ChatFeatureCategory")] - public InheritableReference> TargetChatTypes = new(new EnumList(Enum.GetValues())); + public InheritableReference> TargetChatTypes = new(new List(Enum.GetValues())); [JsonIgnore] public string[] IdentitiesToAddTo @@ -228,7 +229,7 @@ public Dictionary GetChanges(Dictionary GetChanges(Dictionary) + return EqualsInheritableDataListXivChatType(data1, data2); + else + return data1.Value.Equals(data2.Value); + } + + private static bool EqualsInheritableDataListXivChatType(InheritableData data1, InheritableData data2) + { + var list1 = data1.Value as List; + var list2 = data2.Value as List; + + if (list1 is null || list2 is null || list1.Count != list2.Count) + return false; + + for (int i = 0; i < list1.Count; i++) + { + if (!list1[i].Equals(list2[i])) + return false; + } + + return true; + } + public void SetChanges(IEnumerable> changes) { foreach ((var name, var inheritableData) in changes) diff --git a/PlayerTags/Data/XivChatTypeList.cs b/PlayerTags/Data/XivChatTypeList.cs deleted file mode 100644 index e05fdb8..0000000 --- a/PlayerTags/Data/XivChatTypeList.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace PlayerTags.Data -{ - public class EnumList : List where TEnum : Enum - { - public EnumList() : base() - { - } - - public EnumList(IEnumerable collection) : base(collection) - { - } - - //// this is first one '==' - //public static bool operator ==(EnumList obj1, EnumList obj2) - //{ - - //} - - //// this is second one '!=' - //public static bool operator !=(EnumList obj1, EnumList obj2) - //{ - // return !(obj1 == obj2); - //} - - public override bool Equals(object? obj) - { - var obj1 = this; - var obj2 = obj as EnumList; - - if (obj1 is not null && obj2 is not null) - { - if (obj1.Count != obj2.Count) - return false; - - for (int i = 0; i < obj1.Count; i++) - { - if (!obj1[i]?.Equals(obj2[i]) ?? true) - return false; - } - } - - return true; - } - - public override int GetHashCode() - { - return base.GetHashCode(); - } - } -} diff --git a/PlayerTags/Inheritables/InheritableReference.cs b/PlayerTags/Inheritables/InheritableReference.cs index 21bab63..cabcf62 100644 --- a/PlayerTags/Inheritables/InheritableReference.cs +++ b/PlayerTags/Inheritables/InheritableReference.cs @@ -1,5 +1,6 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; +using System.Collections.Generic; namespace PlayerTags.Inheritables { From 5ee2ad66292bda05fe9b4c0e49b37563c76b878d Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 10 Nov 2022 09:59:09 +0100 Subject: [PATCH 119/174] add settings ui for status icon priorizer settings --- .../Configuration/PluginConfigurationUI.cs | 75 +++++ PlayerTags/Resources/Strings.Designer.cs | 262 ++++++++++++++++++ PlayerTags/Resources/Strings.resx | 88 ++++++ 3 files changed, 425 insertions(+) diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index aba314f..7c67cb8 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -10,6 +10,8 @@ using Lumina.Excel.GeneratedSheets; using Pilz.Dalamud.ActivityContexts; using Pilz.Dalamud.Icons; +using Pilz.Dalamud.Nameplates.Model; +using Pilz.Dalamud.Nameplates.Tools; using PlayerTags.Data; using PlayerTags.Inheritables; using PlayerTags.PluginStrings; @@ -246,6 +248,79 @@ public void Draw() ImGui.EndTabItem(); } + if (ImGui.BeginTabItem(Strings.Loc_Static_StatusIconPrioList)) + { + ImGui.Spacing(); + ImGui.Spacing(); + + var isPriorizerEnabled = m_PluginConfiguration.StatusIconPriorizerSettings.UsePriorizedIcons; + DrawCheckbox(nameof(StatusIconPriorizerSettings.UsePriorizedIcons), true, ref isPriorizerEnabled, () => + { + m_PluginConfiguration.StatusIconPriorizerSettings.UsePriorizedIcons = isPriorizerEnabled; + SaveSettings(); + }); + + if (isPriorizerEnabled) + { + var statusIcons = Enum.GetValues(); + + ImGui.Spacing(); + ImGui.Spacing(); + + if (ImGui.Button(Strings.Loc_StatusIconPriorizer_ResetToDefault)) + { + m_PluginConfiguration.StatusIconPriorizerSettings.ResetToDefault(); + SaveSettings(); + } + else if (ImGui.IsItemHovered()) + ImGui.SetTooltip(Strings.Loc_StatusIconPriorizer_ResetToDefault_Description); + + ImGui.SameLine(); + + if (ImGui.Button(Strings.Loc_StatusIconPriorizer_ResetToEmpty)) + { + m_PluginConfiguration.StatusIconPriorizerSettings.ResetToEmpty(); + SaveSettings(); + } + else if (ImGui.IsItemHovered()) + ImGui.SetTooltip(Strings.Loc_StatusIconPriorizer_ResetToEmpty_Description); + + ImGui.Spacing(); + ImGui.Spacing(); + + foreach (var conditionSetName in Enum.GetValues()) + { + if (ImGui.CollapsingHeader(Localizer.GetString(conditionSetName, false))) + { + var conditionSet = m_PluginConfiguration.StatusIconPriorizerSettings.GetConditionSet(conditionSetName); + + if (ImGui.IsItemHovered()) + ImGui.SetTooltip(Localizer.GetString(conditionSetName, true)); + + foreach (var statusIcon in statusIcons) + { + var isChecked = conditionSet.Contains(statusIcon); + DrawCheckbox(Localizer.GetName(statusIcon), true, ref isChecked, () => + { + if (isChecked) + { + if (!conditionSet.Contains(statusIcon)) + conditionSet.Add(statusIcon); + } + else if (conditionSet.Contains(statusIcon)) + conditionSet.Remove(statusIcon); + SaveSettings(); + }); + } + } + + ImGui.Spacing(); + } + } + + ImGui.EndTabItem(); + } + ImGui.EndTabBar(); } diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index 7b45161..b09f035 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -1491,6 +1491,15 @@ public static string Loc_Static_ResetDefault_Description { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Status Icon Priorizer ähnelt. + /// + public static string Loc_Static_StatusIconPrioList { + get { + return ResourceManager.GetString("Loc_Static_StatusIconPrioList", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Tagged Players ähnelt. /// @@ -1518,6 +1527,240 @@ public static string Loc_Static_WarningMessage { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Reset to default ähnelt. + /// + public static string Loc_StatusIconPriorizer_ResetToDefault { + get { + return ResourceManager.GetString("Loc_StatusIconPriorizer_ResetToDefault", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Resets all condition sets to the default settings ähnelt. + /// + public static string Loc_StatusIconPriorizer_ResetToDefault_Description { + get { + return ResourceManager.GetString("Loc_StatusIconPriorizer_ResetToDefault_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Reset to empty ähnelt. + /// + public static string Loc_StatusIconPriorizer_ResetToEmpty { + get { + return ResourceManager.GetString("Loc_StatusIconPriorizer_ResetToEmpty", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Clears all condition sets to an empty collection. None status icons will be priorized. ähnelt. + /// + public static string Loc_StatusIconPriorizer_ResetToEmpty_Description { + get { + return ResourceManager.GetString("Loc_StatusIconPriorizer_ResetToEmpty_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die In Duty ähnelt. + /// + public static string Loc_StatusIconPriorizerConditionSets_InDuty { + get { + return ResourceManager.GetString("Loc_StatusIconPriorizerConditionSets_InDuty", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Status icons that should get priorized within duties. ähnelt. + /// + public static string Loc_StatusIconPriorizerConditionSets_InDuty_Description { + get { + return ResourceManager.GetString("Loc_StatusIconPriorizerConditionSets_InDuty_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die In Foray ähnelt. + /// + public static string Loc_StatusIconPriorizerConditionSets_InForay { + get { + return ResourceManager.GetString("Loc_StatusIconPriorizerConditionSets_InForay", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Status icons that should get priorized within foraies. ähnelt. + /// + public static string Loc_StatusIconPriorizerConditionSets_InForay_Description { + get { + return ResourceManager.GetString("Loc_StatusIconPriorizerConditionSets_InForay_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Overworld ähnelt. + /// + public static string Loc_StatusIconPriorizerConditionSets_Overworld { + get { + return ResourceManager.GetString("Loc_StatusIconPriorizerConditionSets_Overworld", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Status icons that should get priorized at overworld. ähnelt. + /// + public static string Loc_StatusIconPriorizerConditionSets_Overworld_Description { + get { + return ResourceManager.GetString("Loc_StatusIconPriorizerConditionSets_Overworld_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Busy ähnelt. + /// + public static string Loc_StatusIcons_Busy { + get { + return ResourceManager.GetString("Loc_StatusIcons_Busy", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Disconnecting ähnelt. + /// + public static string Loc_StatusIcons_Disconnecting { + get { + return ResourceManager.GetString("Loc_StatusIcons_Disconnecting", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Duty Finder ähnelt. + /// + public static string Loc_StatusIcons_DutyFinder { + get { + return ResourceManager.GetString("Loc_StatusIcons_DutyFinder", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Group Pose ähnelt. + /// + public static string Loc_StatusIcons_GroupPose { + get { + return ResourceManager.GetString("Loc_StatusIcons_GroupPose", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Idle ähnelt. + /// + public static string Loc_StatusIcons_Idle { + get { + return ResourceManager.GetString("Loc_StatusIcons_Idle", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die In Duty ähnelt. + /// + public static string Loc_StatusIcons_InDuty { + get { + return ResourceManager.GetString("Loc_StatusIcons_InDuty", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Mentor ähnelt. + /// + public static string Loc_StatusIcons_Mentor { + get { + return ResourceManager.GetString("Loc_StatusIcons_Mentor", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Mentor Crafting ähnelt. + /// + public static string Loc_StatusIcons_MentorCrafting { + get { + return ResourceManager.GetString("Loc_StatusIcons_MentorCrafting", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Mentor PvE ähnelt. + /// + public static string Loc_StatusIcons_MentorPvE { + get { + return ResourceManager.GetString("Loc_StatusIcons_MentorPvE", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Mentor PvP ähnelt. + /// + public static string Loc_StatusIcons_MentorPvP { + get { + return ResourceManager.GetString("Loc_StatusIcons_MentorPvP", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die New Adventurer ähnelt. + /// + public static string Loc_StatusIcons_NewAdventurer { + get { + return ResourceManager.GetString("Loc_StatusIcons_NewAdventurer", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Party Leader ähnelt. + /// + public static string Loc_StatusIcons_PartyLeader { + get { + return ResourceManager.GetString("Loc_StatusIcons_PartyLeader", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Party Member ähnelt. + /// + public static string Loc_StatusIcons_PartyMember { + get { + return ResourceManager.GetString("Loc_StatusIcons_PartyMember", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Returner ähnelt. + /// + public static string Loc_StatusIcons_Returner { + get { + return ResourceManager.GetString("Loc_StatusIcons_Returner", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Role Playing ähnelt. + /// + public static string Loc_StatusIcons_RolePlaying { + get { + return ResourceManager.GetString("Loc_StatusIcons_RolePlaying", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Viewing Cutscene ähnelt. + /// + public static string Loc_StatusIcons_ViewingCutscene { + get { + return ResourceManager.GetString("Loc_StatusIcons_ViewingCutscene", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die After ähnelt. /// @@ -1706,5 +1949,24 @@ public static string Loc_TextGlowColor_Description { return ResourceManager.GetString("Loc_TextGlowColor_Description", resourceCulture); } } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Use priorized icons ähnelt. + /// + public static string Loc_UsePriorizedIcons { + get { + return ResourceManager.GetString("Loc_UsePriorizedIcons", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die This option checked will force a set of status icons to be priorized over job icons, if you enabled job icons. + ///When disabled, only the disconnected status icon is priorized. ähnelt. + /// + public static string Loc_UsePriorizedIcons_Description { + get { + return ResourceManager.GetString("Loc_UsePriorizedIcons_Description", resourceCulture); + } + } } } diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index f5d3dda..9fed405 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -666,4 +666,92 @@ Defines for which chat type the chat features of this tag should be enabled for. + + Status Icon Priorizer + + + In Duty + + + Status icons that should get priorized within duties. + + + In Foray + + + Status icons that should get priorized within foraies. + + + Overworld + + + Status icons that should get priorized at overworld. + + + Reset to default + + + Resets all condition sets to the default settings + + + Reset to empty + + + Clears all condition sets to an empty collection. None status icons will be priorized. + + + Use priorized icons + + + This option checked will force a set of status icons to be priorized over job icons, if you enabled job icons. +When disabled, only the disconnected status icon is priorized. + + + Busy + + + Disconnecting + + + Duty Finder + + + Group Pose + + + Idle + + + In Duty + + + Mentor + + + Mentor Crafting + + + Mentor PvE + + + Mentor PvP + + + New Adventurer + + + Party Leader + + + Party Member + + + Returner + + + Role Playing + + + Viewing Cutscene + \ No newline at end of file From 1d69893890d1bd632daf1699dead5ebf7e4b6aa3 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 10 Nov 2022 10:30:19 +0100 Subject: [PATCH 120/174] implement Default Plugin Data Templates --- .../Configuration/PluginConfiguration.cs | 1 + PlayerTags/Data/DefaultPluginData.cs | 373 ++++++++++++++++-- PlayerTags/Data/DefaultPluginDataTemplate.cs | 16 + PlayerTags/Data/PluginData.cs | 2 +- 4 files changed, 367 insertions(+), 25 deletions(-) create mode 100644 PlayerTags/Data/DefaultPluginDataTemplate.cs diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index 6d3a2a9..5340178 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -32,6 +32,7 @@ public class PluginConfiguration : IPluginConfiguration { ActivityType.PvpDuty, new GeneralOptionsClass() } }; + public DefaultPluginDataTemplate DefaultPluginDataTemplate = DefaultPluginDataTemplate.Simple; public StatusIconPriorizerSettings StatusIconPriorizerSettings = new(true); public bool IsPlayerNameRandomlyGenerated = false; public bool IsCustomTagsContextMenuEnabled = true; diff --git a/PlayerTags/Data/DefaultPluginData.cs b/PlayerTags/Data/DefaultPluginData.cs index 1ee8fb9..e7365ba 100644 --- a/PlayerTags/Data/DefaultPluginData.cs +++ b/PlayerTags/Data/DefaultPluginData.cs @@ -9,18 +9,232 @@ namespace PlayerTags.Data { public class DefaultPluginData { - public Tag AllTags { get; } + public Tag AllTags { get; private set; } - public Tag AllRoleTags { get; } - public Dictionary RoleTags { get; } - public Dictionary DpsRoleTags { get; } - public Dictionary RangedDpsRoleTags { get; } - public Dictionary LandHandRoleTags { get; } - public Dictionary JobTags { get; } + public Tag AllRoleTags { get; private set; } + public Dictionary RoleTags { get; private set; } + public Dictionary DpsRoleTags { get; private set; } + public Dictionary RangedDpsRoleTags { get; private set; } + public Dictionary LandHandRoleTags { get; private set; } + public Dictionary JobTags { get; private set; } - public Tag AllCustomTags { get; } + public Tag AllCustomTags { get; private set; } - public DefaultPluginData() + public DefaultPluginData(DefaultPluginDataTemplate template) + { + SetupTemplate(template); + } + + private void SetupTemplate(DefaultPluginDataTemplate template) + { + Clear(); + + switch(template) + { + case DefaultPluginDataTemplate.None: + SetupTemplateNone(); + break; + case DefaultPluginDataTemplate.Basic: + SetupTemplateBasic(); + break; + case DefaultPluginDataTemplate.Simple: + SetupTemplateSimple(); + break; + case DefaultPluginDataTemplate.Full: + SetupTemplateFull(); + break; + } + + SetupJobTags(); + } + + private void Clear() + { + + RoleTags = new Dictionary(); + DpsRoleTags = new Dictionary(); + RangedDpsRoleTags = new Dictionary(); + LandHandRoleTags = new Dictionary(); + } + + private void SetupTemplateNone() + { + AllTags = new Tag() + { + IsSelected = true, + IsExpanded = true, + }; + + AllRoleTags = new Tag() + { + IsSelected = false, + IsExpanded = true, + }; + + RoleTags[Role.LandHand] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + RoleTags[Role.Tank] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + RoleTags[Role.Healer] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + RoleTags[Role.Dps] = new Tag() + { + IsSelected = false, + IsExpanded = true, + }; + + DpsRoleTags[DpsRole.Melee] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + DpsRoleTags[DpsRole.Ranged] = new Tag() + { + IsSelected = false, + IsExpanded = true, + }; + + RangedDpsRoleTags[RangedDpsRole.Magical] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + RangedDpsRoleTags[RangedDpsRole.Physical] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + LandHandRoleTags[LandHandRole.Land] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + LandHandRoleTags[LandHandRole.Hand] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + AllCustomTags = new Tag() + { + IsSelected = false, + IsExpanded = true, + }; + } + + private void SetupTemplateBasic() + { + AllTags = new Tag() + { + IsSelected = true, + IsExpanded = true, + + TagPositionInChat = TagPosition.Before, + InsertBehindNumberPrefixInChat = true, + TagPositionInNameplates = TagPosition.Replace, + TagTargetInNameplates = NameplateElement.Title, + + TargetChatTypes = new List(Enum.GetValues()), + }; + + AllRoleTags = new Tag() + { + IsSelected = false, + IsExpanded = true, + }; + + RoleTags[Role.LandHand] = new Tag() + { + IsSelected = false, + IsExpanded = false + }; + + RoleTags[Role.Tank] = new Tag() + { + IsSelected = false, + IsExpanded = false, + Icon = BitmapFontIcon.Tank, + TextColor = 546, + }; + + RoleTags[Role.Healer] = new Tag() + { + IsSelected = false, + IsExpanded = false, + Icon = BitmapFontIcon.Healer, + TextColor = 43, + }; + + RoleTags[Role.Dps] = new Tag() + { + IsSelected = false, + IsExpanded = true, + Icon = BitmapFontIcon.DPS, + TextColor = 508, + }; + + DpsRoleTags[DpsRole.Melee] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + DpsRoleTags[DpsRole.Ranged] = new Tag() + { + IsSelected = false, + IsExpanded = true, + }; + + RangedDpsRoleTags[RangedDpsRole.Magical] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + RangedDpsRoleTags[RangedDpsRole.Physical] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + LandHandRoleTags[LandHandRole.Land] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + LandHandRoleTags[LandHandRole.Hand] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + AllCustomTags = new Tag() + { + IsSelected = false, + IsExpanded = true, + IsTextVisibleInChat = true, + IsTextVisibleInNameplates = true, + }; + } + + private void SetupTemplateSimple() { AllTags = new Tag() { @@ -36,9 +250,119 @@ public DefaultPluginData() IsVisibleInPveDuties = true, IsVisibleInPvpDuties = true, - //NameplateFreeCompanyVisibility = NameplateFreeCompanyVisibility.Never, - //NameplateTitleVisibility = NameplateTitleVisibility.Always, - //NameplateTitlePosition = NameplateTitlePosition.AlwaysAboveName, + IsVisibleForSelf = true, + IsVisibleForFriendPlayers = true, + IsVisibleForPartyPlayers = true, + IsVisibleForAlliancePlayers = true, + IsVisibleForEnemyPlayers = true, + IsVisibleForOtherPlayers = true, + + TargetChatTypes = new List(Enum.GetValues()), + }; + + AllRoleTags = new Tag() + { + IsSelected = false, + IsExpanded = true, + IsRoleIconVisibleInChat = true, + IsTextVisibleInChat = true, + IsRoleIconVisibleInNameplates = true, + IsTextVisibleInNameplates = true, + IsTextColorAppliedToChatName = true, + }; + + RoleTags[Role.LandHand] = new Tag() + { + IsSelected = false, + IsExpanded = false, + Icon = BitmapFontIcon.Crafter, + TextColor = 3, + }; + + RoleTags[Role.Tank] = new Tag() + { + IsSelected = false, + IsExpanded = false, + Icon = BitmapFontIcon.Tank, + TextColor = 546, + }; + + RoleTags[Role.Healer] = new Tag() + { + IsSelected = false, + IsExpanded = false, + Icon = BitmapFontIcon.Healer, + TextColor = 43, + }; + + RoleTags[Role.Dps] = new Tag() + { + IsSelected = false, + IsExpanded = true, + Icon = BitmapFontIcon.DPS, + TextColor = 508, + }; + + DpsRoleTags[DpsRole.Melee] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + DpsRoleTags[DpsRole.Ranged] = new Tag() + { + IsSelected = false, + IsExpanded = true, + }; + + RangedDpsRoleTags[RangedDpsRole.Magical] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + RangedDpsRoleTags[RangedDpsRole.Physical] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + LandHandRoleTags[LandHandRole.Land] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + LandHandRoleTags[LandHandRole.Hand] = new Tag() + { + IsSelected = false, + IsExpanded = false, + }; + + AllCustomTags = new Tag() + { + IsSelected = false, + IsExpanded = true, + IsTextVisibleInChat = true, + IsTextVisibleInNameplates = true, + }; + } + + private void SetupTemplateFull() + { + AllTags = new Tag() + { + IsSelected = true, + IsExpanded = true, + TagPositionInChat = TagPosition.Before, + InsertBehindNumberPrefixInChat = true, + TagPositionInNameplates = TagPosition.Replace, + TagTargetInNameplates = NameplateElement.Title, + IsTextItalic = true, + + IsVisibleInOverworld = true, + IsVisibleInPveDuties = true, + IsVisibleInPvpDuties = true, IsVisibleForSelf = true, IsVisibleForFriendPlayers = true, @@ -58,10 +382,11 @@ public DefaultPluginData() IsTextVisibleInChat = true, IsRoleIconVisibleInNameplates = true, IsTextVisibleInNameplates = true, + IsTextColorAppliedToNameplateName = true, IsTextColorAppliedToChatName = true, + IsJobIconVisibleInNameplates = true, }; - RoleTags = new Dictionary(); RoleTags[Role.LandHand] = new Tag() { IsSelected = false, @@ -94,7 +419,6 @@ public DefaultPluginData() TextColor = 508, }; - DpsRoleTags = new Dictionary(); DpsRoleTags[DpsRole.Melee] = new Tag() { IsSelected = false, @@ -107,7 +431,6 @@ public DefaultPluginData() IsExpanded = true, }; - RangedDpsRoleTags = new Dictionary(); RangedDpsRoleTags[RangedDpsRole.Magical] = new Tag() { IsSelected = false, @@ -120,7 +443,6 @@ public DefaultPluginData() IsExpanded = false, }; - LandHandRoleTags = new Dictionary(); LandHandRoleTags[LandHandRole.Land] = new Tag() { IsSelected = false, @@ -133,6 +455,17 @@ public DefaultPluginData() IsExpanded = false, }; + AllCustomTags = new Tag() + { + IsSelected = false, + IsExpanded = true, + IsTextVisibleInChat = true, + IsTextVisibleInNameplates = true, + }; + } + + private void SetupJobTags() + { JobTags = new Dictionary(); var classJobs = PluginServices.DataManager.GetExcelSheet(); @@ -154,14 +487,6 @@ public DefaultPluginData() } } } - - AllCustomTags = new Tag() - { - IsSelected = false, - IsExpanded = true, - IsTextVisibleInChat = true, - IsTextVisibleInNameplates = true, - }; } } } diff --git a/PlayerTags/Data/DefaultPluginDataTemplate.cs b/PlayerTags/Data/DefaultPluginDataTemplate.cs new file mode 100644 index 0000000..98211ea --- /dev/null +++ b/PlayerTags/Data/DefaultPluginDataTemplate.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PlayerTags.Data +{ + public enum DefaultPluginDataTemplate + { + None, + Basic, + Simple, + Full + } +} diff --git a/PlayerTags/Data/PluginData.cs b/PlayerTags/Data/PluginData.cs index 50df87d..fb45206 100644 --- a/PlayerTags/Data/PluginData.cs +++ b/PlayerTags/Data/PluginData.cs @@ -31,7 +31,7 @@ public PluginData(PluginConfiguration pluginConfiguration) { m_PluginConfiguration = pluginConfiguration; - Default = new DefaultPluginData(); + Default = new DefaultPluginData(pluginConfiguration.DefaultPluginDataTemplate); // Set the default changes and saved changes AllTags = new Tag(new LocalizedPluginString(nameof(AllTags)), Default.AllTags); From c8a3f752f40ec2b9bc554fec41363159b0c77a90 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 10 Nov 2022 12:34:18 +0100 Subject: [PATCH 121/174] implement UI for default plugin data template --- .../Configuration/PluginConfigurationUI.cs | 24 +++-- PlayerTags/Data/PluginData.cs | 10 +- PlayerTags/Resources/Strings.Designer.cs | 98 +++++++++++++++++++ PlayerTags/Resources/Strings.resx | 38 +++++++ 4 files changed, 160 insertions(+), 10 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index 7c67cb8..7dfa20a 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -107,6 +107,11 @@ public void Draw() { ImGui.Spacing(); ImGui.Spacing(); + DrawComboBox(true, true, false, ref m_PluginConfiguration.DefaultPluginDataTemplate, () => + { + m_PluginData.ReloadDefault(); + SaveSettings(); + }, true, true); DrawCheckbox(nameof(m_PluginConfiguration.IsShowInheritedPropertiesEnabled), true, ref m_PluginConfiguration.IsShowInheritedPropertiesEnabled, () => SaveSettings()); ImGui.BeginGroup(); ImGui.Columns(2); @@ -272,7 +277,7 @@ public void Draw() m_PluginConfiguration.StatusIconPriorizerSettings.ResetToDefault(); SaveSettings(); } - else if (ImGui.IsItemHovered()) + if (ImGui.IsItemHovered()) ImGui.SetTooltip(Strings.Loc_StatusIconPriorizer_ResetToDefault_Description); ImGui.SameLine(); @@ -282,7 +287,7 @@ public void Draw() m_PluginConfiguration.StatusIconPriorizerSettings.ResetToEmpty(); SaveSettings(); } - else if (ImGui.IsItemHovered()) + if (ImGui.IsItemHovered()) ImGui.SetTooltip(Strings.Loc_StatusIconPriorizer_ResetToEmpty_Description); ImGui.Spacing(); @@ -294,9 +299,6 @@ public void Draw() { var conditionSet = m_PluginConfiguration.StatusIconPriorizerSettings.GetConditionSet(conditionSetName); - if (ImGui.IsItemHovered()) - ImGui.SetTooltip(Localizer.GetString(conditionSetName, true)); - foreach (var statusIcon in statusIcons) { var isChecked = conditionSet.Contains(statusIcon); @@ -314,6 +316,9 @@ public void Draw() } } + if (ImGui.IsItemHovered()) + ImGui.SetTooltip(Localizer.GetString(conditionSetName, true)); + ImGui.Spacing(); } } @@ -1207,12 +1212,14 @@ private void DrawMultiselect(string localizedStringName, InheritableRefer ImGui.PopStyleVar(); } - private void DrawComboBox(bool isLabelVisible, bool shouldLocalizeNames, bool shouldOrderNames, ref TEnum currentValue, System.Action changed) + private void DrawComboBox(bool isLabelVisible, bool shouldLocalizeNames, bool shouldOrderNames, ref TEnum currentValue, System.Action changed, bool showToolTipToLabel = false, bool showLabelInSameLine = false) where TEnum : Enum { if (isLabelVisible) { ImGui.Text(Localizer.GetString(false)); + if (showLabelInSameLine) + ImGui.SameLine(); } var currentDisplayName = shouldLocalizeNames ? Localizer.GetString(currentValue, false) : currentValue.ToString(); @@ -1253,7 +1260,10 @@ private void DrawComboBox(bool isLabelVisible, bool shouldLocalizeNames, if (ImGui.IsItemHovered() && shouldLocalizeNames) { - ImGui.SetTooltip(Localizer.GetString(currentValue, true)); + if (showToolTipToLabel) + ImGui.SetTooltip(Localizer.GetString(typeof(TEnum).Name, true)); + else + ImGui.SetTooltip(Localizer.GetString(currentValue, true)); } } diff --git a/PlayerTags/Data/PluginData.cs b/PlayerTags/Data/PluginData.cs index fb45206..c8b5481 100644 --- a/PlayerTags/Data/PluginData.cs +++ b/PlayerTags/Data/PluginData.cs @@ -25,12 +25,16 @@ public class PluginData public List CustomTags; public List Identities; - private PluginConfiguration m_PluginConfiguration; + private PluginConfiguration pluginConfiguration; public PluginData(PluginConfiguration pluginConfiguration) { - m_PluginConfiguration = pluginConfiguration; + this.pluginConfiguration = pluginConfiguration; + ReloadDefault(); + } + public void ReloadDefault() + { Default = new DefaultPluginData(pluginConfiguration.DefaultPluginDataTemplate); // Set the default changes and saved changes @@ -261,7 +265,7 @@ public Identity GetIdentity(string name, uint? worldId) if (identity.WorldId == null && worldId != null) { identity.WorldId = worldId; - m_PluginConfiguration.Save(this); + pluginConfiguration.Save(this); return identity; } diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index b09f035..b2f08bf 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -204,6 +204,104 @@ public static string Loc_CustomTags { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Template ähnelt. + /// + public static string Loc_DefaultPluginDataTemplate { + get { + return ResourceManager.GetString("Loc_DefaultPluginDataTemplate", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Basic ähnelt. + /// + public static string Loc_DefaultPluginDataTemplate_Basic { + get { + return ResourceManager.GetString("Loc_DefaultPluginDataTemplate_Basic", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Same as Empty, but includes a very basic pre-confiuration for formatting and coloring. + ///Can also be used if you want to make your own cofiguration but want basic formatting. ähnelt. + /// + public static string Loc_DefaultPluginDataTemplate_Basic_Description { + get { + return ResourceManager.GetString("Loc_DefaultPluginDataTemplate_Basic_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Here you can choose the template for all the settings below. + ///The template is used as basic set of properties. Every change you are making is what get saved. But all options from this template will not be saved. + ///This helpes you by not needing to overwrite so much properties - or by doing your completely own configuration without a template. + /// + ///Warning: + ///Changing this can cause properties to be resetted. You may loose a part of your configuration. + ///After you changed this, ensure everything is setted up how [Rest der Zeichenfolge wurde abgeschnitten]"; ähnelt. + /// + public static string Loc_DefaultPluginDataTemplate_Description { + get { + return ResourceManager.GetString("Loc_DefaultPluginDataTemplate_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Full ähnelt. + /// + public static string Loc_DefaultPluginDataTemplate_Full { + get { + return ResourceManager.GetString("Loc_DefaultPluginDataTemplate_Full", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Show the job tag with color and also color the player name element. ähnelt. + /// + public static string Loc_DefaultPluginDataTemplate_Full_Description { + get { + return ResourceManager.GetString("Loc_DefaultPluginDataTemplate_Full_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Empty ähnelt. + /// + public static string Loc_DefaultPluginDataTemplate_None { + get { + return ResourceManager.GetString("Loc_DefaultPluginDataTemplate_None", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die No single configuration made. This is an completley empty template. + ///Use this if you want to to have every option under your control or just want to make only a few configurations. ähnelt. + /// + public static string Loc_DefaultPluginDataTemplate_None_Description { + get { + return ResourceManager.GetString("Loc_DefaultPluginDataTemplate_None_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Simple ähnelt. + /// + public static string Loc_DefaultPluginDataTemplate_Simple { + get { + return ResourceManager.GetString("Loc_DefaultPluginDataTemplate_Simple", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Shows the job tag with color and the role icon by replacing the title. ähnelt. + /// + public static string Loc_DefaultPluginDataTemplate_Simple_Description { + get { + return ResourceManager.GetString("Loc_DefaultPluginDataTemplate_Simple_Description", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Melee ähnelt. /// diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 9fed405..6629cd8 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -754,4 +754,42 @@ When disabled, only the disconnected status icon is priorized. Viewing Cutscene + + Template + + + Basic + + + Same as Empty, but includes a very basic pre-confiuration for formatting and coloring. +Can also be used if you want to make your own cofiguration but want basic formatting. + + + Here you can choose the template for all the settings below. +The template is used as basic set of properties. Every change you are making is what get saved. But all options from this template will not be saved. +This helpes you by not needing to overwrite so much properties - or by doing your completely own configuration without a template. + +Warning: +Changing this can cause properties to be resetted. You may loose a part of your configuration. +After you changed this, ensure everything is setted up how you like it. + + + Full + + + Show the job tag with color and also color the player name element. + + + Empty + + + No single configuration made. This is an completley empty template. +Use this if you want to to have every option under your control or just want to make only a few configurations. + + + Simple + + + Shows the job tag with color and the role icon by replacing the title. + \ No newline at end of file From e17b884e0875e1d54a8108409c8bc8db6d00f9e7 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 10 Nov 2022 15:03:10 +0100 Subject: [PATCH 122/174] v1.8 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 352f895..90b7b1d 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.7.5.1 + 1.8.0.0 From 3e347e2bcafe91fcfd2571b62d8aff66bbe5c37d Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 13 Nov 2022 08:43:35 +0100 Subject: [PATCH 123/174] put Pilz.Dalamud and replace NuGet package with --- .../ActivityContexts/ActivityContext.cs | 25 +++ .../ActivityContextManager.cs | 85 ++++++++ Pilz.Dalamud/ActivityContexts/ActivityType.cs | 18 ++ Pilz.Dalamud/ActivityContexts/ZoneType.cs | 20 ++ Pilz.Dalamud/Extensions.cs | 41 ++++ Pilz.Dalamud/GameInterfaceHelper.cs | 153 +++++++++++++ Pilz.Dalamud/Icons/JobIconSet.cs | 27 +++ Pilz.Dalamud/Icons/JobIconSetName.cs | 24 +++ Pilz.Dalamud/Icons/JobIconSets.cs | 128 +++++++++++ .../AddonNamePlate_SetPlayerNameEventArgs.cs | 19 ++ ...NamePlate_SetPlayerNameManagedEventArgs.cs | 42 ++++ .../Nameplates/EventArgs/HookBaseEventArgs.cs | 18 ++ .../EventArgs/HookManagedBaseEventArgs.cs | 13 ++ .../EventArgs/HookWithResultBaseEventArgs.cs | 21 ++ .../HookWithResultManagedBaseEventArgs.cs | 13 ++ .../Nameplates/Model/SafeAddonNameplate.cs | 43 ++++ .../Nameplates/Model/SafeNameplateInfo.cs | 57 +++++ .../Nameplates/Model/SafeNameplateObject.cs | 128 +++++++++++ Pilz.Dalamud/Nameplates/Model/StatusIcons.cs | 31 +++ Pilz.Dalamud/Nameplates/NameplateHooks.cs | 203 ++++++++++++++++++ Pilz.Dalamud/Nameplates/NameplateManager.cs | 83 +++++++ .../Nameplates/Tools/NameplateChanges.cs | 51 +++++ .../Nameplates/Tools/NameplateChangesProps.cs | 16 ++ .../Nameplates/Tools/NameplateElements.cs | 15 ++ .../Tools/NameplateUpdateFactory.cs | 48 +++++ .../Nameplates/Tools/StatusIconPriorizer.cs | 67 ++++++ .../Tools/StatusIconPriorizerConditionSets.cs | 15 ++ .../Tools/StatusIconPriorizerSettings.cs | 92 ++++++++ Pilz.Dalamud/Pilz.Dalamud.csproj | 63 ++++++ Pilz.Dalamud/PluginServices.cs | 28 +++ Pilz.Dalamud/Tools/StatusIconFontConverter.cs | 41 ++++ Pilz.Dalamud/Tools/Strings/StringChange.cs | 24 +++ Pilz.Dalamud/Tools/Strings/StringChanges.cs | 40 ++++ .../Tools/Strings/StringChangesProps.cs | 31 +++ Pilz.Dalamud/Tools/Strings/StringPosition.cs | 15 ++ .../Tools/Strings/StringUpdateFactory.cs | 132 ++++++++++++ Pilz.Dalamud/XivApi.cs | 39 ++++ Pilz.Dalamud/packages.lock.json | 6 + PlayerTags.sln | 6 + PlayerTags/PlayerTags.csproj | 2 +- PlayerTags/packages.lock.json | 7 +- 41 files changed, 1924 insertions(+), 6 deletions(-) create mode 100644 Pilz.Dalamud/ActivityContexts/ActivityContext.cs create mode 100644 Pilz.Dalamud/ActivityContexts/ActivityContextManager.cs create mode 100644 Pilz.Dalamud/ActivityContexts/ActivityType.cs create mode 100644 Pilz.Dalamud/ActivityContexts/ZoneType.cs create mode 100644 Pilz.Dalamud/Extensions.cs create mode 100644 Pilz.Dalamud/GameInterfaceHelper.cs create mode 100644 Pilz.Dalamud/Icons/JobIconSet.cs create mode 100644 Pilz.Dalamud/Icons/JobIconSetName.cs create mode 100644 Pilz.Dalamud/Icons/JobIconSets.cs create mode 100644 Pilz.Dalamud/Nameplates/EventArgs/AddonNamePlate_SetPlayerNameEventArgs.cs create mode 100644 Pilz.Dalamud/Nameplates/EventArgs/AddonNamePlate_SetPlayerNameManagedEventArgs.cs create mode 100644 Pilz.Dalamud/Nameplates/EventArgs/HookBaseEventArgs.cs create mode 100644 Pilz.Dalamud/Nameplates/EventArgs/HookManagedBaseEventArgs.cs create mode 100644 Pilz.Dalamud/Nameplates/EventArgs/HookWithResultBaseEventArgs.cs create mode 100644 Pilz.Dalamud/Nameplates/EventArgs/HookWithResultManagedBaseEventArgs.cs create mode 100644 Pilz.Dalamud/Nameplates/Model/SafeAddonNameplate.cs create mode 100644 Pilz.Dalamud/Nameplates/Model/SafeNameplateInfo.cs create mode 100644 Pilz.Dalamud/Nameplates/Model/SafeNameplateObject.cs create mode 100644 Pilz.Dalamud/Nameplates/Model/StatusIcons.cs create mode 100644 Pilz.Dalamud/Nameplates/NameplateHooks.cs create mode 100644 Pilz.Dalamud/Nameplates/NameplateManager.cs create mode 100644 Pilz.Dalamud/Nameplates/Tools/NameplateChanges.cs create mode 100644 Pilz.Dalamud/Nameplates/Tools/NameplateChangesProps.cs create mode 100644 Pilz.Dalamud/Nameplates/Tools/NameplateElements.cs create mode 100644 Pilz.Dalamud/Nameplates/Tools/NameplateUpdateFactory.cs create mode 100644 Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizer.cs create mode 100644 Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizerConditionSets.cs create mode 100644 Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizerSettings.cs create mode 100644 Pilz.Dalamud/Pilz.Dalamud.csproj create mode 100644 Pilz.Dalamud/PluginServices.cs create mode 100644 Pilz.Dalamud/Tools/StatusIconFontConverter.cs create mode 100644 Pilz.Dalamud/Tools/Strings/StringChange.cs create mode 100644 Pilz.Dalamud/Tools/Strings/StringChanges.cs create mode 100644 Pilz.Dalamud/Tools/Strings/StringChangesProps.cs create mode 100644 Pilz.Dalamud/Tools/Strings/StringPosition.cs create mode 100644 Pilz.Dalamud/Tools/Strings/StringUpdateFactory.cs create mode 100644 Pilz.Dalamud/XivApi.cs create mode 100644 Pilz.Dalamud/packages.lock.json diff --git a/Pilz.Dalamud/ActivityContexts/ActivityContext.cs b/Pilz.Dalamud/ActivityContexts/ActivityContext.cs new file mode 100644 index 0000000..ae9fd79 --- /dev/null +++ b/Pilz.Dalamud/ActivityContexts/ActivityContext.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.ActivityContexts +{ + public class ActivityContext + { + public ActivityType ActivityType { get; init; } + public ZoneType ZoneType { get; init; } + + public ActivityContext(ActivityType activityType, ZoneType zoneType) + { + ActivityType = activityType; + ZoneType = zoneType; + } + + public bool IsInDuty + { + get => ZoneType != ZoneType.Overworld; + } + } +} diff --git a/Pilz.Dalamud/ActivityContexts/ActivityContextManager.cs b/Pilz.Dalamud/ActivityContexts/ActivityContextManager.cs new file mode 100644 index 0000000..bf218d6 --- /dev/null +++ b/Pilz.Dalamud/ActivityContexts/ActivityContextManager.cs @@ -0,0 +1,85 @@ +using Dalamud.Logging; +using Lumina.Excel; +using Lumina.Excel.GeneratedSheets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.ActivityContexts +{ + public class ActivityContextManager : IDisposable + { + public delegate void ActivityContextChangedEventHandler(ActivityContextManager sender, ActivityContext activityContext); + public event ActivityContextChangedEventHandler ActivityContextChanged; + + private readonly ExcelSheet contentFinderConditionsSheet; + + public ActivityContext CurrentActivityContext { get; protected set; } + + public ActivityContextManager() + { + // Get condition sheet + contentFinderConditionsSheet = PluginServices.DataManager.GameData.GetExcelSheet(); + + // Checks current territory type (if enabled/installed during a dutiy e.g.) + CheckCurrentTerritory(); + + // Enable event for automatic checks + PluginServices.ClientState.TerritoryChanged += ClientState_TerritoryChanged; + } + + public void Dispose() + { + PluginServices.ClientState.TerritoryChanged -= ClientState_TerritoryChanged; + } + + private void ClientState_TerritoryChanged(object? sender, ushort e) + { + CheckCurrentTerritory(); + } + + private void CheckCurrentTerritory() + { + var content = contentFinderConditionsSheet.FirstOrDefault(c => c.TerritoryType.Row == PluginServices.ClientState.TerritoryType); + ActivityType newActivityContext; + ZoneType newZoneType; + + if (content == null) + { + // No content found, so we must be on the overworld + newActivityContext = ActivityType.None; + newZoneType = ZoneType.Overworld; + } + else + { + // Check for ActivityContext + if (content.PvP) + newActivityContext = ActivityType.PvpDuty; + else + newActivityContext = ActivityType.PveDuty; + + // Find correct member type + var memberType = content.ContentMemberType.Row; + if (content.RowId == 16 || content.RowId == 15) + memberType = 2; // Praetorium and Castrum Meridianum + else if (content.RowId == 735 || content.RowId == 778) + memberType = 127; // Bozja + + // Check for ZoneType + newZoneType = memberType switch + { + 2 => ZoneType.Dungeon, + 3 => ZoneType.Raid, + 4 => ZoneType.AllianceRaid, + 127 => ZoneType.Foray, + _ => ZoneType.Dungeon, + }; + } + + CurrentActivityContext = new(newActivityContext, newZoneType); + ActivityContextChanged?.Invoke(this, CurrentActivityContext); + } + } +} diff --git a/Pilz.Dalamud/ActivityContexts/ActivityType.cs b/Pilz.Dalamud/ActivityContexts/ActivityType.cs new file mode 100644 index 0000000..d82d5ab --- /dev/null +++ b/Pilz.Dalamud/ActivityContexts/ActivityType.cs @@ -0,0 +1,18 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.ActivityContexts +{ + [JsonConverter(typeof(StringEnumConverter))] + public enum ActivityType + { + None = 0x0, + PveDuty = 0x1, + PvpDuty = 0x2 + } +} diff --git a/Pilz.Dalamud/ActivityContexts/ZoneType.cs b/Pilz.Dalamud/ActivityContexts/ZoneType.cs new file mode 100644 index 0000000..6800511 --- /dev/null +++ b/Pilz.Dalamud/ActivityContexts/ZoneType.cs @@ -0,0 +1,20 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.ActivityContexts +{ + [JsonConverter(typeof(StringEnumConverter))] + public enum ZoneType + { + Overworld, + Dungeon, + Raid, + AllianceRaid, + Foray + } +} diff --git a/Pilz.Dalamud/Extensions.cs b/Pilz.Dalamud/Extensions.cs new file mode 100644 index 0000000..08008a4 --- /dev/null +++ b/Pilz.Dalamud/Extensions.cs @@ -0,0 +1,41 @@ +using Dalamud.Game.Text.SeStringHandling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud +{ + public static class Extensions + { + /// + /// Removes a Payload from a given SeString. + /// Using SeString.Payloads.Remove() does not use the reference to compare for some reason. Tis is a workaround. + /// + /// + /// + public static void Remove(this SeString seString, Payload payload) + { + Remove(seString.Payloads, payload); + } + + /// + /// Removes a Payload from a given list. + /// Using List.Remove() does not use the reference to compare for some reason. Tis is a workaround. + /// + /// + /// + public static void Remove(this List payloads, Payload payload) + { + for (int i = 0; i < payloads.Count; i++) + { + if (ReferenceEquals(payloads[i], payload)) + { + payloads.RemoveAt(i); + break; + } + } + } + } +} diff --git a/Pilz.Dalamud/GameInterfaceHelper.cs b/Pilz.Dalamud/GameInterfaceHelper.cs new file mode 100644 index 0000000..f786f13 --- /dev/null +++ b/Pilz.Dalamud/GameInterfaceHelper.cs @@ -0,0 +1,153 @@ +using Dalamud.Game.Text.SeStringHandling; +using FFXIVClientStructs.FFXIV.Client.System.Memory; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud +{ + public static class GameInterfaceHelper + { + public static SeString ReadSeString(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + { + return new SeString(); + } + + if (TryReadStringBytes(ptr, out var bytes) && bytes != null) + { + return SeString.Parse(bytes); + } + + return new SeString(); + } + + public static bool TryReadSeString(IntPtr ptr, out SeString? seString) + { + seString = null; + if (ptr == IntPtr.Zero) + { + return false; + } + + if (TryReadStringBytes(ptr, out var bytes) && bytes != null) + { + seString = SeString.Parse(bytes); + return true; + } + + return false; + } + + public static string? ReadString(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + { + return null; + } + + if (TryReadStringBytes(ptr, out var bytes) && bytes != null) + { + return Encoding.UTF8.GetString(bytes); + } + + return null; + } + + public static bool TryReadString(IntPtr ptr, out string? str) + { + str = null; + if (ptr == IntPtr.Zero) + { + return false; + } + + if (TryReadStringBytes(ptr, out var bytes) && bytes != null) + { + str = Encoding.UTF8.GetString(bytes); + return true; + } + + return false; + } + + public static bool TryReadStringBytes(IntPtr ptr, out byte[]? bytes) + { + bytes = null; + if (ptr == IntPtr.Zero) + { + return false; + } + + var size = 0; + while (Marshal.ReadByte(ptr, size) != 0) + { + size++; + } + + bytes = new byte[size]; + Marshal.Copy(ptr, bytes, 0, size); + + return true; + } + + public static IntPtr PluginAllocate(byte[] bytes) + { + IntPtr pointer = Marshal.AllocHGlobal(bytes.Length + 1); + Marshal.Copy(bytes, 0, pointer, bytes.Length); + Marshal.WriteByte(pointer, bytes.Length, 0); + + return pointer; + } + + public static IntPtr PluginAllocate(SeString seString) + { + return PluginAllocate(seString.Encode()); + } + + public static void PluginFree(IntPtr ptr) + { + Marshal.FreeHGlobal(ptr); + } + + public static void PluginFree(ref IntPtr ptr) + { + PluginFree(ptr); + ptr = IntPtr.Zero; + } + + public static byte[] NullTerminate(this byte[] bytes) + { + if (bytes.Length == 0 || bytes[bytes.Length - 1] != 0) + { + var newBytes = new byte[bytes.Length + 1]; + Array.Copy(bytes, newBytes, bytes.Length); + newBytes[^1] = 0; + + return newBytes; + } + + return bytes; + } + + public static unsafe IntPtr GameUIAllocate(ulong size) + { + return (IntPtr)IMemorySpace.GetUISpace()->Malloc(size, 0); + } + + public static unsafe void GameFree(ref IntPtr ptr, ulong size) + { + if (ptr == IntPtr.Zero) + { + return; + } + + IMemorySpace.Free((void*)ptr, size); + ptr = IntPtr.Zero; + } + } +} diff --git a/Pilz.Dalamud/Icons/JobIconSet.cs b/Pilz.Dalamud/Icons/JobIconSet.cs new file mode 100644 index 0000000..db7acc0 --- /dev/null +++ b/Pilz.Dalamud/Icons/JobIconSet.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Icons +{ + public class JobIconSet + { + private readonly int[] icons; + + public float IconScale { get; init; } + + public JobIconSet(int[] icons, float iconScale) + { + this.icons = icons; + IconScale = iconScale; + } + + public int GetIcon(uint jobID) + { + return icons[jobID - 1]; + } + } +} diff --git a/Pilz.Dalamud/Icons/JobIconSetName.cs b/Pilz.Dalamud/Icons/JobIconSetName.cs new file mode 100644 index 0000000..7d19a2c --- /dev/null +++ b/Pilz.Dalamud/Icons/JobIconSetName.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Icons +{ + public enum JobIconSetName + { + Gold, + Framed, + Glowing, + Blue, + Red, + Purple, + Black, + Yellow, + Orange, + Green, + Grey, + Role + } +} diff --git a/Pilz.Dalamud/Icons/JobIconSets.cs b/Pilz.Dalamud/Icons/JobIconSets.cs new file mode 100644 index 0000000..376b7f5 --- /dev/null +++ b/Pilz.Dalamud/Icons/JobIconSets.cs @@ -0,0 +1,128 @@ +using Lumina.Excel.GeneratedSheets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Icons +{ + public class JobIconSets + { + private readonly Dictionary iconSets = new(); + + public JobIconSets() + { + Add(JobIconSetName.Gold, new[] + { + 62001, 62002, 62003, 62004, 62005, 62006, 62007, 62008, 62009, 62010, + 62011, 62012, 62013, 62014, 62015, 62016, 62017, 62018, 62019, 62020, + 62021, 62022, 62023, 62024, 62025, 62026, 62027, 62028, 62029, 62030, + 62031, 62032, 62033, 62034, 62035, 62036, 62037, 62038, 62039, 62040 + }, 1); + + Add(JobIconSetName.Framed, new[] + { + 62101, 62102, 62103, 62104, 62105, 62106, 62107, 62108, 62109, 62110, + 62111, 62112, 62113, 62114, 62115, 62116, 62117, 62118, 62119, 62120, + 62121, 62122, 62123, 62124, 62125, 62126, 62127, 62128, 62129, 62130, + 62131, 62132, 62133, 62134, 62135, 62136, 62137, 62138, 62139, 62140 + }); + + Add(JobIconSetName.Glowing, new[] + { + 62301, 62302, 62303, 62304, 62305, 62306, 62307, 62310, 62311, 62312, + 62313, 62314, 62315, 62316, 62317, 62318, 62319, 62320, 62401, 62402, + 62403, 62404, 62405, 62406, 62407, 62308, 62408, 62409, 62309, 62410, + 62411, 62412, 62413, 62414, 62415, 62416, 62417, 62418, 62419, 62420 + }); + + Add(JobIconSetName.Grey, new[] + { + 91022, 91023, 91024, 91025, 91026, 91028, 91029, 91031, 91032, 91033, + 91034, 91035, 91036, 91037, 91038, 91039, 91040, 91041, 91079, 91080, + 91081, 91082, 91083, 91084, 91085, 91030, 91086, 91087, 91121, 91122, + 91125, 91123, 91124, 91127, 91128, 91129, 91130, 91131, 91132, 91133 + }, 2); + + Add(JobIconSetName.Black, new[] + { + 91522, 91523, 91524, 91525, 91526, 91528, 91529, 91531, 91532, 91533, + 91534, 91535, 91536, 91537, 91538, 91539, 91540, 91541, 91579, 91580, + 91581, 91582, 91583, 91584, 91585, 91530, 91586, 91587, 91621, 91622, + 91625, 91623, 91624, 91627, 91628, 91629, 91630, 91631, 91632, 91633 + }, 2); + + Add(JobIconSetName.Yellow, new[] + { + 92022, 92023, 92024, 92025, 92026, 92028, 92029, 92031, 92032, 92033, + 92034, 92035, 92036, 92037, 92038, 92039, 92040, 92041, 92079, 92080, + 92081, 92082, 92083, 92084, 92085, 92030, 92086, 92087, 92121, 92122, + 92125, 92123, 92124, 92127, 92128, 92129, 92130, 92131, 92132, 92133 + }, 2); + + Add(JobIconSetName.Orange, new[] + { + 92522, 92523, 92524, 92525, 92526, 92528, 92529, 92531, 92532, 92533, + 92534, 92535, 92536, 92537, 92538, 92539, 92540, 92541, 92579, 92580, + 92581, 92582, 92583, 92584, 92585, 92530, 92586, 92587, 92621, 92622, + 92625, 92623, 92624, 92627, 92628, 92629, 92630, 92631, 92632, 92633 + }, 2); + + Add(JobIconSetName.Red, new[] + { + 93022, 93023, 93024, 93025, 93026, 93028, 93029, 93031, 93032, 93033, + 93034, 93035, 93036, 93037, 93038, 93039, 93040, 93041, 93079, 93080, + 93081, 93082, 93083, 93084, 93085, 93030, 93086, 93087, 93121, 93122, + 93125, 93123, 93124, 93127, 93128, 93129, 93130, 93131, 93132, 93133 + }, 2); + + Add(JobIconSetName.Purple, new[] + { + 93522, 93523, 93524, 93525, 93526, 93528, 93529, 93531, 93532, 93533, + 93534, 93535, 93536, 93537, 93538, 93539, 93540, 93541, 93579, 93580, + 93581, 93582, 93583, 93584, 93585, 93530, 93586, 93587, 93621, 93622, + 93625, 93623, 93624, 93627, 93628, 93629, 93630, 93631, 93632, 93633 + }, 2); + + Add(JobIconSetName.Blue, new[] + { + 94022, 94023, 94024, 94025, 94026, 94028, 94029, 94031, 94032, 94033, + 94034, 94035, 94036, 94037, 94038, 94039, 94040, 94041, 94079, 94080, + 94081, 94082, 94083, 94084, 94085, 94030, 94086, 94087, 94121, 94122, + 94125, 94123, 94124, 94127, 94128, 94129, 94130, 94131, 94132, 94133 + }, 2); + + Add(JobIconSetName.Green, new[] + { + 94522, 94523, 94524, 94525, 94526, 94528, 94529, 94531, 94532, 94533, + 94534, 94535, 94536, 94537, 94538, 94539, 94540, 94541, 94579, 94580, + 94581, 94582, 94583, 94584, 94585, 94530, 94586, 94587, 94621, 94622, + 94625, 94623, 94624, 94627, 94628, 94629, 94630, 94631, 94632, 94633 + }, 2); + + Add(JobIconSetName.Role, new[] + { + 62581, 62584, 62581, 62584, 62586, 62582, 62502, 62502, 62503, 62504, + 62505, 62506, 62507, 62508, 62509, 62510, 62511, 62512, 62581, 62584, + 62581, 62584, 62586, 62582, 62587, 62587, 62587, 62582, 62584, 62584, + 62586, 62581, 62582, 62584, 62587, 62587, 62581, 62586, 62584, 62582 + }); + } + + private void Add(JobIconSetName id, int[] icons, float scale = 1f) + { + iconSets[id] = new JobIconSet(icons, scale); + } + + public int GetJobIcon(JobIconSetName set, uint jobId) + { + return iconSets[set].GetIcon(jobId); + } + + public float GetJobIconSale(JobIconSetName set) + { + return iconSets[set].IconScale; + } + } +} diff --git a/Pilz.Dalamud/Nameplates/EventArgs/AddonNamePlate_SetPlayerNameEventArgs.cs b/Pilz.Dalamud/Nameplates/EventArgs/AddonNamePlate_SetPlayerNameEventArgs.cs new file mode 100644 index 0000000..3a67e2b --- /dev/null +++ b/Pilz.Dalamud/Nameplates/EventArgs/AddonNamePlate_SetPlayerNameEventArgs.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.EventArgs +{ + public class AddonNamePlate_SetPlayerNameEventArgs : HookWithResultBaseEventArgs + { + public IntPtr PlayerNameplateObjectPtr { get; set; } + public IntPtr TitlePtr { get; set; } + public IntPtr NamePtr { get; set; } + public IntPtr FreeCompanyPtr { get; set; } + public bool IsTitleAboveName { get; set; } + public bool IsTitleVisible { get; set; } + public int IconID { get; set; } + } +} diff --git a/Pilz.Dalamud/Nameplates/EventArgs/AddonNamePlate_SetPlayerNameManagedEventArgs.cs b/Pilz.Dalamud/Nameplates/EventArgs/AddonNamePlate_SetPlayerNameManagedEventArgs.cs new file mode 100644 index 0000000..494bdd1 --- /dev/null +++ b/Pilz.Dalamud/Nameplates/EventArgs/AddonNamePlate_SetPlayerNameManagedEventArgs.cs @@ -0,0 +1,42 @@ +using Dalamud.Game.Text.SeStringHandling; +using Pilz.Dalamud.Nameplates.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.EventArgs +{ + public class AddonNamePlate_SetPlayerNameManagedEventArgs : HookWithResultManagedBaseEventArgs + { + public new AddonNamePlate_SetPlayerNameEventArgs OriginalEventArgs + { + get => base.OriginalEventArgs as AddonNamePlate_SetPlayerNameEventArgs; + set => base.OriginalEventArgs = value; + } + + public SafeNameplateObject SafeNameplateObject { get; set; } + public SeString Title { get; set; } + public SeString Name { get; set; } + public SeString FreeCompany { get; set; } + + public bool IsTitleAboveName + { + get => OriginalEventArgs.IsTitleAboveName; + set => OriginalEventArgs.IsTitleAboveName = value; + } + + public bool IsTitleVisible + { + get => OriginalEventArgs.IsTitleVisible; + set => OriginalEventArgs.IsTitleVisible = value; + } + + public int IconID + { + get => OriginalEventArgs.IconID; + set => OriginalEventArgs.IconID = value; + } + } +} diff --git a/Pilz.Dalamud/Nameplates/EventArgs/HookBaseEventArgs.cs b/Pilz.Dalamud/Nameplates/EventArgs/HookBaseEventArgs.cs new file mode 100644 index 0000000..2df854d --- /dev/null +++ b/Pilz.Dalamud/Nameplates/EventArgs/HookBaseEventArgs.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.EventArgs +{ + public abstract class HookBaseEventArgs + { + internal event Action CallOriginal; + + public void Original() + { + CallOriginal?.Invoke(); + } + } +} diff --git a/Pilz.Dalamud/Nameplates/EventArgs/HookManagedBaseEventArgs.cs b/Pilz.Dalamud/Nameplates/EventArgs/HookManagedBaseEventArgs.cs new file mode 100644 index 0000000..71df630 --- /dev/null +++ b/Pilz.Dalamud/Nameplates/EventArgs/HookManagedBaseEventArgs.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.EventArgs +{ + public abstract class HookManagedBaseEventArgs + { + public HookBaseEventArgs OriginalEventArgs { get; internal set; } + } +} diff --git a/Pilz.Dalamud/Nameplates/EventArgs/HookWithResultBaseEventArgs.cs b/Pilz.Dalamud/Nameplates/EventArgs/HookWithResultBaseEventArgs.cs new file mode 100644 index 0000000..ad3c130 --- /dev/null +++ b/Pilz.Dalamud/Nameplates/EventArgs/HookWithResultBaseEventArgs.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.EventArgs +{ + public abstract class HookWithResultBaseEventArgs + { + internal event Func CallOriginal; + + public TResult Result { get; set; } + + // Call Original based on the given properties + public TResult Original() + { + return CallOriginal.Invoke(); + } + } +} diff --git a/Pilz.Dalamud/Nameplates/EventArgs/HookWithResultManagedBaseEventArgs.cs b/Pilz.Dalamud/Nameplates/EventArgs/HookWithResultManagedBaseEventArgs.cs new file mode 100644 index 0000000..59993fd --- /dev/null +++ b/Pilz.Dalamud/Nameplates/EventArgs/HookWithResultManagedBaseEventArgs.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.EventArgs +{ + public abstract class HookWithResultManagedBaseEventArgs + { + public HookWithResultBaseEventArgs OriginalEventArgs { get; internal set; } + } +} diff --git a/Pilz.Dalamud/Nameplates/Model/SafeAddonNameplate.cs b/Pilz.Dalamud/Nameplates/Model/SafeAddonNameplate.cs new file mode 100644 index 0000000..2b8736b --- /dev/null +++ b/Pilz.Dalamud/Nameplates/Model/SafeAddonNameplate.cs @@ -0,0 +1,43 @@ +using Dalamud.Logging; +using Dalamud.Plugin; +using FFXIVClientStructs.FFXIV.Client.UI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.Model +{ + public class SafeAddonNameplate + { + private readonly DalamudPluginInterface Interface; + + public IntPtr Pointer => PluginServices.GameGui.GetAddonByName("NamePlate", 1); + + public SafeAddonNameplate(DalamudPluginInterface pluginInterface) + { + Interface = pluginInterface; + } + + public unsafe SafeNameplateObject GetNamePlateObject(int index) + { + SafeNameplateObject result = null; + + if (Pointer != IntPtr.Zero) + { + var npObjectArrayPtrPtr = Pointer + Marshal.OffsetOf(typeof(AddonNamePlate), nameof(AddonNamePlate.NamePlateObjectArray)).ToInt32(); + var npObjectArrayPtr = Marshal.ReadIntPtr(npObjectArrayPtrPtr); + + if (npObjectArrayPtr != IntPtr.Zero) + { + var npObjectPtr = npObjectArrayPtr + Marshal.SizeOf(typeof(AddonNamePlate.NamePlateObject)) * index; + result = new(npObjectPtr, index); + } + } + + return result; + } + } +} diff --git a/Pilz.Dalamud/Nameplates/Model/SafeNameplateInfo.cs b/Pilz.Dalamud/Nameplates/Model/SafeNameplateInfo.cs new file mode 100644 index 0000000..5076d63 --- /dev/null +++ b/Pilz.Dalamud/Nameplates/Model/SafeNameplateInfo.cs @@ -0,0 +1,57 @@ +using FFXIVClientStructs.FFXIV.Client.System.String; +using FFXIVClientStructs.FFXIV.Client.UI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.Model +{ + public class SafeNameplateInfo + { + public readonly IntPtr Pointer; + public readonly RaptureAtkModule.NamePlateInfo Data; + + public SafeNameplateInfo(IntPtr pointer) + { + Pointer = pointer; + Data = Marshal.PtrToStructure(Pointer); + } + + internal IntPtr NameAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.Name)); + internal IntPtr FcNameAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.FcName)); + internal IntPtr TitleAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.Title)); + internal IntPtr DisplayTitleAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.DisplayTitle)); + internal IntPtr LevelTextAddress => GetStringPtr(nameof(RaptureAtkModule.NamePlateInfo.LevelText)); + + public string Name => GetString(NameAddress); + public string FcName => GetString(FcNameAddress); + public string Title => GetString(TitleAddress); + public string DisplayTitle => GetString(DisplayTitleAddress); + public string LevelText => GetString(LevelTextAddress); + + //public bool IsPlayerCharacter() => XivApi.IsPlayerCharacter(Data.ObjectID.ObjectID); + + //public bool IsPartyMember() => XivApi.IsPartyMember(Data.ObjectID.ObjectID); + + //public bool IsAllianceMember() => XivApi.IsAllianceMember(Data.ObjectID.ObjectID); + + //public uint GetJobID() => GetJobId(Data.ObjectID.ObjectID); + + private unsafe IntPtr GetStringPtr(string name) + { + var namePtr = Pointer + Marshal.OffsetOf(typeof(RaptureAtkModule.NamePlateInfo), name).ToInt32(); + var stringPtrPtr = namePtr + Marshal.OffsetOf(typeof(Utf8String), nameof(Utf8String.StringPtr)).ToInt32(); + var stringPtr = Marshal.ReadIntPtr(stringPtrPtr); + return stringPtr; + } + + private string GetString(IntPtr stringPtr) + { + return Marshal.PtrToStringUTF8(stringPtr); + } + } +} diff --git a/Pilz.Dalamud/Nameplates/Model/SafeNameplateObject.cs b/Pilz.Dalamud/Nameplates/Model/SafeNameplateObject.cs new file mode 100644 index 0000000..6a39ba0 --- /dev/null +++ b/Pilz.Dalamud/Nameplates/Model/SafeNameplateObject.cs @@ -0,0 +1,128 @@ +using Dalamud.Logging; +using FFXIVClientStructs.FFXIV.Client.UI; +using FFXIVClientStructs.FFXIV.Component.GUI; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.Model +{ + public class SafeNameplateObject + { + public IntPtr Pointer { get; } + public AddonNamePlate.NamePlateObject Data { get; } + + private int _Index; + private SafeNameplateInfo _NamePlateInfo; + + public SafeNameplateObject(IntPtr pointer, int index = -1) + { + Pointer = pointer; + Data = Marshal.PtrToStructure(pointer); + _Index = index; + } + + public int Index + { + get + { + int result = _Index; + + if (_Index == -1) + { + var addon = XivApi.GetSafeAddonNamePlate(); + var npObject0 = addon.GetNamePlateObject(0); + + if (npObject0 == null) + result = -1; // NamePlateObject0 was null + else + { + var npObjectBase = npObject0.Pointer; + var npObjectSize = Marshal.SizeOf(typeof(AddonNamePlate.NamePlateObject)); + var index = (Pointer.ToInt64() - npObjectBase.ToInt64()) / npObjectSize; + + if (index < 0 || index >= 50) + result = -2; // NamePlateObject index was out of bounds + else + result = _Index = (int)index; + } + } + + return result; + } + } + + public SafeNameplateInfo NamePlateInfo + { + get + { + SafeNameplateInfo result = null; + + if (_NamePlateInfo != null) + { + var rapturePtr = XivApi.RaptureAtkModulePtr; + + if (rapturePtr != IntPtr.Zero) + { + var npInfoArrayPtr = rapturePtr + Marshal.OffsetOf(typeof(RaptureAtkModule), nameof(RaptureAtkModule.NamePlateInfoArray)).ToInt32(); + var npInfoPtr = npInfoArrayPtr + Marshal.SizeOf(typeof(RaptureAtkModule.NamePlateInfo)) * Index; + result = _NamePlateInfo = new SafeNameplateInfo(npInfoPtr); + } + } + + return result; + } + } + + #region Getters + + public unsafe IntPtr IconImageNodeAddress => Marshal.ReadIntPtr(Pointer + Marshal.OffsetOf(typeof(AddonNamePlate.NamePlateObject), nameof(AddonNamePlate.NamePlateObject.IconImageNode)).ToInt32()); + public unsafe IntPtr NameNodeAddress => Marshal.ReadIntPtr(Pointer + Marshal.OffsetOf(typeof(AddonNamePlate.NamePlateObject), nameof(AddonNamePlate.NamePlateObject.NameText)).ToInt32()); + + public AtkImageNode IconImageNode => Marshal.PtrToStructure(IconImageNodeAddress); + public AtkTextNode NameTextNode => Marshal.PtrToStructure(NameNodeAddress); + + #endregion + + public unsafe bool IsVisible => Data.IsVisible; + public unsafe bool IsLocalPlayer => Data.IsLocalPlayer; + public bool IsPlayer => Data.NameplateKind == 0; + + //public void SetIconScale(float scale, bool force = false) + //{ + // if (force || IconImageNode.AtkResNode.ScaleX != scale || IconImageNode.AtkResNode.ScaleY != scale) + // { + // Instance.SetNodeScale(IconImageNodeAddress, scale, scale); + // } + //} + + //public void SetNameScale(float scale, bool force = false) + //{ + // if (force || NameTextNode.AtkResNode.ScaleX != scale || NameTextNode.AtkResNode.ScaleY != scale) + // { + // Instance.SetNodeScale(NameNodeAddress, scale, scale); + // } + //} + + //public unsafe void SetName(IntPtr ptr) + //{ + // NameTextNode.SetText("aaa"); + //} + + //public void SetIcon(int icon) + //{ + // IconImageNode.LoadIconTexture(icon, 1); + //} + + public void SetIconPosition(short x, short y) + { + var iconXAdjustPtr = Pointer + Marshal.OffsetOf(typeof(AddonNamePlate.NamePlateObject), nameof(AddonNamePlate.NamePlateObject.IconXAdjust)).ToInt32(); + var iconYAdjustPtr = Pointer + Marshal.OffsetOf(typeof(AddonNamePlate.NamePlateObject), nameof(AddonNamePlate.NamePlateObject.IconYAdjust)).ToInt32(); + Marshal.WriteInt16(iconXAdjustPtr, x); + Marshal.WriteInt16(iconYAdjustPtr, y); + } + } +} diff --git a/Pilz.Dalamud/Nameplates/Model/StatusIcons.cs b/Pilz.Dalamud/Nameplates/Model/StatusIcons.cs new file mode 100644 index 0000000..89d7448 --- /dev/null +++ b/Pilz.Dalamud/Nameplates/Model/StatusIcons.cs @@ -0,0 +1,31 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.Model +{ + [JsonConverter(typeof(StringEnumConverter))] + public enum StatusIcons + { + Disconnecting = 061503, + InDuty = 061506, + ViewingCutscene = 061508, + Busy = 061509, + Idle = 061511, + DutyFinder = 061517, + PartyLeader = 061521, + PartyMember = 061522, + RolePlaying = 061545, + GroupPose = 061546, + NewAdventurer = 061523, + Mentor = 061540, + MentorPvE = 061542, + MentorCrafting = 061543, + MentorPvP = 061544, + Returner = 061547, + } +} diff --git a/Pilz.Dalamud/Nameplates/NameplateHooks.cs b/Pilz.Dalamud/Nameplates/NameplateHooks.cs new file mode 100644 index 0000000..1d28eb4 --- /dev/null +++ b/Pilz.Dalamud/Nameplates/NameplateHooks.cs @@ -0,0 +1,203 @@ +using Dalamud.Hooking; +using Pilz.Dalamud.Nameplates.EventArgs; +using Dalamud.Utility.Signatures; +using ImGuiNET; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Pilz.Dalamud.Nameplates.Model; +using Lumina.Excel.GeneratedSheets; +using System.Xml.Linq; + +namespace Pilz.Dalamud.Nameplates +{ + public class NameplateHooks : IDisposable + { + /// + /// Will be executed when the the Game wants to update the content of a nameplate with the details of the Player. + /// + public event AddonNamePlate_SetPlayerNameEventHandler AddonNamePlate_SetPlayerName; + public delegate void AddonNamePlate_SetPlayerNameEventHandler(AddonNamePlate_SetPlayerNameEventArgs eventArgs); + + /// + /// Will be executed when the the Game wants to update the content of a nameplate with the details of the Player. + /// This will event acts on a higher level with SeString instead of IntPtr e.g. + /// + public event AddonNamePlate_SetPlayerNameManagedEventHandler AddonNamePlate_SetPlayerNameManaged; + public delegate void AddonNamePlate_SetPlayerNameManagedEventHandler(AddonNamePlate_SetPlayerNameManagedEventArgs eventArgs); + + [Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 56 57 41 54 41 56 41 57 48 83 EC 40 44 0F B6 E2", DetourName = nameof(SetPlayerNameplateDetour))] + private readonly Hook? hook_AddonNamePlate_SetPlayerNameplateDetour = null; + private unsafe delegate IntPtr AddonNamePlate_SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId); + + /// + /// Defines if all hooks are enabled. If this is false, then there might be something wrong or the class already has been disposed. + /// + public bool IsValid + { + get + { + var isValid = true; + + isValid &= IsHookEnabled(hook_AddonNamePlate_SetPlayerNameplateDetour); + + return isValid; + } + } + + /// + /// Create a new instance of NAmeplateHooks and automatically initialize and enable all Hooks. + /// + public NameplateHooks() + { + SignatureHelper.Initialise(this); + } + + ~NameplateHooks() + { + Dispose(); + } + + public void Dispose() + { + Unhook(); + } + + /// + /// Initialize and enable all Hooks. + /// + internal void Initialize() + { + hook_AddonNamePlate_SetPlayerNameplateDetour?.Enable(); + } + + /// + /// Disable all Hooks. + /// + internal void Unhook() + { + hook_AddonNamePlate_SetPlayerNameplateDetour?.Disable(); + } + + private static bool IsHookEnabled(Hook hook) where T : Delegate + { + return hook != null && hook.IsEnabled; + } + + private IntPtr SetPlayerNameplateDetour(IntPtr playerNameplateObjectPtr, bool isTitleAboveName, bool isTitleVisible, IntPtr titlePtr, IntPtr namePtr, IntPtr freeCompanyPtr, int iconId) + { + var result = IntPtr.Zero; + + if (IsHookEnabled(hook_AddonNamePlate_SetPlayerNameplateDetour)) + { + var eventArgs = new AddonNamePlate_SetPlayerNameEventArgs + { + PlayerNameplateObjectPtr = playerNameplateObjectPtr, + TitlePtr = titlePtr, + NamePtr = namePtr, + FreeCompanyPtr = freeCompanyPtr, + IsTitleAboveName = isTitleAboveName, + IsTitleVisible = isTitleVisible, + IconID = iconId + }; + + void callOriginal() + { + eventArgs.Result = eventArgs.Original(); + } + + // Add handler for the Original call + eventArgs.CallOriginal += () => + { + return hook_AddonNamePlate_SetPlayerNameplateDetour.Original( + eventArgs.PlayerNameplateObjectPtr, + eventArgs.IsTitleAboveName, + eventArgs.IsTitleVisible, + eventArgs.TitlePtr, + eventArgs.NamePtr, + eventArgs.FreeCompanyPtr, + eventArgs.IconID); + }; + + // Invoke Event + var hasDefaultHookEvent = AddonNamePlate_SetPlayerName != null; + AddonNamePlate_SetPlayerName?.Invoke(eventArgs); + + if (AddonNamePlate_SetPlayerNameManaged != null) + { + var freeTitle = false; + var freeName = false; + var freeFreeCompany = false; + + // Create NamePlateObject if possible + var namePlateObj = new SafeNameplateObject(playerNameplateObjectPtr); + + // Create new event + var managedEventArgs = new AddonNamePlate_SetPlayerNameManagedEventArgs + { + OriginalEventArgs = eventArgs, + SafeNameplateObject = namePlateObj, + Title = GameInterfaceHelper.ReadSeString(eventArgs.TitlePtr), + Name = GameInterfaceHelper.ReadSeString(eventArgs.NamePtr), + FreeCompany = GameInterfaceHelper.ReadSeString(eventArgs.FreeCompanyPtr) + }; + + // Get raw string content + var titleRaw = managedEventArgs.Title.Encode(); + var nameRaw = managedEventArgs.Name.Encode(); + var freeCompanyRaw = managedEventArgs.FreeCompany.Encode(); + + // Invoke Managed Event + AddonNamePlate_SetPlayerNameManaged.Invoke(managedEventArgs); + + // Get new Title string ontent + var titleNewRaw = managedEventArgs.Title.Encode(); + if (!titleRaw.SequenceEqual(titleNewRaw)) + { + eventArgs.TitlePtr = GameInterfaceHelper.PluginAllocate(titleNewRaw); + freeTitle = true; + } + + // Get new Name string ontent + var nameNewRaw = managedEventArgs.Name.Encode(); + if (!nameRaw.SequenceEqual(nameNewRaw)) + { + eventArgs.NamePtr = GameInterfaceHelper.PluginAllocate(nameNewRaw); + freeName = true; + } + + // Get new Free Company string ontent + var freeCompanyNewRaw = managedEventArgs.FreeCompany.Encode(); + if (!freeCompanyRaw.SequenceEqual(freeCompanyNewRaw)) + { + eventArgs.FreeCompanyPtr = GameInterfaceHelper.PluginAllocate(freeCompanyNewRaw); + freeFreeCompany = true; + } + + // Call Original as we changed something + callOriginal(); + + // Free memory + if (freeTitle) + GameInterfaceHelper.PluginFree(eventArgs.TitlePtr); + if (freeName) + GameInterfaceHelper.PluginFree(eventArgs.NamePtr); + if (freeFreeCompany) + GameInterfaceHelper.PluginFree(eventArgs.FreeCompanyPtr); + } + else if(!hasDefaultHookEvent) + { + // Call original in case of nothing get called, just to get secure it will not break the game when not calling it. + callOriginal(); + } + + // Set result + result = eventArgs.Result; + } + + return result; + } + } +} diff --git a/Pilz.Dalamud/Nameplates/NameplateManager.cs b/Pilz.Dalamud/Nameplates/NameplateManager.cs new file mode 100644 index 0000000..8fbd04a --- /dev/null +++ b/Pilz.Dalamud/Nameplates/NameplateManager.cs @@ -0,0 +1,83 @@ +using Dalamud.Hooking; +using Pilz.Dalamud.Nameplates.EventArgs; +using Dalamud.Utility.Signatures; +using FFXIVClientStructs.FFXIV.Client.UI; +using System.Runtime.InteropServices; +using Dalamud.Game.ClientState.Objects.Types; +using Pilz.Dalamud.Nameplates.Model; + +namespace Pilz.Dalamud.Nameplates +{ + public class NameplateManager : IDisposable + { + /// + /// Provides events that you can hook to. + /// + public NameplateHooks Hooks { get; init; } = new(); + + /// + /// Defines if all hooks are enabled and the NameplateManager is ready to go. If this is false, then there might be something wrong or something already has been disposed. + /// + public bool IsValid => Hooks.IsValid; + + /// + /// Creates a new instance of the NameplateManager. + /// + public NameplateManager() + { + Hooks.Initialize(); + } + + ~NameplateManager() + { + Dispose(); + } + + public void Dispose() + { + Hooks?.Dispose(); + } + + public static T? GetNameplateGameObject(SafeNameplateObject namePlateObject) where T : GameObject + { + return GetNameplateGameObject(namePlateObject.Pointer); + } + + public static T? GetNameplateGameObject(IntPtr nameplateObjectPtr) where T : GameObject + { + // Get the nameplate object array + var nameplateAddonPtr = PluginServices.GameGui.GetAddonByName("NamePlate", 1); + var nameplateObjectArrayPtrPtr = nameplateAddonPtr + Marshal.OffsetOf(typeof(AddonNamePlate), nameof(AddonNamePlate.NamePlateObjectArray)).ToInt32(); + var nameplateObjectArrayPtr = Marshal.ReadIntPtr(nameplateObjectArrayPtrPtr); + if (nameplateObjectArrayPtr == IntPtr.Zero) + { + return null; + } + + // Determine the index of the nameplate object within the nameplate object array + var namePlateObjectSize = Marshal.SizeOf(typeof(AddonNamePlate.NamePlateObject)); + var namePlateObjectPtr0 = nameplateObjectArrayPtr + namePlateObjectSize * 0; + var namePlateIndex = (nameplateObjectPtr.ToInt64() - namePlateObjectPtr0.ToInt64()) / namePlateObjectSize; + if (namePlateIndex < 0 || namePlateIndex >= AddonNamePlate.NumNamePlateObjects) + { + return null; + } + + // Get the nameplate info array + IntPtr nameplateInfoArrayPtr = IntPtr.Zero; + unsafe + { + var framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance(); + nameplateInfoArrayPtr = new IntPtr(&framework->GetUiModule()->GetRaptureAtkModule()->NamePlateInfoArray); + } + + // Get the nameplate info for the nameplate object + var namePlateInfoPtr = new IntPtr(nameplateInfoArrayPtr.ToInt64() + Marshal.SizeOf(typeof(RaptureAtkModule.NamePlateInfo)) * namePlateIndex); + RaptureAtkModule.NamePlateInfo namePlateInfo = Marshal.PtrToStructure(namePlateInfoPtr); + + // Return the object for its object id + var objectId = namePlateInfo.ObjectID.ObjectID; + return PluginServices.ObjectTable.SearchById(objectId) as T; + } + } +} diff --git a/Pilz.Dalamud/Nameplates/Tools/NameplateChanges.cs b/Pilz.Dalamud/Nameplates/Tools/NameplateChanges.cs new file mode 100644 index 0000000..b33c372 --- /dev/null +++ b/Pilz.Dalamud/Nameplates/Tools/NameplateChanges.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Pilz.Dalamud.Tools.Strings; + +namespace Pilz.Dalamud.Nameplates.Tools +{ + public class NameplateChanges + { + private readonly Dictionary changes = new(); + + public NameplateChanges() + { + changes.Add(NameplateElements.Title, new()); + changes.Add(NameplateElements.Name, new()); + changes.Add(NameplateElements.FreeCompany, new()); + } + + /// + /// Gets the properties with the changes of an element of your choice where you can add your payloads to a change and setup some options. + /// + /// The position of your choice. + /// + public StringChangesProps GetProps(NameplateElements element) + { + return changes[element]; + } + + /// + /// Gets the changes of an element of your choice where you can add your payloads to a change. + /// + /// The position of your choice. + /// + public StringChanges GetChanges(NameplateElements element) + { + return GetProps(element).StringChanges; + } + + /// + /// Gets a change of the position of the element of your choice where you can add your payloads. + /// + /// The position of your choice. + /// + public StringChange GetChange(NameplateElements element, StringPosition position) + { + return GetChanges(element).GetChange(position); + } + } +} diff --git a/Pilz.Dalamud/Nameplates/Tools/NameplateChangesProps.cs b/Pilz.Dalamud/Nameplates/Tools/NameplateChangesProps.cs new file mode 100644 index 0000000..56f7017 --- /dev/null +++ b/Pilz.Dalamud/Nameplates/Tools/NameplateChangesProps.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.Tools +{ + public class NameplateChangesProps + { + /// + /// All the changes to the nameplate that should be made. + /// + public NameplateChanges Changes { get; set; } + } +} diff --git a/Pilz.Dalamud/Nameplates/Tools/NameplateElements.cs b/Pilz.Dalamud/Nameplates/Tools/NameplateElements.cs new file mode 100644 index 0000000..0a15cf9 --- /dev/null +++ b/Pilz.Dalamud/Nameplates/Tools/NameplateElements.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.Tools +{ + public enum NameplateElements + { + Name, + Title, + FreeCompany + } +} diff --git a/Pilz.Dalamud/Nameplates/Tools/NameplateUpdateFactory.cs b/Pilz.Dalamud/Nameplates/Tools/NameplateUpdateFactory.cs new file mode 100644 index 0000000..b04f947 --- /dev/null +++ b/Pilz.Dalamud/Nameplates/Tools/NameplateUpdateFactory.cs @@ -0,0 +1,48 @@ +using Dalamud.Game.Text.SeStringHandling; +using Dalamud.Game.Text.SeStringHandling.Payloads; +using Pilz.Dalamud.ActivityContexts; +using Pilz.Dalamud.Nameplates.Model; +using Pilz.Dalamud.Tools; +using Pilz.Dalamud.Tools.Strings; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.Tools +{ + public static class NameplateUpdateFactory + { + public static void ApplyNameplateChanges(NameplateChangesProps props) + { + foreach (NameplateElements element in Enum.GetValues(typeof(NameplateElements))) + { + var change = props.Changes.GetProps(element); + StringUpdateFactory.ApplyStringChanges(change); + } + } + + public static bool ApplyStatusIconWithPrio(ref int statusIcon, int newStatusIcon, StringChange stringChange, ActivityContext activityContext, StatusIconPriorizer priorizer) + { + var isPrio = priorizer.IsPriorityIcon(statusIcon, activityContext); + + if (!isPrio) + { + var fontIcon = StatusIconFontConverter.GetBitmapFontIconFromStatusIcon((StatusIcons)statusIcon); + + if (fontIcon != null) + { + // Set new font icon as string change + var iconPayload = new IconPayload(fontIcon.Value); + stringChange.Payloads.Insert(0, iconPayload); + + // Use new status icon as status icon + statusIcon = newStatusIcon; + } + } + + return isPrio; + } + } +} diff --git a/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizer.cs b/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizer.cs new file mode 100644 index 0000000..6d0c6fa --- /dev/null +++ b/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizer.cs @@ -0,0 +1,67 @@ +using Lumina.Excel.GeneratedSheets; +using Pilz.Dalamud.ActivityContexts; +using Pilz.Dalamud.Nameplates.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.Tools +{ + public class StatusIconPriorizer + { + private static StatusIconPriorizerSettings DefaultSettings { get; } = new(); + public StatusIconPriorizerSettings Settings { get; init; } + + public StatusIconPriorizer() : this(DefaultSettings) + { + } + + public StatusIconPriorizer(StatusIconPriorizerSettings settings) + { + Settings = settings; + } + + /// + /// Check for an icon that should take priority over the job icon, + /// taking into account whether or not the player is in a duty. + /// + /// The incoming icon id that is being overwritten by the plugin. + /// The icon id that should be used. + /// Whether a priority icon was found. + public bool IsPriorityIcon(int iconId, ActivityContext activityContext) + { + bool isPrioIcon; + + if (!Settings.UsePriorizedIcons && iconId != (int)StatusIcons.Disconnecting && iconId != (int)StatusIcons.Disconnecting + 50) + isPrioIcon = false; + else + { + // Select which set of priority icons to use based on whether we're in a duty + // In the future, there can be a third list used when in combat + var priorityIcons = GetPriorityIcons(activityContext); + + // Determine whether the incoming icon should take priority over the job icon + // Check the id plus 50 as that's an alternately sized version + isPrioIcon = priorityIcons.Contains(iconId) || priorityIcons.Contains(iconId + 50); + } + + return isPrioIcon; + } + + private IEnumerable GetPriorityIcons(ActivityContext activityContext) + { + StatusIconPriorizerConditionSets set; + + if (activityContext.ZoneType == ZoneType.Foray) + set = StatusIconPriorizerConditionSets.InForay; + else if (activityContext.IsInDuty) + set = StatusIconPriorizerConditionSets.InDuty; + else + set = StatusIconPriorizerConditionSets.Overworld; + + return Settings.GetConditionSet(set).Select(n => (int)n); + } + } +} diff --git a/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizerConditionSets.cs b/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizerConditionSets.cs new file mode 100644 index 0000000..6c78cc7 --- /dev/null +++ b/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizerConditionSets.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.Tools +{ + public enum StatusIconPriorizerConditionSets + { + Overworld, + InDuty, + InForay + } +} diff --git a/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizerSettings.cs b/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizerSettings.cs new file mode 100644 index 0000000..1222e6c --- /dev/null +++ b/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizerSettings.cs @@ -0,0 +1,92 @@ +using Newtonsoft.Json; +using Pilz.Dalamud.ActivityContexts; +using Pilz.Dalamud.Nameplates.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Nameplates.Tools +{ + public class StatusIconPriorizerSettings + { + [JsonProperty("IconConditionSets")] + private Dictionary> iconConditionSets = new(); + public bool UsePriorizedIcons { get; set; } = true; + + [JsonConstructor] + private StatusIconPriorizerSettings(JsonConstructorAttribute dummy) + { + } + + public StatusIconPriorizerSettings() : this(false) + { + } + + public StatusIconPriorizerSettings(bool fillWithDefaultSettings) + { + foreach (StatusIconPriorizerConditionSets set in Enum.GetValues(typeof(StatusIconPriorizerConditionSets))) + iconConditionSets.Add(set, new List()); + + if (fillWithDefaultSettings) + FillWithDefaultSettings(); + } + + public List GetConditionSet(StatusIconPriorizerConditionSets set) + { + return iconConditionSets[set]; + } + + public void ResetToEmpty() + { + foreach (var kvp in iconConditionSets) + kvp.Value.Clear(); + } + + public void ResetToDefault() + { + ResetToEmpty(); + FillWithDefaultSettings(); + } + + private void FillWithDefaultSettings() + { + var setOverworld = GetConditionSet(StatusIconPriorizerConditionSets.Overworld); + setOverworld.AddRange(new[] + { + StatusIcons.Disconnecting, // Disconnecting + StatusIcons.InDuty, // In Duty + StatusIcons.ViewingCutscene, // Viewing Cutscene + StatusIcons.Busy, // Busy + StatusIcons.Idle, // Idle + StatusIcons.DutyFinder, // Duty Finder + StatusIcons.PartyLeader, // Party Leader + StatusIcons.PartyMember, // Party Member + StatusIcons.RolePlaying, // Role Playing + StatusIcons.GroupPose, // Group Pose + }); + + var setInDuty = GetConditionSet(StatusIconPriorizerConditionSets.InDuty); + setInDuty.AddRange(new[] + { + StatusIcons.Disconnecting, // Disconnecting + StatusIcons.ViewingCutscene, // Viewing Cutscene + StatusIcons.Idle, // Idle + StatusIcons.GroupPose, // Group Pose + }); + + var setInForay = GetConditionSet(StatusIconPriorizerConditionSets.InForay); + setInForay.AddRange(new[] + { + // This allows you to see which players don't have a party + StatusIcons.InDuty, // In Duty + + StatusIcons.Disconnecting, // Disconnecting + StatusIcons.ViewingCutscene, // Viewing Cutscene + StatusIcons.Idle, // Idle + StatusIcons.GroupPose, // Group Pose + }); + } + } +} diff --git a/Pilz.Dalamud/Pilz.Dalamud.csproj b/Pilz.Dalamud/Pilz.Dalamud.csproj new file mode 100644 index 0000000..540e7f5 --- /dev/null +++ b/Pilz.Dalamud/Pilz.Dalamud.csproj @@ -0,0 +1,63 @@ + + + + net6.0-windows + enable + annotations + true + latest + false + false + x64 + + + + true + true + + + + $(appdata)\XIVLauncher\addon\Hooks\dev\ + False + Pilzinsel64 + https://github.com/Pilzinsel64/Pilz.Dalamud + https://github.com/Pilzinsel64/Pilz.Dalamud + git + 0.1.1.0 + 0.1.1.0 + 0.1.1 + True + + + + + $(DalamudLibPath)FFXIVClientStructs.dll + false + + + $(DalamudLibPath)Newtonsoft.Json.dll + false + + + $(DalamudLibPath)Dalamud.dll + false + + + $(DalamudLibPath)ImGui.NET.dll + false + + + $(DalamudLibPath)ImGuiScene.dll + false + + + $(DalamudLibPath)Lumina.dll + false + + + $(DalamudLibPath)Lumina.Excel.dll + false + + + + diff --git a/Pilz.Dalamud/PluginServices.cs b/Pilz.Dalamud/PluginServices.cs new file mode 100644 index 0000000..37302ed --- /dev/null +++ b/Pilz.Dalamud/PluginServices.cs @@ -0,0 +1,28 @@ +using Dalamud.Data; +using Dalamud.Game.ClientState; +using Dalamud.Game.ClientState.Objects; +using Dalamud.Game.Gui; +using Dalamud.IoC; +using Dalamud.Plugin; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud +{ + public class PluginServices + { + [PluginService] public static GameGui GameGui { get; set; } = null; + [PluginService] public static DalamudPluginInterface PluginInterface { get; set; } = null; + [PluginService] public static ClientState ClientState { get; set; } = null; + [PluginService] public static DataManager DataManager { get; set; } = null; + [PluginService] public static ObjectTable ObjectTable { get; set; } = null; + + public static void Initialize(DalamudPluginInterface dalamudPluginInterface) + { + dalamudPluginInterface.Create(); + } + } +} diff --git a/Pilz.Dalamud/Tools/StatusIconFontConverter.cs b/Pilz.Dalamud/Tools/StatusIconFontConverter.cs new file mode 100644 index 0000000..d5ecff2 --- /dev/null +++ b/Pilz.Dalamud/Tools/StatusIconFontConverter.cs @@ -0,0 +1,41 @@ +using Dalamud.Game.Text.SeStringHandling; +using Pilz.Dalamud.Nameplates.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Tools +{ + public static class StatusIconFontConverter + { + public static StatusIcons? GetStatusIconFromBitmapFontIcon(BitmapFontIcon fontIcon) + { + return fontIcon switch + { + BitmapFontIcon.NewAdventurer => StatusIcons.NewAdventurer, + BitmapFontIcon.Mentor => StatusIcons.Mentor, + BitmapFontIcon.MentorPvE => StatusIcons.MentorPvE, + BitmapFontIcon.MentorCrafting => StatusIcons.MentorCrafting, + BitmapFontIcon.MentorPvP => StatusIcons.MentorPvP, + BitmapFontIcon.Returner => StatusIcons.Returner, + _ => null + }; + } + + public static BitmapFontIcon? GetBitmapFontIconFromStatusIcon(StatusIcons icon) + { + return icon switch + { + StatusIcons.NewAdventurer => BitmapFontIcon.NewAdventurer, + StatusIcons.Mentor => BitmapFontIcon.Mentor, + StatusIcons.MentorPvE => BitmapFontIcon.MentorPvE, + StatusIcons.MentorCrafting => BitmapFontIcon.MentorCrafting, + StatusIcons.MentorPvP => BitmapFontIcon.MentorPvP, + StatusIcons.Returner => BitmapFontIcon.Returner, + _ => null + }; + } + } +} diff --git a/Pilz.Dalamud/Tools/Strings/StringChange.cs b/Pilz.Dalamud/Tools/Strings/StringChange.cs new file mode 100644 index 0000000..f6a019e --- /dev/null +++ b/Pilz.Dalamud/Tools/Strings/StringChange.cs @@ -0,0 +1,24 @@ +using Dalamud.Game.Text.SeStringHandling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Tools.Strings +{ + public class StringChange + { + /// + /// The payloads to use for inserting/replacing. + /// + public List Payloads { get; init; } = new(); + + /// + /// Defines if only one anchor payload should be used, if using anchor payloads. + /// With this true the single anchor payload will be used in StringUpdateFactory instead of the anchor payload list. + /// Not needed to be true for the most cases. + /// + public bool ForceUsingSingleAnchorPayload { get; set; } = false; + } +} diff --git a/Pilz.Dalamud/Tools/Strings/StringChanges.cs b/Pilz.Dalamud/Tools/Strings/StringChanges.cs new file mode 100644 index 0000000..1ae85c0 --- /dev/null +++ b/Pilz.Dalamud/Tools/Strings/StringChanges.cs @@ -0,0 +1,40 @@ +using Dalamud.Game.Text.SeStringHandling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Tools.Strings +{ + public class StringChanges + { + private readonly Dictionary changes = new(); + + public StringChanges() + { + changes.Add(StringPosition.Before, new StringChange()); + changes.Add(StringPosition.After, new StringChange()); + changes.Add(StringPosition.Replace, new StringChange()); + } + + /// + /// Gets a change of the position of your choice where you can add your payloads. + /// + /// The position of your choice. + /// + public StringChange GetChange(StringPosition position) + { + return changes[position]; + } + + /// + /// Checks if there is any string change listed. + /// + /// + public bool Any() + { + return changes.Sum(n => n.Value.Payloads.Count) != 0; + } + } +} diff --git a/Pilz.Dalamud/Tools/Strings/StringChangesProps.cs b/Pilz.Dalamud/Tools/Strings/StringChangesProps.cs new file mode 100644 index 0000000..d0cd253 --- /dev/null +++ b/Pilz.Dalamud/Tools/Strings/StringChangesProps.cs @@ -0,0 +1,31 @@ +using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Game.Text.SeStringHandling; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Tools.Strings +{ + public class StringChangesProps + { + /// + /// The string where the changes should be applied. + /// + public SeString Destination { get; set; } + /// + /// The changes that should be applied to the destination. + /// + public StringChanges StringChanges { get; set; } = new(); + /// + /// Payloads to use as anchor where the changes should be applied to. + /// + public List AnchorPayloads { get; set; } = new(); + /// + /// A single payload to use as anchor where the changes should be applied to. + /// This property will only be used if StringChange.ForceSingleAnchorPayload is true. + /// + public Payload AnchorPayload { get; set; } + } +} diff --git a/Pilz.Dalamud/Tools/Strings/StringPosition.cs b/Pilz.Dalamud/Tools/Strings/StringPosition.cs new file mode 100644 index 0000000..46a05db --- /dev/null +++ b/Pilz.Dalamud/Tools/Strings/StringPosition.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Tools.Strings +{ + public enum StringPosition + { + Before, + After, + Replace + } +} diff --git a/Pilz.Dalamud/Tools/Strings/StringUpdateFactory.cs b/Pilz.Dalamud/Tools/Strings/StringUpdateFactory.cs new file mode 100644 index 0000000..ab3423a --- /dev/null +++ b/Pilz.Dalamud/Tools/Strings/StringUpdateFactory.cs @@ -0,0 +1,132 @@ +using Dalamud.Game.Text.SeStringHandling; +using Dalamud.Game.Text.SeStringHandling.Payloads; +using Lumina.Text; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Pilz.Dalamud.Tools.Strings +{ + public static class StringUpdateFactory + { + public static void ApplyStringChanges(StringChangesProps props) + { + if (props.StringChanges != null && props.StringChanges.Any()) + { + var seString = props.Destination; + List stringPositionsOrdered = GetOrderedStringPositions(props); + + foreach (var stringPosition in stringPositionsOrdered) + { + var stringChange = props.StringChanges.GetChange(stringPosition); + if (stringChange != null && stringChange.Payloads.Any()) + { + AddSpacesBetweenTextPayloads(stringChange.Payloads, stringPosition); + + if (stringPosition == StringPosition.Before) + { + Payload anchorFirst = stringChange.ForceUsingSingleAnchorPayload ? props.AnchorPayload : props.AnchorPayloads?.FirstOrDefault(); + + if (anchorFirst != null) + { + var anchorPayloadIndex = seString.Payloads.IndexOf(anchorFirst); + seString.Payloads.InsertRange(anchorPayloadIndex, stringChange.Payloads); + } + else + seString.Payloads.InsertRange(0, stringChange.Payloads); + } + else if (stringPosition == StringPosition.After) + { + Payload anchorLast = stringChange.ForceUsingSingleAnchorPayload ? props.AnchorPayload : props.AnchorPayloads?.LastOrDefault(); + + if (anchorLast != null) + { + var anchorPayloadIndex = seString.Payloads.IndexOf(anchorLast); + seString.Payloads.InsertRange(anchorPayloadIndex + 1, stringChange.Payloads); + } + else + seString.Payloads.AddRange(stringChange.Payloads); + } + else if (stringPosition == StringPosition.Replace) + { + Payload anchorReplace = props.AnchorPayload; + + if (anchorReplace != null) + { + var anchorPayloadIndex = seString.Payloads.IndexOf(anchorReplace); + seString.Payloads.InsertRange(anchorPayloadIndex, stringChange.Payloads); + seString.Remove(anchorReplace); + } + else + { + seString.Payloads.Clear(); + seString.Payloads.AddRange(stringChange.Payloads); + } + } + } + } + } + } + + private static void AddSpacesBetweenTextPayloads(List payloads, StringPosition tagPosition) + { + if (payloads != null && payloads.Any()) + { + var indicesToInsertSpacesAt = new List(); + var lastTextPayloadIndex = -1; + + static TextPayload getNewTextPayload() => new(" "); + + foreach (var payload in payloads.Reverse()) + { + if (payload is IconPayload iconPayload) + lastTextPayloadIndex = -1; + else if (payload is TextPayload textPayload) + { + if (lastTextPayloadIndex != -1) + indicesToInsertSpacesAt.Add(payloads.IndexOf(textPayload) + 1); + lastTextPayloadIndex = payloads.IndexOf(textPayload); + } + } + + foreach (var indexToInsertSpaceAt in indicesToInsertSpacesAt) + payloads.Insert(indexToInsertSpaceAt, getNewTextPayload()); + + // Decide whether to add a space to the end + if (tagPosition == StringPosition.Before) + { + var significantPayloads = payloads.Where(payload => payload is TextPayload || payload is IconPayload); + if (significantPayloads.Last() is TextPayload) + payloads.Add(getNewTextPayload()); + } + // Decide whether to add a space to the beginning + else if (tagPosition == StringPosition.After) + { + var significantPayloads = payloads.Where(payload => payload is TextPayload || payload is IconPayload); + if (significantPayloads.First() is TextPayload) + payloads.Insert(0, getNewTextPayload()); + } + } + } + + private static List GetOrderedStringPositions(StringChangesProps props) + { + var tagPositionsOrdered = new List(); + + // If there's no anchor payload, do replaces first so that befores and afters are based on the replaced data + if (props.AnchorPayloads == null || !props.AnchorPayloads.Any()) + tagPositionsOrdered.Add(StringPosition.Replace); + + tagPositionsOrdered.Add(StringPosition.Before); + tagPositionsOrdered.Add(StringPosition.After); + + // If there is an anchor payload, do replaces last so that we still know which payload needs to be removed + if (props.AnchorPayloads != null && props.AnchorPayloads.Any()) + tagPositionsOrdered.Add(StringPosition.Replace); + + return tagPositionsOrdered; + } + } +} diff --git a/Pilz.Dalamud/XivApi.cs b/Pilz.Dalamud/XivApi.cs new file mode 100644 index 0000000..5d2a35c --- /dev/null +++ b/Pilz.Dalamud/XivApi.cs @@ -0,0 +1,39 @@ +using FFXIVClientStructs.FFXIV.Client.System.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Pilz.Dalamud.Nameplates.Model; + +namespace Pilz.Dalamud +{ + public class XivApi + { + private static IntPtr _RaptureAtkModulePtr = IntPtr.Zero; + + public static IntPtr RaptureAtkModulePtr + { + get + { + if (_RaptureAtkModulePtr == IntPtr.Zero) + { + unsafe + { + var framework = Framework.Instance(); + var uiModule = framework->GetUiModule(); + + _RaptureAtkModulePtr = new IntPtr(uiModule->GetRaptureAtkModule()); + } + } + + return _RaptureAtkModulePtr; + } + } + + public static SafeAddonNameplate GetSafeAddonNamePlate() + { + return new(PluginServices.PluginInterface); + } + } +} diff --git a/Pilz.Dalamud/packages.lock.json b/Pilz.Dalamud/packages.lock.json new file mode 100644 index 0000000..8ee9f35 --- /dev/null +++ b/Pilz.Dalamud/packages.lock.json @@ -0,0 +1,6 @@ +{ + "version": 1, + "dependencies": { + "net6.0-windows7.0": {} + } +} \ No newline at end of file diff --git a/PlayerTags.sln b/PlayerTags.sln index d0f9aff..72c2a81 100644 --- a/PlayerTags.sln +++ b/PlayerTags.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 17.3.32929.385 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlayerTags", "PlayerTags\PlayerTags.csproj", "{13C812E9-0D42-4B95-8646-40EEBF30636F}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pilz.Dalamud", "Pilz.Dalamud\Pilz.Dalamud.csproj", "{D0362D71-E77F-4739-80BE-CD4454188B8F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -15,6 +17,10 @@ Global {13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|x64.Build.0 = Debug|x64 {13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.ActiveCfg = Release|x64 {13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.Build.0 = Release|x64 + {D0362D71-E77F-4739-80BE-CD4454188B8F}.Debug|x64.ActiveCfg = Debug|x64 + {D0362D71-E77F-4739-80BE-CD4454188B8F}.Debug|x64.Build.0 = Debug|x64 + {D0362D71-E77F-4739-80BE-CD4454188B8F}.Release|x64.ActiveCfg = Release|x64 + {D0362D71-E77F-4739-80BE-CD4454188B8F}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 90b7b1d..55a6599 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -26,7 +26,7 @@ - + $(DalamudLibPath)FFXIVClientStructs.dll false diff --git a/PlayerTags/packages.lock.json b/PlayerTags/packages.lock.json index fc36ed7..d25458d 100644 --- a/PlayerTags/packages.lock.json +++ b/PlayerTags/packages.lock.json @@ -14,11 +14,8 @@ "resolved": "2.1.8", "contentHash": "YqagNXs9InxmqkXzq7kLveImxnodkBEicAhydMXVp7dFjC7xb76U6zGgAax4/BWIWfZeWzr5DJyQSev31kj81A==" }, - "Pilz.Dalamud": { - "type": "Direct", - "requested": "[0.1.0, )", - "resolved": "0.1.0", - "contentHash": "n22WXrCzA+EAQHi4ve4PgTZYDzr0f0qsQ/1ApBBQjoCKJcwFox2rO692/2davRWiUQiNv9B56ikcnHocLp75tQ==" + "pilz.dalamud": { + "type": "Project" } } } From 1014fcc9f3b76464fe4f42f890176eb4f11331dc Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 13 Nov 2022 21:16:45 +0100 Subject: [PATCH 124/174] handle depricated properties for "IsIconVisibleInChat" and "IsIconVisibleInNameplate" --- PlayerTags/Data/Tag.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/PlayerTags/Data/Tag.cs b/PlayerTags/Data/Tag.cs index a168890..9774806 100644 --- a/PlayerTags/Data/Tag.cs +++ b/PlayerTags/Data/Tag.cs @@ -107,6 +107,18 @@ public Dictionary Inheritables public InheritableValue CustomId = new InheritableValue(Guid.Empty); + [JsonProperty, Obsolete] + private InheritableValue IsIconVisibleInChat + { + set => IsRoleIconVisibleInChat = value; + } + + [JsonProperty, Obsolete] + private InheritableValue IsIconVisibleInNameplate + { + set => IsRoleIconVisibleInNameplates = value; + } + [InheritableCategory("IconCategory")] public InheritableValue Icon = new InheritableValue(BitmapFontIcon.Aethernet); [InheritableCategory("IconCategory")] From 972f9e88196bb59fb2b26baadd9fa74ed2665b2e Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 13 Nov 2022 21:17:19 +0100 Subject: [PATCH 125/174] change version to v1.8.0.1 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 55a6599..dad6506 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.0.0 + 1.8.0.1 From 3849644e04164f9276ff0c209ff2b94446b683fa Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 15 Nov 2022 19:56:58 +0100 Subject: [PATCH 126/174] add dead player handling (backend) --- .../Configuration/PluginConfiguration.cs | 2 +- PlayerTags/Data/DeadPlayerHandling.cs | 15 +++++ .../Features/NameplateTagTargetFeature.cs | 63 +++++++++++++++++-- 3 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 PlayerTags/Data/DeadPlayerHandling.cs diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index 5340178..a0aabeb 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -284,7 +284,7 @@ public class GeneralOptionsClass public NameplateFreeCompanyVisibility NameplateFreeCompanyVisibility = NameplateFreeCompanyVisibility.Default; public NameplateTitleVisibility NameplateTitleVisibility = NameplateTitleVisibility.WhenHasTags; public NameplateTitlePosition NameplateTitlePosition = NameplateTitlePosition.AlwaysAboveName; - + public DeadPlayerHandling NameplateDeadPlayerHandling = DeadPlayerHandling.Include; public bool IsApplyTagsToAllChatMessagesEnabled = true; } } diff --git a/PlayerTags/Data/DeadPlayerHandling.cs b/PlayerTags/Data/DeadPlayerHandling.cs new file mode 100644 index 0000000..9fd6883 --- /dev/null +++ b/PlayerTags/Data/DeadPlayerHandling.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PlayerTags.Data +{ + public enum DeadPlayerHandling + { + Ignore, + Include, + GrayOut + } +} diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index c73205f..32f10dc 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -2,6 +2,9 @@ using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; +using FFXIVClientStructs.FFXIV.Client.Game.Character; +using FFXIVClientStructs.FFXIV.Client.System.Memory; +using FFXIVClientStructs.FFXIV.Component.GUI; using Lumina.Excel.GeneratedSheets; using Pilz.Dalamud.Icons; using Pilz.Dalamud.Nameplates.Tools; @@ -106,13 +109,37 @@ protected override bool IsTextVisible(Tag tag) return false; } - private void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs args) + private unsafe void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs args) { var beforeTitleBytes = args.Title.Encode(); var iconID = args.IconId; var generalOptions = m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType]; + var applyTags = false; + var grayOut = false; + + if (args.PlayerCharacter != null) + { + if (args.PlayerCharacter.IsDead) + { + switch (generalOptions.NameplateDeadPlayerHandling) + { + case DeadPlayerHandling.Include: + applyTags = true; + break; + case DeadPlayerHandling.GrayOut: + grayOut = true; + break; + } + } + else + applyTags = true; + } + + if (applyTags) + AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID); + else if(grayOut) + GrayOutNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID); - AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID); args.IconId = iconID; if (generalOptions.NameplateTitlePosition == NameplateTitlePosition.AlwaysAboveName) @@ -150,6 +177,17 @@ private void AddPayloadChanges(NameplateElement nameplateElement, TagPosition ta } } + private NameplateChanges GenerateEmptyNameplateChanges(SeString name, SeString title, SeString freeCompany) + { + NameplateChanges nameplateChanges = new(); + + nameplateChanges.GetProps(NameplateElements.Name).Destination = name; + nameplateChanges.GetProps(NameplateElements.Title).Destination = title; + nameplateChanges.GetProps(NameplateElements.FreeCompany).Destination = freeCompany; + + return nameplateChanges; + } + /// /// Adds tags to the nameplate of a game object. /// @@ -160,10 +198,7 @@ private void AddPayloadChanges(NameplateElement nameplateElement, TagPosition ta private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString title, SeString freeCompany, ref int statusIcon) { int? newStatusIcon = null; - NameplateChanges nameplateChanges = new(); - nameplateChanges.GetProps(NameplateElements.Name).Destination = name; - nameplateChanges.GetProps(NameplateElements.Title).Destination = title; - nameplateChanges.GetProps(NameplateElements.FreeCompany).Destination = freeCompany; + NameplateChanges nameplateChanges = GenerateEmptyNameplateChanges(name, title, freeCompany); if (gameObject is PlayerCharacter playerCharacter) { @@ -244,6 +279,22 @@ void applyTextFormatting(Tag tag) } } + protected void GrayOutNameplate(GameObject gameObject, SeString name, SeString title, SeString freeCompany, ref int statusIcon) + { + if (gameObject is PlayerCharacter playerCharacter) + { + NameplateChanges nameplateChanges = GenerateEmptyNameplateChanges(name, title, freeCompany); + + foreach (NameplateElements element in Enum.GetValues()) + { + nameplateChanges.GetChange(element, StringPosition.Before).Payloads.Add(new UIForegroundPayload(3)); + nameplateChanges.GetChange(element, StringPosition.After).Payloads.Add(new UIForegroundPayload(0)); + } + + ApplyNameplateChanges(nameplateChanges); + } + } + protected void ApplyNameplateChanges(NameplateChanges nameplateChanges) { var props = new NameplateChangesProps From 2fa6d6b94fd6545e0ce84fee43e91b92d2cbe5ef Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 15 Nov 2022 20:00:02 +0100 Subject: [PATCH 127/174] fix not using icon set from tag --- PlayerTags/Features/NameplateTagTargetFeature.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index 32f10dc..e2a185d 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -242,7 +242,7 @@ void checkTag(Tag tag) AddPayloadChanges(tag.TagTargetInNameplates.InheritedValue.Value, tag.TagPositionInNameplates.InheritedValue.Value, payloads, nameplateChanges, false); } if (newStatusIcon == null && classJob != null && (tag.IsJobIconVisibleInNameplates?.InheritedValue ?? false)) - newStatusIcon = jobIconSets.GetJobIcon(JobIconSetName.Framed, classJob.Id); + newStatusIcon = jobIconSets.GetJobIcon(tag.JobIconSet?.InheritedValue ?? JobIconSetName.Framed, classJob.Id); } } From 4764a354397cb7849361177d4f40cbcb774837a0 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 15 Nov 2022 20:01:27 +0100 Subject: [PATCH 128/174] fix status icon is visible if tag is not --- PlayerTags/Features/NameplateTagTargetFeature.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index e2a185d..2970a8c 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -241,7 +241,7 @@ void checkTag(Tag tag) if (payloads.Any()) AddPayloadChanges(tag.TagTargetInNameplates.InheritedValue.Value, tag.TagPositionInNameplates.InheritedValue.Value, payloads, nameplateChanges, false); } - if (newStatusIcon == null && classJob != null && (tag.IsJobIconVisibleInNameplates?.InheritedValue ?? false)) + if (IsTagVisible(tag, gameObject) && newStatusIcon == null && classJob != null && (tag.IsJobIconVisibleInNameplates?.InheritedValue ?? false)) newStatusIcon = jobIconSets.GetJobIcon(tag.JobIconSet?.InheritedValue ?? JobIconSetName.Framed, classJob.Id); } } From 649c75afff212d54dd473949aa9f0f9f6b15adff Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 15 Nov 2022 20:09:35 +0100 Subject: [PATCH 129/174] fix status icon priorizing doesn't work --- PlayerTags/Features/NameplateTagTargetFeature.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index 2970a8c..044d0ac 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -250,7 +250,8 @@ void checkTag(Tag tag) if (newStatusIcon != null) { var change = nameplateChanges.GetChange(NameplateElements.Name, StringPosition.Before); - NameplateUpdateFactory.ApplyStatusIconWithPrio(ref statusIcon, (int)newStatusIcon, change, ActivityContextManager.CurrentActivityContext, statusiconPriorizer); + if (NameplateUpdateFactory.ApplyStatusIconWithPrio(ref statusIcon, (int)newStatusIcon, change, ActivityContextManager.CurrentActivityContext, statusiconPriorizer)) + statusIcon = (int)newStatusIcon; } // Build the final strings out of the payloads From 5eaa7d147adb021016f584252365d1bb5eccf3ff Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 15 Nov 2022 20:20:02 +0100 Subject: [PATCH 130/174] add ui for dead player handling --- .../Configuration/PluginConfigurationUI.cs | 4 ++ PlayerTags/Resources/Strings.Designer.cs | 63 +++++++++++++++++++ PlayerTags/Resources/Strings.resx | 21 +++++++ 3 files changed, 88 insertions(+) diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index 7dfa20a..a0577e6 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -87,6 +87,7 @@ public void Draw() DrawComboBox(true, true, false, ref propertyProxy.NameplateFreeCompanyVisibility, () => SaveSettings(true)); DrawComboBox(true, true, false, ref propertyProxy.NameplateTitleVisibility, () => SaveSettings(true)); DrawComboBox(true, true, false, ref propertyProxy.NameplateTitlePosition, () => SaveSettings(true)); + DrawComboBox(true, true, false, ref propertyProxy.NameplateDeadPlayerHandling, () => SaveSettings(true)); ImGui.Spacing(); ImGui.Spacing(); @@ -1367,6 +1368,7 @@ private class PropertyProxy public NameplateFreeCompanyVisibility NameplateFreeCompanyVisibility; public NameplateTitleVisibility NameplateTitleVisibility; public NameplateTitlePosition NameplateTitlePosition; + public DeadPlayerHandling NameplateDeadPlayerHandling; public bool IsApplyTagsToAllChatMessagesEnabled; public PropertyProxy(PluginConfiguration config) @@ -1381,6 +1383,7 @@ public void LoadData() NameplateFreeCompanyVisibility = pluginConfig.GeneralOptions[currentActivityContext].NameplateFreeCompanyVisibility; NameplateTitleVisibility = pluginConfig.GeneralOptions[currentActivityContext].NameplateTitleVisibility; NameplateTitlePosition = pluginConfig.GeneralOptions[currentActivityContext].NameplateTitlePosition; + NameplateDeadPlayerHandling = pluginConfig.GeneralOptions[currentActivityContext].NameplateDeadPlayerHandling; IsApplyTagsToAllChatMessagesEnabled = pluginConfig.GeneralOptions[currentActivityContext].IsApplyTagsToAllChatMessagesEnabled; } @@ -1403,6 +1406,7 @@ void applyChanges(ActivityType key) pluginConfig.GeneralOptions[key].NameplateFreeCompanyVisibility = NameplateFreeCompanyVisibility; pluginConfig.GeneralOptions[key].NameplateTitleVisibility = NameplateTitleVisibility; pluginConfig.GeneralOptions[key].NameplateTitlePosition = NameplateTitlePosition; + pluginConfig.GeneralOptions[key].NameplateDeadPlayerHandling = NameplateDeadPlayerHandling; pluginConfig.GeneralOptions[key].IsApplyTagsToAllChatMessagesEnabled = IsApplyTagsToAllChatMessagesEnabled; } } diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index b2f08bf..9d24be5 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -204,6 +204,69 @@ public static string Loc_CustomTags { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Handling for dead players ähnelt. + /// + public static string Loc_DeadPlayerHandling { + get { + return ResourceManager.GetString("Loc_DeadPlayerHandling", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Gray out ähnelt. + /// + public static string Loc_DeadPlayerHandling_GrayOut { + get { + return ResourceManager.GetString("Loc_DeadPlayerHandling_GrayOut", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Gray out the nameplate of dead players and don't apply any tag for. ähnelt. + /// + public static string Loc_DeadPlayerHandling_GrayOut_Description { + get { + return ResourceManager.GetString("Loc_DeadPlayerHandling_GrayOut_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Ignore ähnelt. + /// + public static string Loc_DeadPlayerHandling_Ignore { + get { + return ResourceManager.GetString("Loc_DeadPlayerHandling_Ignore", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Don't process dead players and don't apply any tag for. ähnelt. + /// + public static string Loc_DeadPlayerHandling_Ignore_Description { + get { + return ResourceManager.GetString("Loc_DeadPlayerHandling_Ignore_Description", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Include ähnelt. + /// + public static string Loc_DeadPlayerHandling_Include { + get { + return ResourceManager.GetString("Loc_DeadPlayerHandling_Include", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Handle dead players as they are alive. No difference between dead and alive players. ähnelt. + /// + public static string Loc_DeadPlayerHandling_Include_Description { + get { + return ResourceManager.GetString("Loc_DeadPlayerHandling_Include_Description", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Template ähnelt. /// diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 6629cd8..5763f92 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -792,4 +792,25 @@ Use this if you want to to have every option under your control or just want to Shows the job tag with color and the role icon by replacing the title. + + Gray out + + + Ignore + + + Include + + + Handling for dead players + + + Gray out the nameplate of dead players and don't apply any tag for. + + + Don't process dead players and don't apply any tag for. + + + Handle dead players as they are alive. No difference between dead and alive players. + \ No newline at end of file From 6ec3a1a97077e305f5c95f79294f860366d15206 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 15 Nov 2022 20:22:47 +0100 Subject: [PATCH 131/174] version 1.8.0.2 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index dad6506..a07f0c2 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.0.1 + 1.8.0.2 From 8573555af79eb976a547b0cbba45c98d2860ac0f Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 15 Nov 2022 21:06:50 +0100 Subject: [PATCH 132/174] finally fix status icon priorizing & add new option --- .../Tools/NameplateUpdateFactory.cs | 22 +++++++++++-------- .../Tools/StatusIconPriorizerSettings.cs | 18 +++++++++++++++ .../Configuration/PluginConfiguration.cs | 1 + .../Configuration/PluginConfigurationUI.cs | 2 ++ .../Features/NameplateTagTargetFeature.cs | 7 +++--- PlayerTags/Resources/Strings.Designer.cs | 18 +++++++++++++++ PlayerTags/Resources/Strings.resx | 6 +++++ 7 files changed, 61 insertions(+), 13 deletions(-) diff --git a/Pilz.Dalamud/Nameplates/Tools/NameplateUpdateFactory.cs b/Pilz.Dalamud/Nameplates/Tools/NameplateUpdateFactory.cs index b04f947..ebc9518 100644 --- a/Pilz.Dalamud/Nameplates/Tools/NameplateUpdateFactory.cs +++ b/Pilz.Dalamud/Nameplates/Tools/NameplateUpdateFactory.cs @@ -23,26 +23,30 @@ public static void ApplyNameplateChanges(NameplateChangesProps props) } } - public static bool ApplyStatusIconWithPrio(ref int statusIcon, int newStatusIcon, StringChange stringChange, ActivityContext activityContext, StatusIconPriorizer priorizer) + public static bool ApplyStatusIconWithPrio(ref int statusIcon, int newStatusIcon, StringChange stringChange, ActivityContext activityContext, StatusIconPriorizer priorizer, bool moveIconToNameplateIfPossible) { - var isPrio = priorizer.IsPriorityIcon(statusIcon, activityContext); - - if (!isPrio) + bool? isPrio = null; + var fontIcon = StatusIconFontConverter.GetBitmapFontIconFromStatusIcon((StatusIcons)statusIcon); + + if (moveIconToNameplateIfPossible) { - var fontIcon = StatusIconFontConverter.GetBitmapFontIconFromStatusIcon((StatusIcons)statusIcon); - if (fontIcon != null) { // Set new font icon as string change var iconPayload = new IconPayload(fontIcon.Value); stringChange.Payloads.Insert(0, iconPayload); - // Use new status icon as status icon - statusIcon = newStatusIcon; + // If we moved it, we don't need it as icon anymore, yay :D + isPrio = false; } } - return isPrio; + isPrio ??= priorizer.IsPriorityIcon(statusIcon, activityContext); + + if (!isPrio.Value) + statusIcon = newStatusIcon; + + return isPrio.Value; } } } diff --git a/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizerSettings.cs b/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizerSettings.cs index 1222e6c..a5bfe34 100644 --- a/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizerSettings.cs +++ b/Pilz.Dalamud/Nameplates/Tools/StatusIconPriorizerSettings.cs @@ -65,6 +65,12 @@ private void FillWithDefaultSettings() StatusIcons.PartyMember, // Party Member StatusIcons.RolePlaying, // Role Playing StatusIcons.GroupPose, // Group Pose + StatusIcons.Mentor, + StatusIcons.MentorCrafting, + StatusIcons.MentorPvE, + StatusIcons.MentorPvP, + StatusIcons.Returner, + StatusIcons.NewAdventurer, }); var setInDuty = GetConditionSet(StatusIconPriorizerConditionSets.InDuty); @@ -74,6 +80,12 @@ private void FillWithDefaultSettings() StatusIcons.ViewingCutscene, // Viewing Cutscene StatusIcons.Idle, // Idle StatusIcons.GroupPose, // Group Pose + StatusIcons.Mentor, + StatusIcons.MentorCrafting, + StatusIcons.MentorPvE, + StatusIcons.MentorPvP, + StatusIcons.Returner, + StatusIcons.NewAdventurer, }); var setInForay = GetConditionSet(StatusIconPriorizerConditionSets.InForay); @@ -86,6 +98,12 @@ private void FillWithDefaultSettings() StatusIcons.ViewingCutscene, // Viewing Cutscene StatusIcons.Idle, // Idle StatusIcons.GroupPose, // Group Pose + StatusIcons.Mentor, + StatusIcons.MentorCrafting, + StatusIcons.MentorPvE, + StatusIcons.MentorPvP, + StatusIcons.Returner, + StatusIcons.NewAdventurer, }); } } diff --git a/PlayerTags/Configuration/PluginConfiguration.cs b/PlayerTags/Configuration/PluginConfiguration.cs index a0aabeb..e04432f 100644 --- a/PlayerTags/Configuration/PluginConfiguration.cs +++ b/PlayerTags/Configuration/PluginConfiguration.cs @@ -34,6 +34,7 @@ public class PluginConfiguration : IPluginConfiguration public DefaultPluginDataTemplate DefaultPluginDataTemplate = DefaultPluginDataTemplate.Simple; public StatusIconPriorizerSettings StatusIconPriorizerSettings = new(true); + public bool MoveStatusIconToNameplateTextIfPossible = true; public bool IsPlayerNameRandomlyGenerated = false; public bool IsCustomTagsContextMenuEnabled = true; public bool IsShowInheritedPropertiesEnabled = true; diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index a0577e6..cbc334e 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -266,6 +266,8 @@ public void Draw() SaveSettings(); }); + DrawCheckbox(nameof(PluginConfiguration.MoveStatusIconToNameplateTextIfPossible), true, ref m_PluginConfiguration.MoveStatusIconToNameplateTextIfPossible, () => SaveSettings()); + if (isPriorizerEnabled) { var statusIcons = Enum.GetValues(); diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index 044d0ac..09786f4 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -136,7 +136,7 @@ private unsafe void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs } if (applyTags) - AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID); + AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID, generalOptions); else if(grayOut) GrayOutNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID); @@ -195,7 +195,7 @@ private NameplateChanges GenerateEmptyNameplateChanges(SeString name, SeString t /// The name text to change. /// The title text to change. /// The free company text to change. - private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString title, SeString freeCompany, ref int statusIcon) + private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString title, SeString freeCompany, ref int statusIcon, GeneralOptionsClass generalOptions) { int? newStatusIcon = null; NameplateChanges nameplateChanges = GenerateEmptyNameplateChanges(name, title, freeCompany); @@ -250,8 +250,7 @@ void checkTag(Tag tag) if (newStatusIcon != null) { var change = nameplateChanges.GetChange(NameplateElements.Name, StringPosition.Before); - if (NameplateUpdateFactory.ApplyStatusIconWithPrio(ref statusIcon, (int)newStatusIcon, change, ActivityContextManager.CurrentActivityContext, statusiconPriorizer)) - statusIcon = (int)newStatusIcon; + NameplateUpdateFactory.ApplyStatusIconWithPrio(ref statusIcon, (int)newStatusIcon, change, ActivityContextManager.CurrentActivityContext, statusiconPriorizer, m_PluginConfiguration.MoveStatusIconToNameplateTextIfPossible); } // Build the final strings out of the payloads diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index 9d24be5..01912cb 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -1094,6 +1094,24 @@ public static string Loc_LandHandRole_Land { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Move Status Icon to Nameplate if possible ähnelt. + /// + public static string Loc_MoveStatusIconToNameplateTextIfPossible { + get { + return ResourceManager.GetString("Loc_MoveStatusIconToNameplateTextIfPossible", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die If the current status icon is available as Font Icon then move it to the Player Name text in the Nameplate, so there is place for another icon to use, e.g. the job icon. ähnelt. + /// + public static string Loc_MoveStatusIconToNameplateTextIfPossible_Description { + get { + return ResourceManager.GetString("Loc_MoveStatusIconToNameplateTextIfPossible_Description", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Nameplate properties ähnelt. /// diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 5763f92..2d9c1a8 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -813,4 +813,10 @@ Use this if you want to to have every option under your control or just want to Handle dead players as they are alive. No difference between dead and alive players. + + Move Status Icon to Nameplate if possible + + + If the current status icon is available as Font Icon then move it to the Player Name text in the Nameplate, so there is place for another icon to use, e.g. the job icon. + \ No newline at end of file From dc365bfcb5a3c1fd54c23abcb2f91ecf421e2277 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 15 Nov 2022 21:09:36 +0100 Subject: [PATCH 133/174] v1.8.0.3 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index a07f0c2..aef4a18 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.0.2 + 1.8.0.3 From 17fff4449bf20ee6ec8bdcb5e0fb51edeb1caebe Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 15 Nov 2022 21:09:42 +0100 Subject: [PATCH 134/174] fix naming --- PlayerTags/Resources/Strings.Designer.cs | 2 +- PlayerTags/Resources/Strings.resx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index 01912cb..94f850b 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -1095,7 +1095,7 @@ public static string Loc_LandHandRole_Land { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Move Status Icon to Nameplate if possible ähnelt. + /// Sucht eine lokalisierte Zeichenfolge, die Move Status Icon to Nameplate text if possible ähnelt. /// public static string Loc_MoveStatusIconToNameplateTextIfPossible { get { diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 2d9c1a8..6f9fd7b 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -814,7 +814,7 @@ Use this if you want to to have every option under your control or just want to Handle dead players as they are alive. No difference between dead and alive players. - Move Status Icon to Nameplate if possible + Move Status Icon to Nameplate text if possible If the current status icon is available as Font Icon then move it to the Player Name text in the Nameplate, so there is place for another icon to use, e.g. the job icon. From 14bb07f7abbd1ffcdec6fd75a36140941838623e Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 16 Nov 2022 07:30:21 +0100 Subject: [PATCH 135/174] use gray color at text formatting applying --- .../Features/NameplateTagTargetFeature.cs | 52 ++++--------------- PlayerTags/Features/TagTargetFeature.cs | 7 +-- PlayerTags/Resources/Strings.Designer.cs | 2 +- PlayerTags/Resources/Strings.resx | 2 +- 4 files changed, 16 insertions(+), 47 deletions(-) diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index 09786f4..7b02576 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -114,31 +114,8 @@ private unsafe void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs var beforeTitleBytes = args.Title.Encode(); var iconID = args.IconId; var generalOptions = m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType]; - var applyTags = false; - var grayOut = false; - if (args.PlayerCharacter != null) - { - if (args.PlayerCharacter.IsDead) - { - switch (generalOptions.NameplateDeadPlayerHandling) - { - case DeadPlayerHandling.Include: - applyTags = true; - break; - case DeadPlayerHandling.GrayOut: - grayOut = true; - break; - } - } - else - applyTags = true; - } - - if (applyTags) - AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID, generalOptions); - else if(grayOut) - GrayOutNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID); + AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID, generalOptions); args.IconId = iconID; @@ -200,7 +177,7 @@ private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString t int? newStatusIcon = null; NameplateChanges nameplateChanges = GenerateEmptyNameplateChanges(name, title, freeCompany); - if (gameObject is PlayerCharacter playerCharacter) + if (gameObject is PlayerCharacter playerCharacter && (!playerCharacter.IsDead || generalOptions.NameplateDeadPlayerHandling != DeadPlayerHandling.Ignore)) { var classJob = playerCharacter.ClassJob; var classJobGameData = classJob?.GameData; @@ -258,6 +235,12 @@ void checkTag(Tag tag) if (gameObject is PlayerCharacter playerCharacter1) { + ushort? colorOverwrite = null; + + // Use gray color if player is dead + if (playerCharacter1.IsDead && generalOptions.NameplateDeadPlayerHandling == DeadPlayerHandling.GrayOut) + colorOverwrite = 3; + // An additional step to apply text color to additional locations Identity identity = m_PluginData.GetIdentity(playerCharacter1); foreach (var customTagId in identity.CustomTagIds) @@ -274,27 +257,12 @@ void applyTextFormatting(Tag tag) { var destStrings = new[] { name, title, freeCompany }; var isTextColorApplied = new[] { tag.IsTextColorAppliedToNameplateName, tag.IsTextColorAppliedToNameplateTitle, tag.IsTextColorAppliedToNameplateFreeCompany }; - ApplyTextFormatting(gameObject, tag, new[] { name, title, freeCompany }, isTextColorApplied, null); + ApplyTextFormatting(gameObject, tag, new[] { name, title, freeCompany }, isTextColorApplied, null, + overwriteTextColor: colorOverwrite); } } } - protected void GrayOutNameplate(GameObject gameObject, SeString name, SeString title, SeString freeCompany, ref int statusIcon) - { - if (gameObject is PlayerCharacter playerCharacter) - { - NameplateChanges nameplateChanges = GenerateEmptyNameplateChanges(name, title, freeCompany); - - foreach (NameplateElements element in Enum.GetValues()) - { - nameplateChanges.GetChange(element, StringPosition.Before).Payloads.Add(new UIForegroundPayload(3)); - nameplateChanges.GetChange(element, StringPosition.After).Payloads.Add(new UIForegroundPayload(0)); - } - - ApplyNameplateChanges(nameplateChanges); - } - } - protected void ApplyNameplateChanges(NameplateChanges nameplateChanges) { var props = new NameplateChangesProps diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index 7773da5..a0e6c0b 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -223,7 +223,7 @@ protected void ApplyStringChanges(SeString seString, StringChanges stringChanges StringUpdateFactory.ApplyStringChanges(props); } - protected void ApplyTextFormatting(GameObject gameObject, Tag tag, SeString[] destStrings, InheritableValue[] textColorApplied, List preferedPayloads) + protected void ApplyTextFormatting(GameObject gameObject, Tag tag, SeString[] destStrings, InheritableValue[] textColorApplied, List preferedPayloads, ushort? overwriteTextColor = null) { if (IsTagVisible(tag, gameObject)) { @@ -239,11 +239,12 @@ protected void ApplyTextFormatting(GameObject gameObject, Tag tag, SeString[] de void applyTextColor(SeString destPayload, InheritableValue enableFlag, InheritableValue colorValue) { + var colorToUse = overwriteTextColor ?? colorValue?.InheritedValue; if (shouldApplyFormattingPayloads(destPayload) && enableFlag.InheritedValue != null && enableFlag.InheritedValue.Value - && colorValue.InheritedValue != null) - applyTextFormattingPayloads(destPayload, new UIForegroundPayload(colorValue.InheritedValue.Value), new UIForegroundPayload(0)); + && colorToUse != null) + applyTextFormattingPayloads(destPayload, new UIForegroundPayload(colorToUse.Value), new UIForegroundPayload(0)); } //void applyTextGlowColor(SeString destPayload, InheritableValue enableFlag, InheritableValue colorValue) diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index 94f850b..e0808c2 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -223,7 +223,7 @@ public static string Loc_DeadPlayerHandling_GrayOut { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Gray out the nameplate of dead players and don't apply any tag for. ähnelt. + /// Sucht eine lokalisierte Zeichenfolge, die Apply any tag but gray out the nameplate. ähnelt. /// public static string Loc_DeadPlayerHandling_GrayOut_Description { get { diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 6f9fd7b..43bbdae 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -805,7 +805,7 @@ Use this if you want to to have every option under your control or just want to Handling for dead players - Gray out the nameplate of dead players and don't apply any tag for. + Apply any tag but gray out the nameplate. Don't process dead players and don't apply any tag for. From 164f611516521cd5017f07c069793975439b5a2b Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 16 Nov 2022 07:30:21 +0100 Subject: [PATCH 136/174] use gray color at text formatting applying --- .../Features/NameplateTagTargetFeature.cs | 54 ++++--------------- PlayerTags/Features/TagTargetFeature.cs | 7 +-- PlayerTags/Resources/Strings.Designer.cs | 2 +- PlayerTags/Resources/Strings.resx | 2 +- 4 files changed, 17 insertions(+), 48 deletions(-) diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index 09786f4..c196c57 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -114,31 +114,8 @@ private unsafe void Nameplate_PlayerNameplateUpdated(PlayerNameplateUpdatedArgs var beforeTitleBytes = args.Title.Encode(); var iconID = args.IconId; var generalOptions = m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType]; - var applyTags = false; - var grayOut = false; - if (args.PlayerCharacter != null) - { - if (args.PlayerCharacter.IsDead) - { - switch (generalOptions.NameplateDeadPlayerHandling) - { - case DeadPlayerHandling.Include: - applyTags = true; - break; - case DeadPlayerHandling.GrayOut: - grayOut = true; - break; - } - } - else - applyTags = true; - } - - if (applyTags) - AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID, generalOptions); - else if(grayOut) - GrayOutNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID); + AddTagsToNameplate(args.PlayerCharacter, args.Name, args.Title, args.FreeCompany, ref iconID, generalOptions); args.IconId = iconID; @@ -200,7 +177,7 @@ private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString t int? newStatusIcon = null; NameplateChanges nameplateChanges = GenerateEmptyNameplateChanges(name, title, freeCompany); - if (gameObject is PlayerCharacter playerCharacter) + if (gameObject is PlayerCharacter playerCharacter && (!playerCharacter.IsDead || generalOptions.NameplateDeadPlayerHandling != DeadPlayerHandling.Ignore)) { var classJob = playerCharacter.ClassJob; var classJobGameData = classJob?.GameData; @@ -256,8 +233,14 @@ void checkTag(Tag tag) // Build the final strings out of the payloads ApplyNameplateChanges(nameplateChanges); - if (gameObject is PlayerCharacter playerCharacter1) + if (gameObject is PlayerCharacter playerCharacter1 && (!playerCharacter1.IsDead || generalOptions.NameplateDeadPlayerHandling != DeadPlayerHandling.Ignore)) { + ushort? colorOverwrite = null; + + // Use gray color if player is dead + if (playerCharacter1.IsDead && generalOptions.NameplateDeadPlayerHandling == DeadPlayerHandling.GrayOut) + colorOverwrite = 3; + // An additional step to apply text color to additional locations Identity identity = m_PluginData.GetIdentity(playerCharacter1); foreach (var customTagId in identity.CustomTagIds) @@ -274,27 +257,12 @@ void applyTextFormatting(Tag tag) { var destStrings = new[] { name, title, freeCompany }; var isTextColorApplied = new[] { tag.IsTextColorAppliedToNameplateName, tag.IsTextColorAppliedToNameplateTitle, tag.IsTextColorAppliedToNameplateFreeCompany }; - ApplyTextFormatting(gameObject, tag, new[] { name, title, freeCompany }, isTextColorApplied, null); + ApplyTextFormatting(gameObject, tag, new[] { name, title, freeCompany }, isTextColorApplied, null, + overwriteTextColor: colorOverwrite); } } } - protected void GrayOutNameplate(GameObject gameObject, SeString name, SeString title, SeString freeCompany, ref int statusIcon) - { - if (gameObject is PlayerCharacter playerCharacter) - { - NameplateChanges nameplateChanges = GenerateEmptyNameplateChanges(name, title, freeCompany); - - foreach (NameplateElements element in Enum.GetValues()) - { - nameplateChanges.GetChange(element, StringPosition.Before).Payloads.Add(new UIForegroundPayload(3)); - nameplateChanges.GetChange(element, StringPosition.After).Payloads.Add(new UIForegroundPayload(0)); - } - - ApplyNameplateChanges(nameplateChanges); - } - } - protected void ApplyNameplateChanges(NameplateChanges nameplateChanges) { var props = new NameplateChangesProps diff --git a/PlayerTags/Features/TagTargetFeature.cs b/PlayerTags/Features/TagTargetFeature.cs index 7773da5..a0e6c0b 100644 --- a/PlayerTags/Features/TagTargetFeature.cs +++ b/PlayerTags/Features/TagTargetFeature.cs @@ -223,7 +223,7 @@ protected void ApplyStringChanges(SeString seString, StringChanges stringChanges StringUpdateFactory.ApplyStringChanges(props); } - protected void ApplyTextFormatting(GameObject gameObject, Tag tag, SeString[] destStrings, InheritableValue[] textColorApplied, List preferedPayloads) + protected void ApplyTextFormatting(GameObject gameObject, Tag tag, SeString[] destStrings, InheritableValue[] textColorApplied, List preferedPayloads, ushort? overwriteTextColor = null) { if (IsTagVisible(tag, gameObject)) { @@ -239,11 +239,12 @@ protected void ApplyTextFormatting(GameObject gameObject, Tag tag, SeString[] de void applyTextColor(SeString destPayload, InheritableValue enableFlag, InheritableValue colorValue) { + var colorToUse = overwriteTextColor ?? colorValue?.InheritedValue; if (shouldApplyFormattingPayloads(destPayload) && enableFlag.InheritedValue != null && enableFlag.InheritedValue.Value - && colorValue.InheritedValue != null) - applyTextFormattingPayloads(destPayload, new UIForegroundPayload(colorValue.InheritedValue.Value), new UIForegroundPayload(0)); + && colorToUse != null) + applyTextFormattingPayloads(destPayload, new UIForegroundPayload(colorToUse.Value), new UIForegroundPayload(0)); } //void applyTextGlowColor(SeString destPayload, InheritableValue enableFlag, InheritableValue colorValue) diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index 94f850b..e0808c2 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -223,7 +223,7 @@ public static string Loc_DeadPlayerHandling_GrayOut { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Gray out the nameplate of dead players and don't apply any tag for. ähnelt. + /// Sucht eine lokalisierte Zeichenfolge, die Apply any tag but gray out the nameplate. ähnelt. /// public static string Loc_DeadPlayerHandling_GrayOut_Description { get { diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 6f9fd7b..43bbdae 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -805,7 +805,7 @@ Use this if you want to to have every option under your control or just want to Handling for dead players - Gray out the nameplate of dead players and don't apply any tag for. + Apply any tag but gray out the nameplate. Don't process dead players and don't apply any tag for. From cce0f957489377429675ecb0fae71f3f7c23105c Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 17 Nov 2022 19:35:38 +0100 Subject: [PATCH 137/174] v1.8.0.4 testing --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index aef4a18..7b4f443 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.0.3 + 1.8.0.4 From 103a826599bba16dca93ff6a6a15bd561ff876d7 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 17 Nov 2022 19:52:04 +0100 Subject: [PATCH 138/174] optimize dead player handling a bit --- .../Features/NameplateTagTargetFeature.cs | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/PlayerTags/Features/NameplateTagTargetFeature.cs b/PlayerTags/Features/NameplateTagTargetFeature.cs index c196c57..37f4d83 100644 --- a/PlayerTags/Features/NameplateTagTargetFeature.cs +++ b/PlayerTags/Features/NameplateTagTargetFeature.cs @@ -174,10 +174,11 @@ private NameplateChanges GenerateEmptyNameplateChanges(SeString name, SeString t /// The free company text to change. private void AddTagsToNameplate(GameObject gameObject, SeString name, SeString title, SeString freeCompany, ref int statusIcon, GeneralOptionsClass generalOptions) { + var playerCharacter = gameObject as PlayerCharacter; int? newStatusIcon = null; NameplateChanges nameplateChanges = GenerateEmptyNameplateChanges(name, title, freeCompany); - if (gameObject is PlayerCharacter playerCharacter && (!playerCharacter.IsDead || generalOptions.NameplateDeadPlayerHandling != DeadPlayerHandling.Ignore)) + if (playerCharacter != null && (!playerCharacter.IsDead || generalOptions.NameplateDeadPlayerHandling != DeadPlayerHandling.Ignore)) { var classJob = playerCharacter.ClassJob; var classJobGameData = classJob?.GameData; @@ -230,19 +231,17 @@ void checkTag(Tag tag) NameplateUpdateFactory.ApplyStatusIconWithPrio(ref statusIcon, (int)newStatusIcon, change, ActivityContextManager.CurrentActivityContext, statusiconPriorizer, m_PluginConfiguration.MoveStatusIconToNameplateTextIfPossible); } + // Gray out the nameplate + if (playerCharacter != null && playerCharacter.IsDead && generalOptions.NameplateDeadPlayerHandling == DeadPlayerHandling.GrayOut) + GrayOutNameplate(gameObject, nameplateChanges); + // Build the final strings out of the payloads ApplyNameplateChanges(nameplateChanges); - if (gameObject is PlayerCharacter playerCharacter1 && (!playerCharacter1.IsDead || generalOptions.NameplateDeadPlayerHandling != DeadPlayerHandling.Ignore)) + if (playerCharacter != null && (!playerCharacter.IsDead || generalOptions.NameplateDeadPlayerHandling == DeadPlayerHandling.Include)) { - ushort? colorOverwrite = null; - - // Use gray color if player is dead - if (playerCharacter1.IsDead && generalOptions.NameplateDeadPlayerHandling == DeadPlayerHandling.GrayOut) - colorOverwrite = 3; - // An additional step to apply text color to additional locations - Identity identity = m_PluginData.GetIdentity(playerCharacter1); + Identity identity = m_PluginData.GetIdentity(playerCharacter); foreach (var customTagId in identity.CustomTagIds) { var customTag = m_PluginData.CustomTags.FirstOrDefault(tag => tag.CustomId.Value == customTagId); @@ -250,15 +249,26 @@ void checkTag(Tag tag) applyTextFormatting(customTag); } - if (playerCharacter1.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter1.ClassJob.GameData.Abbreviation, out var jobTag)) + if (playerCharacter.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter.ClassJob.GameData.Abbreviation, out var jobTag)) applyTextFormatting(jobTag); void applyTextFormatting(Tag tag) { var destStrings = new[] { name, title, freeCompany }; var isTextColorApplied = new[] { tag.IsTextColorAppliedToNameplateName, tag.IsTextColorAppliedToNameplateTitle, tag.IsTextColorAppliedToNameplateFreeCompany }; - ApplyTextFormatting(gameObject, tag, new[] { name, title, freeCompany }, isTextColorApplied, null, - overwriteTextColor: colorOverwrite); + ApplyTextFormatting(gameObject, tag, new[] { name, title, freeCompany }, isTextColorApplied, null); + } + } + } + + private void GrayOutNameplate(GameObject gameObject, NameplateChanges nameplateChanges) + { + if (gameObject is PlayerCharacter playerCharacter) + { + foreach (NameplateElements element in Enum.GetValues()) + { + nameplateChanges.GetChange(element, StringPosition.Before).Payloads.Add(new UIForegroundPayload(3)); + nameplateChanges.GetChange(element, StringPosition.After).Payloads.Add(new UIForegroundPayload(0)); } } } From cfbe84d28fe26dcd3a36791b73b9677b50a05e4b Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 17 Nov 2022 19:53:02 +0100 Subject: [PATCH 139/174] v1.8.0.5 Testing --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 7b4f443..e32c71f 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.0.4 + 1.8.0.5 From dcecc832eea2957813adf4680eda4404addfeaa3 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Thu, 17 Nov 2022 20:06:38 +0100 Subject: [PATCH 140/174] update translation files --- PlayerTags/Resources/Strings.de.resx | 9 -------- PlayerTags/Resources/Strings.es-ES.resx | 30 ------------------------- PlayerTags/Resources/Strings.fr.resx | 30 ------------------------- 3 files changed, 69 deletions(-) diff --git a/PlayerTags/Resources/Strings.de.resx b/PlayerTags/Resources/Strings.de.resx index 96de658..fbf466b 100644 --- a/PlayerTags/Resources/Strings.de.resx +++ b/PlayerTags/Resources/Strings.de.resx @@ -354,15 +354,6 @@ Zeige im Chat - - Bestimmt, ob das Symbol im Chat dargestellt wird. - - - Zeige in der Namensanzeige - - - Bestimmt, ob das Symbol in der Namensanzeige dargestellt wird. - Text diff --git a/PlayerTags/Resources/Strings.es-ES.resx b/PlayerTags/Resources/Strings.es-ES.resx index 35cfbd2..b2c166b 100644 --- a/PlayerTags/Resources/Strings.es-ES.resx +++ b/PlayerTags/Resources/Strings.es-ES.resx @@ -354,15 +354,6 @@ Mostrar en el chat - - Si el icono se mostrará o no dentro del chat. - - - Mostrar en placas de nombre - - - Si el icono se mostrará o no en las placas de nombre. - Texto @@ -621,25 +612,4 @@ Otros (Experimental) - - Insert behind group number prefix in chat - - - If enabled, the Tag and Icon will get insert behind the Group/Alliance number prefix in Chat instead of before. - - - Nameplate properties - - - Defines whenever the free company element of the nameplate should be visible or not. - - - Defines the position for the title element of the nameplate. Should it be above or below the name? You can decide! - - - Defines whenever the title element of the nameplate should be visible or not. - - - Chat - \ No newline at end of file diff --git a/PlayerTags/Resources/Strings.fr.resx b/PlayerTags/Resources/Strings.fr.resx index a894726..12643c9 100644 --- a/PlayerTags/Resources/Strings.fr.resx +++ b/PlayerTags/Resources/Strings.fr.resx @@ -354,15 +354,6 @@ Afficher dans le chat - - Si l'icône doit être affichée dans le chat. - - - Afficher dans les plaques de noms - - - Si l'icône doit être affichée dans les plaques de noms. - Texte @@ -621,25 +612,4 @@ Autre (expérimental) - - Insert behind group number prefix in chat - - - If enabled, the Tag and Icon will get insert behind the Group/Alliance number prefix in Chat instead of before. - - - Nameplate properties - - - Defines whenever the free company element of the nameplate should be visible or not. - - - Defines the position for the title element of the nameplate. Should it be above or below the name? You can decide! - - - Defines whenever the title element of the nameplate should be visible or not. - - - Chat - \ No newline at end of file From 8f74555201b33a905bcb215c7afc4f5f838a3692 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 20 Nov 2022 11:41:34 +0100 Subject: [PATCH 141/174] change version to v1.8.0.6 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index e32c71f..6311c54 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.0.5 + 1.8.0.6 From 399766a8fe3884562cd860de8d52587ef4a8e68f Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 21 Nov 2022 06:13:26 +0100 Subject: [PATCH 142/174] fix conifg backward-compatibility due private fields --- PlayerTags/Data/Tag.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Data/Tag.cs b/PlayerTags/Data/Tag.cs index 9774806..a688346 100644 --- a/PlayerTags/Data/Tag.cs +++ b/PlayerTags/Data/Tag.cs @@ -77,7 +77,7 @@ public Dictionary Inheritables { m_Inheritables = new Dictionary(); - var inheritableFields = GetType().GetFields().Where(field => typeof(IInheritable).IsAssignableFrom(field.FieldType)); + var inheritableFields = GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).Where(field => typeof(IInheritable).IsAssignableFrom(field.FieldType)); foreach (var inheritableField in inheritableFields) { IInheritable? inheritable = inheritableField.GetValue(this) as IInheritable; From ecde52a94eb702a9105e9b69d040553eeb90b80b Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 21 Nov 2022 06:13:31 +0100 Subject: [PATCH 143/174] v1.8.0.7 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 6311c54..9892346 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.0.6 + 1.8.0.7 From 8e28a60d4b994f7d87a873476f62e563f9679d8f Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 21 Nov 2022 06:27:23 +0100 Subject: [PATCH 144/174] finally fix config backward-compatibility --- PlayerTags/Data/Tag.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/PlayerTags/Data/Tag.cs b/PlayerTags/Data/Tag.cs index a688346..d802e8d 100644 --- a/PlayerTags/Data/Tag.cs +++ b/PlayerTags/Data/Tag.cs @@ -77,7 +77,7 @@ public Dictionary Inheritables { m_Inheritables = new Dictionary(); - var inheritableFields = GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).Where(field => typeof(IInheritable).IsAssignableFrom(field.FieldType)); + var inheritableFields = GetType().GetFields().Where(field => typeof(IInheritable).IsAssignableFrom(field.FieldType)); foreach (var inheritableField in inheritableFields) { IInheritable? inheritable = inheritableField.GetValue(this) as IInheritable; @@ -281,11 +281,25 @@ private static bool EqualsInheritableDataListXivChatType(InheritableData return true; } + private static readonly Dictionary ObsulteInheritableStringMap = new() + { + { "IsIconVisibleInChat", nameof(IsRoleIconVisibleInChat) }, + { "IsIconVisibleInNameplate", nameof(IsRoleIconVisibleInNameplates) } + }; + private static string FixObsuleteInheritableStringName(string name) + { + if (ObsulteInheritableStringMap.ContainsKey(name)) + return ObsulteInheritableStringMap[name]; + else + return name; + } + public void SetChanges(IEnumerable> changes) { foreach ((var name, var inheritableData) in changes) { - Inheritables[name].SetData(inheritableData); + var namefixed = FixObsuleteInheritableStringName(name); + Inheritables[namefixed].SetData(inheritableData); } } From 6a7e336c1a5b63ce9a6b071bd53fd66fd8dc344e Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 21 Nov 2022 06:27:37 +0100 Subject: [PATCH 145/174] v1.8.0.8 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 9892346..0dc86d1 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.0.7 + 1.8.0.8 From 1a8fbf5c5edde2dc20b48a6c0ffb0873ce1758e5 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 21 Nov 2022 13:25:07 +0100 Subject: [PATCH 146/174] IsIconVisibleInNameplates old config fix - no clue why --- PlayerTags/Data/Tag.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PlayerTags/Data/Tag.cs b/PlayerTags/Data/Tag.cs index d802e8d..1ff6dfa 100644 --- a/PlayerTags/Data/Tag.cs +++ b/PlayerTags/Data/Tag.cs @@ -284,7 +284,8 @@ private static bool EqualsInheritableDataListXivChatType(InheritableData private static readonly Dictionary ObsulteInheritableStringMap = new() { { "IsIconVisibleInChat", nameof(IsRoleIconVisibleInChat) }, - { "IsIconVisibleInNameplate", nameof(IsRoleIconVisibleInNameplates) } + { "IsIconVisibleInNameplate", nameof(IsRoleIconVisibleInNameplates) }, + { "IsIconVisibleInNameplates", nameof(IsRoleIconVisibleInNameplates) } }; private static string FixObsuleteInheritableStringName(string name) { From 48973ae70184cc47b65acf00c909b5ee6ba3a9b7 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 21 Nov 2022 13:25:41 +0100 Subject: [PATCH 147/174] v1.8.0.9 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 0dc86d1..1d49e4f 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.0.8 + 1.8.0.9 From d5248e001ae7dc00792530766d1633daadc4c504 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Tue, 22 Nov 2022 16:45:28 +0100 Subject: [PATCH 148/174] fix ignoring Target Chat Type --- PlayerTags/Features/ChatTagTargetFeature.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index 57d9da8..d05f689 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -340,12 +340,15 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender { StringChanges stringChanges = new(); + bool isTagEnabled(Tag tag) + => tag.TagPositionInChat.InheritedValue != null && tag.TargetChatTypes.InheritedValue != null && tag.TargetChatTypes.InheritedValue.Contains(chatType); + if (stringMatch.GameObject is PlayerCharacter playerCharacter) { // Add the job tag if (playerCharacter.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter.ClassJob.GameData.Abbreviation, out var jobTag)) { - if (jobTag.TagPositionInChat.InheritedValue != null && jobTag.TargetChatTypes.InheritedValue != null && jobTag.TargetChatTypes.Value.Contains(chatType)) + if (isTagEnabled(jobTag)) { var payloads = GetPayloads(jobTag, stringMatch.GameObject); if (payloads.Any()) @@ -380,7 +383,7 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender var customTag = m_PluginData.CustomTags.FirstOrDefault(tag => tag.CustomId.Value == customTagId); if (customTag != null) { - if (customTag.TagPositionInChat.InheritedValue != null) + if (isTagEnabled(customTag)) { var customTagPayloads = GetPayloads(customTag, stringMatch.GameObject); if (customTagPayloads.Any()) @@ -407,14 +410,14 @@ void addPayloadChanges(Tag tag, IEnumerable payloads) if (stringMatch.GameObject is PlayerCharacter playerCharacter1) { - if (playerCharacter1.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter1.ClassJob.GameData.Abbreviation, out var jobTag)) + if (playerCharacter1.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter1.ClassJob.GameData.Abbreviation, out var jobTag) & isTagEnabled(jobTag)) applyTextFormatting(jobTag); } foreach (var customTagId in identity.CustomTagIds) { var customTag = m_PluginData.CustomTags.FirstOrDefault(tag => tag.CustomId.Value == customTagId); - if (customTag != null) + if (customTag != null && isTagEnabled(customTag)) applyTextFormatting(customTag); } From 4cebded59e09001dee76f57cf0bf3718a92817c5 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 23 Nov 2022 10:05:39 +0100 Subject: [PATCH 149/174] v1.8.1 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 1d49e4f..d41259e 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.0.9 + 1.8.1.0 From 2b61a57424b232996cfeaea81c6adebdd53a45f0 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 23 Nov 2022 10:49:33 +0100 Subject: [PATCH 150/174] update translation files --- PlayerTags/Resources/Strings.Designer.cs | 9 + PlayerTags/Resources/Strings.de.resx | 189 ++++++++++++++++++++ PlayerTags/Resources/Strings.es-ES.resx | 210 +++++++++++++++++++++++ PlayerTags/Resources/Strings.fr.resx | 30 ++++ PlayerTags/Resources/Strings.resx | 3 + 5 files changed, 441 insertions(+) diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index e0808c2..1f52b65 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -707,6 +707,15 @@ public static string Loc_IsPlayersTabSelfVisible_Description { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Show role icon in Chat ähnelt. + /// + public static string Loc_IsRoleIconVisibleInChat { + get { + return ResourceManager.GetString("Loc_IsRoleIconVisibleInChat", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Whether the role icon will be shown in chat. ähnelt. /// diff --git a/PlayerTags/Resources/Strings.de.resx b/PlayerTags/Resources/Strings.de.resx index fbf466b..c5fa5fa 100644 --- a/PlayerTags/Resources/Strings.de.resx +++ b/PlayerTags/Resources/Strings.de.resx @@ -354,6 +354,15 @@ Zeige im Chat + + Bestimmt, ob das Rollensymbol im angezeigt Chat wird. + + + Rollensymbol in Namensschildern anzeigen + + + Bestimmt, ob das Rollensymbol in Namensanzeigen angezeigt wird. + Text @@ -633,4 +642,184 @@ Chat + + Rollensymbol in Namensschildern anzeigen + + + Job-Symbol in Namenschildern anzeigen + + + Bestimmt, ob das Job-Symbol in Namensanzeigen angezeigt wird. + + + Job-Symbolsatz + + + Das Symbolset, welches für das Anzeigen von Job-Symbolen genutzt wird. Du kannst das Rollensymbol-Set auswählen, um Rollensymbole anzuzeigen. + + + Erweiterte Chateinstellungen + + + Zutreffende Chattypen + + + Definiert, für welche Chattypen die Chatfunktionen von diesem Tag greifen sollen. + + + Statusicon-Priorität + + + In einem Inhalt + + + Statusicons, welche in Inhalten priorisiert werden sollen. + + + In einem Foray + + + Statusicons, welche in Forays priorisiert werden sollen. + + + Oberwelt + + + Statusicons, welche auf der Oberwelt priorisiert werden sollen. + + + Auf Standard zurücksetzen + + + Setzt alle Bedingungssets auf die Standardeinstellungen zurück + + + Auf leer zurücksetzen + + + Löscht alle Bedingungssets zu einer leeren Sammlung. Keine Statussymbole werden priorisiert. + + + Priorisierte Symbole verwenden + + + Wenn diese Option aktiviert ist, wird eine Reihe von eingestellten Statussymbolen gegenüber von Jobsymbolen priorisiert. +Wenn deaktiviert, wird nur das "Nicht-Verbunden"-Statussymbol priorisiert. + + + Beschäftigt + + + Verbindungsprobleme + + + Inhaltssuche + + + Gruppenfotomodus + + + Inaktiv + + + In einem Inhalt + + + Mentor + + + Handwerksmentor + + + Kampfmentor + + + PvP-Mentor + + + Neuling + + + Gruppenanführer + + + In Gruppe + + + Wiederkehrer + + + Rollenspiel + + + Schaut Zwischensequenz + + + Vorlage + + + Grundlegend + + + Wie leer, aber enthält eine sehr grundlegende Vorkonfiguration für Formatierung und Färbung. +Kann auch verwendet werden, wenn Du deine eigene Konfiguration erstellen möchtest, aber grundlegende Formatierungen haben möchtest. + + + Hier kannst Du die Vorlage für alle Einstellungen unten auswählen. +Die Vorlage wird als Grundlage für Eigenschaften verwendet. Jede Änderung, die Sie vornehmen, wird gespeichert. Allerdings werden keine Optionen, die dieser Vorlage entsprechen, gespeichert. +Dies hilft Ihnen, wenn Du nicht so viele Eigenschaften überschreiben müssen - oder Deine komplett eigene Konfiguration ohne Vorlage erstellen möchten. + +Warnung: +Wenn Du dies ändern, könnten Eigenschaften zurückgesetzt werden. Du könntest einen Teil Deiner Konfiguration verlieren. +Nachdem Du dies geändert hast, stelle sicher, dass alles so eingerichtet ist, wie Du es magst. + + + Vollständig + + + Zeige den Job-Tag mit Farbe und färbe auch das Spielernamen-Element. + + + Leer + + + Keine einzelne Vorkonfiguration. Dies ist eine komplett leere Vorlage. +Benutze dies, wenn du jede Option unter deiner Kontrolle haben möchtest oder nur ein paar Konfigurationen machen möchtest. + + + Einfach + + + Zeigt den Job-Tag mit Farbe und dem Rollensymbol durch Ersetzen des Titels. + + + Ausgrauen + + + Ignorieren + + + Einbeziehen + + + Handhabung für tote Spieler + + + Wende jeden Tag an, aber graue das Namensschild aus. + + + Verarbeite keine toten Spieler und wende keinen Tag an. + + + Behandle tote Spieler, als wären sie am Leben und mache keinen Unterschied zwischen toten und lebendigen Spielern. + + + Statussymbol nach Möglichkeit zum Namensschild-Text verschieben + + + Wenn das aktuelle Statussymbol als Schriftsymbol verfügbar ist, verschiebe es in den Text des Spielernamen auf dem Namensschild, sodass es Platz gibt, um es mit einem anderen Symbol zu ersetzen, z.B. das Job-Symbol. + + + Rollensymbol im Chat anzeigen + \ No newline at end of file diff --git a/PlayerTags/Resources/Strings.es-ES.resx b/PlayerTags/Resources/Strings.es-ES.resx index b2c166b..aa1015d 100644 --- a/PlayerTags/Resources/Strings.es-ES.resx +++ b/PlayerTags/Resources/Strings.es-ES.resx @@ -354,6 +354,15 @@ Mostrar en el chat + + Si el icono de rol se mostrará o no en el chat. + + + Mostrar icono de rol en placas de nombres + + + Si el icono de rol se mostrará o no en las placas de nombre. + Texto @@ -612,4 +621,205 @@ Otros (Experimental) + + Insertar detrás del prefijo de número de grupo en el chat + + + Si se habilita, la etiqueta y el icono se insertarán detrás del prefijo de número del grupo/alianza en el chat, en lugar de delante. + + + Propiedades de placas de nombres + + + Define si el elemento de Free Company de la placa de nombre debería ser visible o no. + + + Define la posición del elemento de título de la placa de nombre. ¿Debería estar encima o debajo del nombre del jugador? ¡Tú decides! + + + Define si el elemento de título de la placa de nombre debería ser visible o no. + + + Chat + + + Mostrar icono de rol en placa de nombre + + + Mostrar icono de job en placas de nombres + + + Define si el icono de job se mostrará en las placas de nombre o no. + + + Conjunto de iconos de jobs + + + El conjunto de iconos a usar para mostrar el icono de job. Tambien puedes elegir que el conjunto de iconos de roles muestre los iconos de roles en su lugar. + + + Opciones Avanzadas de Chat + + + Tipos de Objetivos de Chat + + + Define para qué tipo de chat se deberían usar las características de esta etiqueta. + + + Priorizador de Icono de Estado + + + En Duty + + + Iconos de estado que deberían tener prioridad dentro de duties. + + + En Foray + + + Iconos de estado que deberían tener prioridad en las forays. + + + Mundo Abierto + + + Iconos de estado que deberían tener prioridad cuando estés en el mundo abierto (fuera de cualquier duty). + + + Restablecer por defecto + + + Restablece todas las condiciones a los ajustes por defecto + + + Restablecer a vacío + + + Limpia todas las condiciones a una colección vacía. Ningún icono de estado será priorizado. + + + Usar iconos priorizados + + + Con esta opción marcada obligará a priorizar un conjunto de iconos de estado sobre los iconos de job, si habilitas los iconos de jobs. +Cuando se desactiva, sólo se prioriza el icono de estado desconectado. + + + Ocupado + + + Desconectándose + + + Duty Finder + + + Group Pose + + + Inactivo + + + En Duty + + + Mentor + + + Mentor de Crafting + + + Mentor de PvE + + + Mentor de PvP + + + Nuevo Aventurero + + + Líder del Grupo + + + Miembro del Grupo + + + Jugador Returner + + + Roleando + + + Viendo Escena de Vídeo + + + Plantilla + + + Básico + + + Igual que Vacío, pero incluye una pre-configuración muy básica para el formato y colores. +También se puede utilizar si quieres hacer tu propia cofiguración pero quieres un formato básico. + + + Aquí puede elegir la plantilla para todos los ajustes a continuación. +La plantilla se utiliza como conjunto básico de propiedades. Cada cambio que estás haciendo es lo que se guarda. Pero no se guardarán todas las opciones de esta plantilla. +Esto te ayuda al no necesitar sobrescribir tantas propiedades - o al crear una configuración completamente nueva sin una plantilla. + +Advertencia: +Cambiar esto puede causar que las propiedades sean restablecidas. Puedes perder una parte de tu configuración. +Después de cambiar esto, asegútate de que todo está configurado a tu gusto. + + + Completo + + + Mostrar la etiqueta del job con el color y también colorear el nombre del jugador. + + + Vacío + + + No se ha hecho una sola configuración. Esta es una plantilla completamente vacía. +Usa esto si quieres tener todas las opciones bajo tu control o solo quieres hacer unas pocas configuraciones. + + + Simple + + + Muestra la etiqueta de job con el color y el icono del rol reemplazando el título. + + + Poner en Gris + + + Ignorar + + + Incluir + + + Ajustes para jugadores muertos + + + Aplicar cualquier etiqueta pero poner gris la placa de nombre. + + + No procesar jugadores muertos y no aplicarles ninguna etiqueta. + + + Ajusta los jugadores muertos como si estuvieran vivos. No habrá diferencia entre los jugadores muertos y los vivos. + + + Mover el icono de estado a la placa de nombre si fuera posible + + + Si el icono de estado actual está disponible como icono de fuente, se moverá al Nombre del Jugador en la placa de nombre, para que haya sitio para otro icono (por ejemplo, el icono de job). + + + Mostrar icono de rol en placas de chat + \ No newline at end of file diff --git a/PlayerTags/Resources/Strings.fr.resx b/PlayerTags/Resources/Strings.fr.resx index 12643c9..5574d81 100644 --- a/PlayerTags/Resources/Strings.fr.resx +++ b/PlayerTags/Resources/Strings.fr.resx @@ -612,4 +612,34 @@ Autre (expérimental) + + Les griser + + + Les ignorer + + + Les inclure + + + Traitement des personnages décédés + + + Appliquer tous les tags, mais griser leur plaque de nom. + + + Les personnages décédés ne seront pas traités et tous les tags les concernant seront ignorés. + + + Les personnages décédés seront gérés comme s'ils étaient vivants. Aucune différenciation ne sera appliquée entre les personnages vivants et décédés. + + + Déplacer l'Icône de Statut dans le texte de la Plaque de nom si possible + + + Si l'icône de statut actuel existe en tant qu'icône textuelle, alors la déplacer dans le texte à côté du Nom du Personnage dans sa Plaque de nom, afin de laisser place à un autre icône, tel que l'icône de Job, par exemple. + + + Afficher l'icône de rôle dans le Chat + \ No newline at end of file diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 43bbdae..1d335d0 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -819,4 +819,7 @@ Use this if you want to to have every option under your control or just want to If the current status icon is available as Font Icon then move it to the Player Name text in the Nameplate, so there is place for another icon to use, e.g. the job icon. + + Show role icon in Chat + \ No newline at end of file From dfda152a94f10e288f8fad91c90cb98822110454 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 23 Nov 2022 12:18:34 +0100 Subject: [PATCH 151/174] fix typos --- PlayerTags/Resources/Strings.Designer.cs | 6 +++--- PlayerTags/Resources/Strings.resx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index 1f52b65..91d2069 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -298,11 +298,11 @@ public static string Loc_DefaultPluginDataTemplate_Basic_Description { /// /// Sucht eine lokalisierte Zeichenfolge, die Here you can choose the template for all the settings below. ///The template is used as basic set of properties. Every change you are making is what get saved. But all options from this template will not be saved. - ///This helpes you by not needing to overwrite so much properties - or by doing your completely own configuration without a template. + ///This helps you by not needing to overwrite so much properties - or by doing your completely own configuration without a template. /// ///Warning: ///Changing this can cause properties to be resetted. You may loose a part of your configuration. - ///After you changed this, ensure everything is setted up how [Rest der Zeichenfolge wurde abgeschnitten]"; ähnelt. + ///After you changed this, ensure everything is setted up how y [Rest der Zeichenfolge wurde abgeschnitten]"; ähnelt. /// public static string Loc_DefaultPluginDataTemplate_Description { get { @@ -338,7 +338,7 @@ public static string Loc_DefaultPluginDataTemplate_None { } /// - /// Sucht eine lokalisierte Zeichenfolge, die No single configuration made. This is an completley empty template. + /// Sucht eine lokalisierte Zeichenfolge, die No single configuration made. This is a completely empty template. ///Use this if you want to to have every option under your control or just want to make only a few configurations. ähnelt. /// public static string Loc_DefaultPluginDataTemplate_None_Description { diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 1d335d0..2ddb778 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -767,7 +767,7 @@ Can also be used if you want to make your own cofiguration but want basic format Here you can choose the template for all the settings below. The template is used as basic set of properties. Every change you are making is what get saved. But all options from this template will not be saved. -This helpes you by not needing to overwrite so much properties - or by doing your completely own configuration without a template. +This helps you by not needing to overwrite so much properties - or by doing your completely own configuration without a template. Warning: Changing this can cause properties to be resetted. You may loose a part of your configuration. @@ -783,7 +783,7 @@ After you changed this, ensure everything is setted up how you like it. Empty - No single configuration made. This is an completley empty template. + No single configuration made. This is a completely empty template. Use this if you want to to have every option under your control or just want to make only a few configurations. From 65d5dad4f0e00830d27f812ce8dbfe419db4446a Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 23 Nov 2022 13:15:39 +0100 Subject: [PATCH 152/174] fix typos --- PlayerTags/Resources/Strings.Designer.cs | 4 ++-- PlayerTags/Resources/Strings.resx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index 91d2069..8a1fc15 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -286,8 +286,8 @@ public static string Loc_DefaultPluginDataTemplate_Basic { } /// - /// Sucht eine lokalisierte Zeichenfolge, die Same as Empty, but includes a very basic pre-confiuration for formatting and coloring. - ///Can also be used if you want to make your own cofiguration but want basic formatting. ähnelt. + /// Sucht eine lokalisierte Zeichenfolge, die Same as Empty, but includes a very basic pre-configuration for formatting and coloring. + ///Can also be used if you want to make your own configuration but want basic formatting. ähnelt. /// public static string Loc_DefaultPluginDataTemplate_Basic_Description { get { diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 2ddb778..581e1cf 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -761,8 +761,8 @@ When disabled, only the disconnected status icon is priorized. Basic - Same as Empty, but includes a very basic pre-confiuration for formatting and coloring. -Can also be used if you want to make your own cofiguration but want basic formatting. + Same as Empty, but includes a very basic pre-configuration for formatting and coloring. +Can also be used if you want to make your own configuration but want basic formatting. Here you can choose the template for all the settings below. From 30ae07b1899fbaa690470ee2c0fd282a5a740c82 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 23 Nov 2022 14:47:48 +0100 Subject: [PATCH 153/174] fix typo --- PlayerTags/Resources/Strings.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 581e1cf..a100308 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -625,7 +625,7 @@ Insert behind group number prefix in chat - If enabled, the Tag and Icon will get insert behind the Group/Alliance number prefix in Chat instead of before. + If enabled, the Tag and Icon will get inserted behind the Group/Alliance number prefix in Chat instead of before. Nameplate properties From df74b2dd9a3aeda9848e70ac2fcb792776e099e1 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 23 Nov 2022 14:49:55 +0100 Subject: [PATCH 154/174] update translation files --- PlayerTags/Resources/Strings.Designer.cs | 2 +- PlayerTags/Resources/Strings.fr.resx | 180 +++++++++++++++++++++++ 2 files changed, 181 insertions(+), 1 deletion(-) diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index 8a1fc15..86a721c 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -447,7 +447,7 @@ public static string Loc_InsertBehindNumberPrefixInChat { } /// - /// Sucht eine lokalisierte Zeichenfolge, die If enabled, the Tag and Icon will get insert behind the Group/Alliance number prefix in Chat instead of before. ähnelt. + /// Sucht eine lokalisierte Zeichenfolge, die If enabled, the Tag and Icon will get inserted behind the Group/Alliance number prefix in Chat instead of before. ähnelt. /// public static string Loc_InsertBehindNumberPrefixInChat_Description { get { diff --git a/PlayerTags/Resources/Strings.fr.resx b/PlayerTags/Resources/Strings.fr.resx index 5574d81..9a8ff1f 100644 --- a/PlayerTags/Resources/Strings.fr.resx +++ b/PlayerTags/Resources/Strings.fr.resx @@ -354,6 +354,15 @@ Afficher dans le chat + + Si l'icône de rôle doit être affichée dans le chat. + + + Afficher l'icône de rôle dans les Plaques de nom + + + Si l'icône de rôle doit être affichée dans les plaques de nom. + Texte @@ -612,6 +621,177 @@ Autre (expérimental) + + Insérer après le préfixe de numéro d'équipe dans le chat + + + Si activée, cette option insérera le tag & l'icône après le préfixe de numéro d'équipe/d'alliance dans le chat plutôt qu'avant. + + + Propriétés de la plaque de nom + + + Définit quand est-ce que l'élément compagnie libre de la plaque de nom devrait être visible ou non. + + + Définit la position pour l'élément titre de la plaque de nom. Devrait-il être au-dessus, ou en-dessous du nom ? À vous de décider ! + + + Définit quand est-ce que l'élément titre de la plaque de nom devrait être visible ou non. + + + Chat + + + Afficher l'icône de rôle dans la plaque de nom + + + Afficher l'icône de job dans la Plaque de nom + + + Si l'icône de job doit être affichée dans les plaques de nom. + + + Set d'icônes de job + + + Le set d'icônes à utiliser pour afficher l'icône de job. Vous pouvez également choisir le set d'icône de rôle pour afficher un icône de rôle à la place. + + + Options de Chat Avancées + + + Types de Chat affectés + + + Définit quels types de chat devraient être affectés par les fonctionnalités de ce tag. + + + Priorité des icônes de statut + + + En mission + + + Les icônes de statuts qui ont la priorité durant les missions. + + + En mission d'exploration + + + Les icônes de statuts qui ont la priorité durant les missions d'exploration. + + + Hors-mission + + + Les icônes de statuts qui ont la priorité en dehors des missions. + + + Réinitialiser aux valeurs par défaut + + + Réinitialise toutes les conditions définies aux paramètres par défaut + + + Réinitialiser à zéro + + + Supprime toutes les conditions définies. Plus aucune icône de statut ne sera affichée en priorité. + + + Activer les priorités d'icônes + + + L'activation de cette option obligera la priorisation de l'affichage des icônes de statuts plutôt que celles de jobs, si vous avez activé les icônes de jobs. +Lorsque cette option est désactivée, seule l'icône de statut de déconnexion sera prioritaire. + + + Occupé·e + + + En cours de déconnexion + + + En recherche de mission + + + Pose de groupe + + + Absent·e + + + En mission + + + Mentor + + + Mentor (artisanat/récolte) + + + Mentor PvE + + + Mentor JcJ + + + Novice + + + Chef d'équipe + + + Membre d'équipe + + + Rappelé·e + + + Jeu de rôle + + + Cinématique + + + Modèle de base + + + Basique + + + Quasiment identique à Vide, mais inclut une pré-configuration très basique pour le formatage et la couleur. +Peut également être utilisé si vous souhaitez créer votre propre configuration, mais que vous souhaitez avoir un formatage basique tout de même. + + + Vous pouvez choisir ici le modèle de base pour tous les paramétrages ci-dessous. +Le modèle utilisé est un ensemble basique de propriétés. Chaque modification que vous faites sera sauvegardée ; cependant, les options provenant du modèle ne sont pas sauvegardées. +Cela vous permet de ne pas avoir à surcharger énormément de propriétés - ou de créer votre propre configuration complète sans modèle de base. + +Attention : +Modifier ce champ peut provoquer la réinitialisation de propriétés. Vous pouvez perdre une partie de votre configuration. +Après avoir modifié ce champ, vérifiez bien que tous vos paramètres correspondent à vos attentes. + + + Complet + + + Préconfiguré pour afficher le tag de job avec couleur et colore également le texte du nom du personnage. + + + Vide + + + Aucune configuration. C'est un modèle complètement vide. +Utilisez ce modèle si vous souhaitez avoir toutes les options sous votre contrôle ou si vous souhaitez avoir votre propre configuration légère. + + + Simple + + + Préconfiguré pour afficher le tag de job avec couleur et remplacer le titre par l'icône de rôle. + Les griser From e9617b624e80a8bea51de78eeffc147d504b23f8 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 27 Nov 2022 18:59:26 +0100 Subject: [PATCH 155/174] v1.8.2 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index d41259e..f79c1bd 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.1.0 + 1.8.2.0 From c0eb7b757533f288cd82031cbc189a69dd3344be Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 7 Dec 2022 07:09:46 +0100 Subject: [PATCH 156/174] change & to && isTagEnabled() --- PlayerTags/Features/ChatTagTargetFeature.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index d05f689..ae31123 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -410,7 +410,7 @@ void addPayloadChanges(Tag tag, IEnumerable payloads) if (stringMatch.GameObject is PlayerCharacter playerCharacter1) { - if (playerCharacter1.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter1.ClassJob.GameData.Abbreviation, out var jobTag) & isTagEnabled(jobTag)) + if (playerCharacter1.ClassJob.GameData != null && m_PluginData.JobTags.TryGetValue(playerCharacter1.ClassJob.GameData.Abbreviation, out var jobTag) && isTagEnabled(jobTag)) applyTextFormatting(jobTag); } From 8c8683cf8d76cdf514f73e03485d14e3760761f5 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 7 Dec 2022 07:17:46 +0100 Subject: [PATCH 157/174] enable tags on ALL chat messages, regardless if the Chat Type is defined --- PlayerTags/Features/ChatTagTargetFeature.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index ae31123..c6e4eb1 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -121,7 +121,7 @@ public override void Dispose() private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) { - if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType].IsApplyTagsToAllChatMessagesEnabled && Enum.IsDefined(type)) + if (m_PluginConfiguration.GeneralOptions[ActivityContextManager.CurrentActivityContext.ActivityType].IsApplyTagsToAllChatMessagesEnabled) { AddTagsToChat(sender, type, true); AddTagsToChat(message, type, false); From 16b0d1fb13b072b6f41bff11bc8f137a6869f16b Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 7 Dec 2022 20:11:22 +0100 Subject: [PATCH 158/174] add option to also include undefined chat types --- PlayerTags/Data/DefaultPluginData.cs | 3 +++ PlayerTags/Data/Tag.cs | 2 ++ PlayerTags/Features/ChatTagTargetFeature.cs | 3 ++- PlayerTags/Resources/Strings.Designer.cs | 19 +++++++++++++++++++ PlayerTags/Resources/Strings.de.resx | 7 +++++++ PlayerTags/Resources/Strings.resx | 7 +++++++ 6 files changed, 40 insertions(+), 1 deletion(-) diff --git a/PlayerTags/Data/DefaultPluginData.cs b/PlayerTags/Data/DefaultPluginData.cs index e7365ba..84bf440 100644 --- a/PlayerTags/Data/DefaultPluginData.cs +++ b/PlayerTags/Data/DefaultPluginData.cs @@ -151,6 +151,7 @@ private void SetupTemplateBasic() TagTargetInNameplates = NameplateElement.Title, TargetChatTypes = new List(Enum.GetValues()), + TargetChatTypesIncludeUndefined = true, }; AllRoleTags = new Tag() @@ -258,6 +259,7 @@ private void SetupTemplateSimple() IsVisibleForOtherPlayers = true, TargetChatTypes = new List(Enum.GetValues()), + TargetChatTypesIncludeUndefined = true, }; AllRoleTags = new Tag() @@ -372,6 +374,7 @@ private void SetupTemplateFull() IsVisibleForOtherPlayers = true, TargetChatTypes = new List(Enum.GetValues()), + TargetChatTypesIncludeUndefined = true, }; AllRoleTags = new Tag() diff --git a/PlayerTags/Data/Tag.cs b/PlayerTags/Data/Tag.cs index 1ff6dfa..1244c1c 100644 --- a/PlayerTags/Data/Tag.cs +++ b/PlayerTags/Data/Tag.cs @@ -189,6 +189,8 @@ private InheritableValue IsIconVisibleInNameplate [InheritableCategory("ChatFeatureCategory")] public InheritableReference> TargetChatTypes = new(new List(Enum.GetValues())); + [InheritableCategory("ChatFeatureCategory")] + public InheritableValue TargetChatTypesIncludeUndefined = new(true); [JsonIgnore] public string[] IdentitiesToAddTo diff --git a/PlayerTags/Features/ChatTagTargetFeature.cs b/PlayerTags/Features/ChatTagTargetFeature.cs index c6e4eb1..fe11e31 100644 --- a/PlayerTags/Features/ChatTagTargetFeature.cs +++ b/PlayerTags/Features/ChatTagTargetFeature.cs @@ -341,7 +341,8 @@ private void AddTagsToChat(SeString message, XivChatType chatType, bool isSender StringChanges stringChanges = new(); bool isTagEnabled(Tag tag) - => tag.TagPositionInChat.InheritedValue != null && tag.TargetChatTypes.InheritedValue != null && tag.TargetChatTypes.InheritedValue.Contains(chatType); + => tag.TagPositionInChat.InheritedValue != null && tag.TargetChatTypes.InheritedValue != null && + (tag.TargetChatTypes.InheritedValue.Contains(chatType) || (!Enum.IsDefined(chatType) && (tag.TargetChatTypesIncludeUndefined?.InheritedValue ?? false))); if (stringMatch.GameObject is PlayerCharacter playerCharacter) { diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index 86a721c..d14322a 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -2075,6 +2075,25 @@ public static string Loc_TargetChatTypes_Description { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Include undefined Chat Types ähnelt. + /// + public static string Loc_TargetChatTypesIncludeUndefined { + get { + return ResourceManager.GetString("Loc_TargetChatTypesIncludeUndefined", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die When enabled the Tag will apply to all Chat messages that has not a defined type. + ///This case can happen either if the Game updates and the Enumeration of all Chat Types gets invalid due to shifted values, or plugins creates a custom chat type for whatever reason. ähnelt. + /// + public static string Loc_TargetChatTypesIncludeUndefined_Description { + get { + return ResourceManager.GetString("Loc_TargetChatTypesIncludeUndefined_Description", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Text ähnelt. /// diff --git a/PlayerTags/Resources/Strings.de.resx b/PlayerTags/Resources/Strings.de.resx index c5fa5fa..da21b3e 100644 --- a/PlayerTags/Resources/Strings.de.resx +++ b/PlayerTags/Resources/Strings.de.resx @@ -822,4 +822,11 @@ Benutze dies, wenn du jede Option unter deiner Kontrolle haben möchtest oder nu Rollensymbol im Chat anzeigen + + Undefinierte Chattypen einbeziehen + + + Wenn aktiviert, gilt das Tag für alle Chat-Nachrichten, die keinen definierten Typ haben. +Dieser Fall kann entweder auftreten, wenn das Spiel ein Update bekommt und die Aufzählung aller Chat-Typen aufgrund von geänderten Werten ungültig sind oder Plugins erstellt einen benutzerdefinierten Chat-Typ, aus welchen Gründen auch immer. + \ No newline at end of file diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index a100308..0850b13 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -822,4 +822,11 @@ Use this if you want to to have every option under your control or just want to Show role icon in Chat + + Include undefined Chat Types + + + When enabled the Tag will apply to all Chat messages that has not a defined type. +This case can happen either if the Game updates and the Enumeration of all Chat Types gets invalid due to shifted values, or plugins creates a custom chat type for whatever reason. + \ No newline at end of file From 5bb3335af6f6613677c7c819082a3865557edd1b Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 7 Dec 2022 20:11:38 +0100 Subject: [PATCH 159/174] v1.8.3 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index f79c1bd..688b060 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.2.0 + 1.8.3.0 From 7527e4f373cdebfc06c64558144e9540a0125f5a Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 10 Dec 2022 12:36:56 +0100 Subject: [PATCH 160/174] update translation files --- PlayerTags/Resources/Strings.es-ES.resx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/PlayerTags/Resources/Strings.es-ES.resx b/PlayerTags/Resources/Strings.es-ES.resx index aa1015d..17cf525 100644 --- a/PlayerTags/Resources/Strings.es-ES.resx +++ b/PlayerTags/Resources/Strings.es-ES.resx @@ -822,4 +822,11 @@ Usa esto si quieres tener todas las opciones bajo tu control o solo quieres hace Mostrar icono de rol en placas de chat + + Incluir Tipos de Chat sin definir + + + Cuando está habilitado, la Etiqueta se aplicará todos los mensajes de chat que no tengan un tipo definido. +Esto puede ocurrir tanto si el juego se actualiza y la enumeración de todos los tipos de chat se vuelve inválida debido a valores modificados, o si algún otro plugin crea un tipo de chat personalizado por cualquier motivo. + \ No newline at end of file From 5734e0d6808c4bc20f0b2f29f39b193c02b5aa14 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 10 Dec 2022 12:37:44 +0100 Subject: [PATCH 161/174] v1.8.3.1 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 688b060..8a86ff6 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.3.0 + 1.8.3.1 From 32b73aa8514336b8108596a80a652800c15e2ba4 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 19 Dec 2022 08:51:44 +0100 Subject: [PATCH 162/174] a few hight-DPI improvements --- .../Configuration/PluginConfigurationUI.cs | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index cbc334e..3f448a5 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -12,6 +12,7 @@ using Pilz.Dalamud.Icons; using Pilz.Dalamud.Nameplates.Model; using Pilz.Dalamud.Nameplates.Tools; +using Pilz.Dalamud.Tools; using PlayerTags.Data; using PlayerTags.Inheritables; using PlayerTags.PluginStrings; @@ -40,6 +41,8 @@ private struct PlayerInfo private InheritableValue? m_ColorPickerPopupDataContext; private Dictionary inheritableTEnumProxies = new(); + private static float dpiScaling = ImGui.GetWindowDpiScale(); + public PluginConfigurationUI(PluginConfiguration config, PluginData pluginData) { m_PluginConfiguration = config; @@ -47,6 +50,8 @@ public PluginConfigurationUI(PluginConfiguration config, PluginData pluginData) propertyProxy = new PropertyProxy(config); } + private static float ScaleDpi(float input) => input * dpiScaling; + public void Draw() { if (m_PluginConfiguration == null || !m_PluginConfiguration.IsVisible) @@ -54,7 +59,7 @@ public void Draw() return; } - ImGui.SetNextWindowSize(new Vector2(600, 500), ImGuiCond.FirstUseEver); + ImGui.SetNextWindowSize(new Vector2(ScaleDpi(600), ScaleDpi(500)), ImGuiCond.FirstUseEver); if (ImGui.Begin(Strings.Loc_Static_PluginName, ref m_PluginConfiguration.IsVisible)) { @@ -463,8 +468,10 @@ public void DrawTree(Tag tag) // Don't allow expanding the item to select the item // Don't allow clicking on add/remove buttons to select the item - var deadzoneTopLeft = new Vector2(beforeItemPos.X + ImGui.GetContentRegionAvail().X - 23, beforeItemPos.Y - 2); - var deadzoneBottomRight = new Vector2(beforeItemPos.X + ImGui.GetContentRegionAvail().X + 2, afterItemPos.Y + 2); + var hard23 = ScaleDpi(23); + var hard2 = ScaleDpi(2); + var deadzoneTopLeft = new Vector2(beforeItemPos.X + ImGui.GetContentRegionAvail().X - hard23, beforeItemPos.Y - hard2); + var deadzoneBottomRight = new Vector2(beforeItemPos.X + ImGui.GetContentRegionAvail().X + hard2, afterItemPos.Y + hard2); if (!ImGui.IsItemToggledOpen() && !ImGui.IsMouseHoveringRect(deadzoneTopLeft, deadzoneBottomRight) && ImGui.IsItemClicked()) { Select(tag); @@ -480,7 +487,7 @@ public void DrawTree(Tag tag) ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(0, 0)); ImGui.PushStyleVar(ImGuiStyleVar.ItemInnerSpacing, new Vector2(0, 0)); ImGui.PushFont(UiBuilder.IconFont); - ImGui.SetCursorPosX(ImGui.GetCursorPos().X + ImGui.GetContentRegionAvail().X - 23); + ImGui.SetCursorPosX(ImGui.GetCursorPos().X + ImGui.GetContentRegionAvail().X - hard23); if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString())) { var newTag = new Tag(new LocalizedPluginString(nameof(PluginData.CustomTags))) @@ -519,7 +526,7 @@ public void DrawTree(Tag tag) ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(0, 0)); ImGui.PushStyleVar(ImGuiStyleVar.ItemInnerSpacing, new Vector2(0, 0)); ImGui.PushFont(UiBuilder.IconFont); - ImGui.SetCursorPosX(ImGui.GetCursorPos().X + ImGui.GetContentRegionAvail().X - 23); + ImGui.SetCursorPosX(ImGui.GetCursorPos().X + ImGui.GetContentRegionAvail().X - hard23); if (ImGui.Button(FontAwesomeIcon.TrashAlt.ToIconString())) { m_PluginData.RemoveCustomTagFromIdentities(tag); @@ -574,6 +581,7 @@ public void DrawTree(Tag tag) public void DrawControls(Tag tag) { + var hard23 = ScaleDpi(23); ImGui.PushID(tag.GetHashCode().ToString()); // Render the add property override button and popup @@ -589,7 +597,7 @@ public void DrawControls(Tag tag) ImGui.PushStyleColor(ImGuiCol.ButtonActive, new Vector4(0.2f, 0.6f, 0.2f, 1)); ImGui.PushFont(UiBuilder.IconFont); - if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString(), new Vector2(23, 23))) + if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString(), new Vector2(hard23, hard23))) { ImGui.OpenPopup("AddPopup"); } @@ -599,8 +607,8 @@ public void DrawControls(Tag tag) ImGui.PopStyleColor(); bool wasPaddingConsumed = false; - ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, 5)); - ImGui.SetNextWindowPos(ImGui.GetCursorScreenPos() - new Vector2(0, 4)); + ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, ScaleDpi(5))); + ImGui.SetNextWindowPos(ImGui.GetCursorScreenPos() - new Vector2(0, ScaleDpi(4))); if (ImGui.BeginPopup("AddPopup")) { wasPaddingConsumed = true; @@ -695,7 +703,7 @@ public void DrawControls(Tag tag) { ImGui.SameLine(); ImGui.PushFont(UiBuilder.IconFont); - ImGui.SetCursorPosX(ImGui.GetCursorPos().X + ImGui.GetContentRegionAvail().X - 23); + ImGui.SetCursorPosX(ImGui.GetCursorPos().X + ImGui.GetContentRegionAvail().X - hard23); if (ImGui.Button(FontAwesomeIcon.Recycle.ToIconString())) { tag.SetDefaults(); @@ -807,12 +815,13 @@ public void DrawControls(Tag tag) private void DrawRemovePropertyOverrideButton(IInheritable inheritable) { + var hard23 = ScaleDpi(23); ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(0, 0)); ImGui.PushStyleColor(ImGuiCol.Button, new Vector4(0.3f, 0.1f, 0.1f, 1)); ImGui.PushStyleColor(ImGuiCol.ButtonHovered, new Vector4(0.6f, 0.2f, 0.2f, 1)); ImGui.PushStyleColor(ImGuiCol.ButtonActive, new Vector4(0.6f, 0.2f, 0.2f, 1)); ImGui.PushFont(UiBuilder.IconFont); - if (ImGui.Button(FontAwesomeIcon.TrashAlt.ToIconString(), new Vector2(23, 23))) + if (ImGui.Button(FontAwesomeIcon.TrashAlt.ToIconString(), new Vector2(hard23, hard23))) { inheritable.Behavior = InheritableBehavior.Inherit; SaveSettings(); @@ -837,7 +846,7 @@ private void DrawInheritable(string localizedStringName, InheritableValue } ImGui.BeginGroup(); - ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(0 , 50)); + ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(0, ScaleDpi(50))); ImGui.Text(Localizer.GetString(localizedStringName, false)); if (ImGui.IsItemHovered()) @@ -890,7 +899,7 @@ private void DrawInheritable(string localizedStringName, bool shouldLocal } ImGui.BeginGroup(); - ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(0, 50)); + ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(0, ScaleDpi(50))); ImGui.Text(Localizer.GetString(localizedStringName, false)); if (ImGui.IsItemHovered()) @@ -914,8 +923,8 @@ private void DrawInheritable(string localizedStringName, bool shouldLocal if (isEnabled) { ImGui.SameLine(); - ImGui.SetNextItemWidth(200); - ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(200, 0)); + ImGui.SetNextItemWidth(ScaleDpi(200)); + ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(ScaleDpi(200), 0)); TEnum value = inheritable.InheritedValue != null ? inheritable.InheritedValue.Value : default(TEnum); DrawComboBox(false, shouldLocalizeNames, shouldOrderNames, ref value, () => { }); ImGui.EndChild(); @@ -940,8 +949,8 @@ private void DrawInheritable(string localizedStringName, bool shouldLocal if (isEnabled) { ImGui.SameLine(); - ImGui.SetNextItemWidth(200); - ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(200, 0)); + ImGui.SetNextItemWidth(ScaleDpi(200)); + ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(ScaleDpi(200), 0)); DrawComboBox(false, shouldLocalizeNames, shouldOrderNames, ref inheritable.Value, () => { SaveSettings(); }); ImGui.EndChild(); } @@ -968,7 +977,7 @@ private void DrawInheritable(string localizedStringName, InheritableValue { }); ImGui.EndChild(); @@ -1127,8 +1136,8 @@ private void DrawInheritable(string localizedStringName, InheritableReference { SaveSettings(); }); ImGui.EndChild(); } @@ -1304,7 +1313,7 @@ private void DrawColorButton(string colorId, Vector4 color, System.Action clicke ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(0, 0)); ImGui.PushStyleVar(ImGuiStyleVar.ItemInnerSpacing, new Vector2(0, 0)); ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 0); - if (ImGui.Button($"###{colorId}", new Vector2(23, 23))) + if (ImGui.Button($"###{colorId}", new Vector2(ScaleDpi(23), ScaleDpi(23)))) { clicked(); } From 89c0f2197135a0d36e615282291fab0581040e54 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 19 Dec 2022 08:55:56 +0100 Subject: [PATCH 163/174] simplyfy GetIdentity --- PlayerTags/Data/PluginData.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/PlayerTags/Data/PluginData.cs b/PlayerTags/Data/PluginData.cs index c8b5481..cd9c2c8 100644 --- a/PlayerTags/Data/PluginData.cs +++ b/PlayerTags/Data/PluginData.cs @@ -266,13 +266,9 @@ public Identity GetIdentity(string name, uint? worldId) { identity.WorldId = worldId; pluginConfiguration.Save(this); - - return identity; - } - else - { - return identity; } + + return identity; } } From 078bb3a2fda6de4559c073a795066354d2bb5313 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 19 Dec 2022 08:56:21 +0100 Subject: [PATCH 164/174] v1.8.4.0 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 8a86ff6..1a43dc6 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.3.1 + 1.8.4.0 From be9a450c7de5558a64ca0daf18a5e9d25f0ec07d Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 19 Dec 2022 11:24:58 +0100 Subject: [PATCH 165/174] use ImGuiHelper --- .../Configuration/PluginConfigurationUI.cs | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index 3f448a5..eceea73 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -41,8 +41,6 @@ private struct PlayerInfo private InheritableValue? m_ColorPickerPopupDataContext; private Dictionary inheritableTEnumProxies = new(); - private static float dpiScaling = ImGui.GetWindowDpiScale(); - public PluginConfigurationUI(PluginConfiguration config, PluginData pluginData) { m_PluginConfiguration = config; @@ -50,7 +48,7 @@ public PluginConfigurationUI(PluginConfiguration config, PluginData pluginData) propertyProxy = new PropertyProxy(config); } - private static float ScaleDpi(float input) => input * dpiScaling; + private static float ScalePoints(float input) => input * ImGuiHelpers.GlobalScale; public void Draw() { @@ -59,7 +57,7 @@ public void Draw() return; } - ImGui.SetNextWindowSize(new Vector2(ScaleDpi(600), ScaleDpi(500)), ImGuiCond.FirstUseEver); + ImGui.SetNextWindowSize(ImGuiHelpers.ScaledVector2(600, 500), ImGuiCond.FirstUseEver); if (ImGui.Begin(Strings.Loc_Static_PluginName, ref m_PluginConfiguration.IsVisible)) { @@ -468,8 +466,8 @@ public void DrawTree(Tag tag) // Don't allow expanding the item to select the item // Don't allow clicking on add/remove buttons to select the item - var hard23 = ScaleDpi(23); - var hard2 = ScaleDpi(2); + var hard23 = ScalePoints(23); + var hard2 = ScalePoints(2); var deadzoneTopLeft = new Vector2(beforeItemPos.X + ImGui.GetContentRegionAvail().X - hard23, beforeItemPos.Y - hard2); var deadzoneBottomRight = new Vector2(beforeItemPos.X + ImGui.GetContentRegionAvail().X + hard2, afterItemPos.Y + hard2); if (!ImGui.IsItemToggledOpen() && !ImGui.IsMouseHoveringRect(deadzoneTopLeft, deadzoneBottomRight) && ImGui.IsItemClicked()) @@ -581,7 +579,7 @@ public void DrawTree(Tag tag) public void DrawControls(Tag tag) { - var hard23 = ScaleDpi(23); + var hard23 = ScalePoints(23); ImGui.PushID(tag.GetHashCode().ToString()); // Render the add property override button and popup @@ -607,8 +605,8 @@ public void DrawControls(Tag tag) ImGui.PopStyleColor(); bool wasPaddingConsumed = false; - ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, ScaleDpi(5))); - ImGui.SetNextWindowPos(ImGui.GetCursorScreenPos() - new Vector2(0, ScaleDpi(4))); + ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, ImGuiHelpers.ScaledVector2(0, 5)); + ImGui.SetNextWindowPos(ImGui.GetCursorScreenPos() - ImGuiHelpers.ScaledVector2(0, 4)); if (ImGui.BeginPopup("AddPopup")) { wasPaddingConsumed = true; @@ -815,13 +813,12 @@ public void DrawControls(Tag tag) private void DrawRemovePropertyOverrideButton(IInheritable inheritable) { - var hard23 = ScaleDpi(23); ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(0, 0)); ImGui.PushStyleColor(ImGuiCol.Button, new Vector4(0.3f, 0.1f, 0.1f, 1)); ImGui.PushStyleColor(ImGuiCol.ButtonHovered, new Vector4(0.6f, 0.2f, 0.2f, 1)); ImGui.PushStyleColor(ImGuiCol.ButtonActive, new Vector4(0.6f, 0.2f, 0.2f, 1)); ImGui.PushFont(UiBuilder.IconFont); - if (ImGui.Button(FontAwesomeIcon.TrashAlt.ToIconString(), new Vector2(hard23, hard23))) + if (ImGui.Button(FontAwesomeIcon.TrashAlt.ToIconString(), ImGuiHelpers.ScaledVector2(23))) { inheritable.Behavior = InheritableBehavior.Inherit; SaveSettings(); @@ -846,7 +843,7 @@ private void DrawInheritable(string localizedStringName, InheritableValue } ImGui.BeginGroup(); - ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(0, ScaleDpi(50))); + ImGui.BeginChild(inheritable.GetHashCode().ToString(), ImGuiHelpers.ScaledVector2(0, 50)); ImGui.Text(Localizer.GetString(localizedStringName, false)); if (ImGui.IsItemHovered()) @@ -899,7 +896,7 @@ private void DrawInheritable(string localizedStringName, bool shouldLocal } ImGui.BeginGroup(); - ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(0, ScaleDpi(50))); + ImGui.BeginChild(inheritable.GetHashCode().ToString(), ImGuiHelpers.ScaledVector2(0, 50)); ImGui.Text(Localizer.GetString(localizedStringName, false)); if (ImGui.IsItemHovered()) @@ -923,8 +920,8 @@ private void DrawInheritable(string localizedStringName, bool shouldLocal if (isEnabled) { ImGui.SameLine(); - ImGui.SetNextItemWidth(ScaleDpi(200)); - ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(ScaleDpi(200), 0)); + ImGui.SetNextItemWidth(ScalePoints(200)); + ImGui.BeginChild(inheritable.GetHashCode().ToString(), ImGuiHelpers.ScaledVector2(200, 0)); TEnum value = inheritable.InheritedValue != null ? inheritable.InheritedValue.Value : default(TEnum); DrawComboBox(false, shouldLocalizeNames, shouldOrderNames, ref value, () => { }); ImGui.EndChild(); @@ -949,8 +946,8 @@ private void DrawInheritable(string localizedStringName, bool shouldLocal if (isEnabled) { ImGui.SameLine(); - ImGui.SetNextItemWidth(ScaleDpi(200)); - ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(ScaleDpi(200), 0)); + ImGui.SetNextItemWidth(ScalePoints(200)); + ImGui.BeginChild(inheritable.GetHashCode().ToString(), ImGuiHelpers.ScaledVector2(200, 0)); DrawComboBox(false, shouldLocalizeNames, shouldOrderNames, ref inheritable.Value, () => { SaveSettings(); }); ImGui.EndChild(); } @@ -977,7 +974,7 @@ private void DrawInheritable(string localizedStringName, InheritableValue { }); ImGui.EndChild(); @@ -1136,8 +1133,8 @@ private void DrawInheritable(string localizedStringName, InheritableReference { SaveSettings(); }); ImGui.EndChild(); } @@ -1313,7 +1310,7 @@ private void DrawColorButton(string colorId, Vector4 color, System.Action clicke ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(0, 0)); ImGui.PushStyleVar(ImGuiStyleVar.ItemInnerSpacing, new Vector2(0, 0)); ImGui.PushStyleVar(ImGuiStyleVar.FrameRounding, 0); - if (ImGui.Button($"###{colorId}", new Vector2(ScaleDpi(23), ScaleDpi(23)))) + if (ImGui.Button($"###{colorId}", ImGuiHelpers.ScaledVector2(23))) { clicked(); } From 6589412ef37326570cf625f160375dd89e899749 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 19 Dec 2022 11:26:41 +0100 Subject: [PATCH 166/174] v1.8.4.1 --- PlayerTags/PlayerTags.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index 1a43dc6..dd4d875 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,7 +1,7 @@  r00telement;Pilzinsel64 - 1.8.4.0 + 1.8.4.1 From 61ea6f48347aba8171753d83f4bb8d2eaee0a720 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 1 Jan 2023 19:56:49 +0100 Subject: [PATCH 167/174] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 61f58dc..3fab814 100644 --- a/README.md +++ b/README.md @@ -24,4 +24,4 @@ If you want to contribute to a language that isn't listed, just tell me with an # Credits -This plugin was originally developed by r00telement but forked and continued by Pilzinsel64. +This plugin was originally developed by [r00telement](https://github.com/r00telement) but forked and continued by Pilzinsel64. From ab483384e858f680ee098c4b4108d35f8d741172 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sun, 1 Jan 2023 19:57:07 +0100 Subject: [PATCH 168/174] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3fab814..17db729 100644 --- a/README.md +++ b/README.md @@ -24,4 +24,4 @@ If you want to contribute to a language that isn't listed, just tell me with an # Credits -This plugin was originally developed by [r00telement](https://github.com/r00telement) but forked and continued by Pilzinsel64. +This plugin was originally developed by [r00telement](https://github.com/r00telement) but forked and continued by [Pilzinsel64](https://github.com/Pilzinsel64). From d13672b34d8bcab652d0378664213665cfcf7f17 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 7 Jan 2023 13:01:12 +0100 Subject: [PATCH 169/174] Add Japanese by Refer to README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 17db729..b6d7202 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ If you want to contribute to a language that isn't listed, just tell me with an | German | Pilzinsel64, xEbony | Spanish | Risu | French | Khayle +| Japanese | Refer | ... | You? # Credits From 4673928a81efd834796c8953c99fbf1fef3336e0 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Sat, 7 Jan 2023 13:05:44 +0100 Subject: [PATCH 170/174] update translation files --- PlayerTags/Resources/Strings.fr.resx | 7 + PlayerTags/Resources/Strings.ja.resx | 832 +++++++++++++++++++++++++++ 2 files changed, 839 insertions(+) create mode 100644 PlayerTags/Resources/Strings.ja.resx diff --git a/PlayerTags/Resources/Strings.fr.resx b/PlayerTags/Resources/Strings.fr.resx index 9a8ff1f..735187e 100644 --- a/PlayerTags/Resources/Strings.fr.resx +++ b/PlayerTags/Resources/Strings.fr.resx @@ -822,4 +822,11 @@ Utilisez ce modèle si vous souhaitez avoir toutes les options sous votre contr Afficher l'icône de rôle dans le Chat + + Inclure les types de chat non-définis + + + Lorsque cette option est activée, le tag s'appliquera à tous les messages qui n'ont pas de type défini. +Cela peut se produire si les mises à jour du jeu et l'énumération de tous les types de chat deviennent invalides en raison de valeurs déplacées ou altérées, ou si un autre plugin crée un type de chat personnalisé pour quelque raison que ce soit. + \ No newline at end of file diff --git a/PlayerTags/Resources/Strings.ja.resx b/PlayerTags/Resources/Strings.ja.resx new file mode 100644 index 0000000..2e6d6fc --- /dev/null +++ b/PlayerTags/Resources/Strings.ja.resx @@ -0,0 +1,832 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Player Tags + + + このプラグインは、ネームプレートやチャットを修正することができます。これらを変更する他のプラグインと組み合わせた場合、不具合が起きる可能性があります。プラグインのロード順で違いが出るかもしれません。 + + + 全般 + + + 簡易タグ + + + タグ付きプレイヤー + + + プレイヤー + + + タグを追加: {0} + + + タグを削除: {0} + + + ネームプレート + + + {1} に {0} を追加する + + + <Inherited> + + + 選択中 + + + 展開中 + + + コンテキストメニューの統合 + + + コンテキストメニューに、プレイヤーにタグを追加・削除するためのオプションが追加されます。 + + + 継承されたプロパティの表示 + + + 親ノードから継承したプロパティがエディタに表示されます。 + + + フリーカンパニーを表示 + + + Default + + + ネームプレートのFCタグは、キャラクターがフリーカンパニーに入っているときのみ表示されます。 + + + 表示しない + + + ネームプレートのFCタグは、一切表示されません。 + + + 称号の表示 + + + 常に表示 + + + ネームプレートの称号は、キャラクターが称号を付けていない場合でも常に表示されます。 + + + Default + + + ネームプレートの称号は、キャラクターが称号を付けている場合のみ表示されます。 + + + 表示しない + + + ネームプレートの称号は、一切表示されません。 + + + タグがある場合のみ表示 + + + ネームプレートの称号は、タグがある場合のみ表示されます。 + + + 称号の位置 + + + 常に名前の上に表示 + + + ネームプレートの称号は、常に名前の上に配置されます。 + + + 常に名前の下に表示 + + + ネームプレートの称号は、常に名前の下に配置されます。 + + + Default + + + 称号の表示位置は、称号によって位置が変わります。 + + + フリーカンパニー + + + ネームプレート上の 名前 要素。 + + + 名前 + + + ネームプレート上の 名前 要素。 + + + 称号 + + + ネームプレート上の 称号 要素。 + + + 開発版 + + + 試験運用版 + + + ランダムにプレイヤー名を生成する + + + すべてのプレイヤーの名前を、ランダムに生成したものに置き換える。 + + + チャットで自分にタグを適用する + + + チャットネームとキャラクターを紐付けし、チャットで自身にタグを適用できるようにしようとするものです。 + + + すべてのチャットメッセージにタグを適用する + + + 全体チャットを含む、すべてのチャットメッセージにタグを適用します。 + + + この項目を既定にリセットします。 + + + すべての項目を既定にリセットします。カスタムタグは変更されません。 + + + タグ + + + <No text> + + + 全て + + + ロール + + + ギャザラー/クラフター + + + タンク + + + ヒーラー + + + DPS + + + 近接 + + + レンジ + + + 魔法 + + + 物理 + + + クラフター + + + ギャザラー + + + カスタム + + + カスタム + + + この上書きの値を有効にします。 + + + プロパティの上書きを追加します。 + + + このプロパティの上書きを削除します。値は親アイテムから継承されます。 + + + 新しいタグ + + + カスタムタグを追加する。 + + + このカスタムタグを削除します。 + + + アイコン + + + 実際に表示されるアイコンです + + + チャット上で表示 + + + チャットでロールアイコンを表示するかどうか。 + + + ネームプレートにロールアイコンを表示 + + + ネームプレートにロールアイコンを表示するかどうか。 + + + テキスト + + + 実際に表示されるテキストです + + + + + + テキストの色 + + + 発光色 + + + テキストの発光色 + + + 斜体 + + + テキストを斜体にするかどうか。 + + + チャット上で表示 + + + チャットでテキストを表示するかどうか。 + + + ネームプレートに表示 + + + ネームプレートにテキストを表示するかどうか。 + + + チャット中の位置 + + + チャットでタグが配置される場所。 + + + ネームプレートの位置 + + + ネームプレートでタグが配置される場所。 + + + ターゲットのネームプレート + + + ネームプレートにおいて、タグが対象とすべき要素。 + + + プレイヤーを追加 + + + タグを追加するプレイヤーのリスト。カンマまたはセミコロンで区切ります。例:"Yoshida Naoki, Hime Chan"。 + + + の後 + + + 対象の要素の後にタグを表示する。 + + + の前 + + + 対象の要素の前にタグを表示する。 + + + 置換 + + + 対象の要素をタグに置き換える。 + + + 有効化 + + + カスタム ID + + + 全般プロパティ + + + アイコンのプロパティ + + + テキストのプロパティ + + + 位置のプロパティ + + + アクティビティのプロパティ + + + プレイヤーのプロパティ + + + PvEコンテンツ中に表示 + + + PvEコンテンツ中にタグを表示するかどうか。 + + + PvPコンテンツ中に表示 + + + PvPコンテンツ中にタグを表示するかどうか。 + + + 別の場所で表示 + + + 特定のオプションがない他の状況でもタグを表示するかどうか。 + + + 自分に表示 + + + タグを自分のプレイヤーに表示するかどうか。 + + + パーティーメンバーに表示 + + + タグをパーティメンバーに表示するかどうか。 + + + アライアンスメンバーに表示 + + + パーティに参加していないアライアンスメンバーにもタグを表示するかどうか。 + + + フレンドに表示 + + + タグをフレンドに表示するかどうか。 + + + 敵に表示 + + + PvPコンテンツで敵にタグを表示させるかどうか。 + + + その他に表示 + + + 特定のオプションがない他の状況でプレイヤーにタグを表示するかどうか。 + + + 近接順で並べ替え + + + 自分に近いプレーヤーが上に向かって並びます。 + + + 自己を表示 + + + プレイヤーリストに自分自身を表示します。 + + + フレンドを表示 + + + プレイヤーリストにフレンドを表示します。 + + + パーティーメンバーを表示 + + + プレイヤーリストにパーティメンバーを表示します。 + + + アライアンスメンバーを表示 + + + プレイヤー一覧にアライアンスメンバーを表示します。 + + + 敵を表示 + + + プレイヤー一覧に敵を表示します。 + + + その他を表示 + + + プレイヤーリストにその他を表示します。 + + + チャット名に色をつける + + + チャットで名前に色をつけるかどうか。 + + + ネームプレートに色をつける + + + ネームプレートの名前に色をつけるかどうか。 + + + ネームプレートの称号に色をつける + + + ネームプレートの称号に色をつけるかどうか。 + + + ネームプレートのFCタグに色をつける + + + ネームプレートのFCタグに色をつけるかどうか。 + + + すべての場所 + + + 非戦闘中 + + + PvEコンテンツ + + + PvPコンテンツ + + + 現在有効なプロファイル + + + 以下のオプションを適用する + + + 以下のオプションは、あなたがどこにいても適用されます。オーバーワールドでも、PvEコンテンツでも、PvPコンテンツでも同じになります。他の環境用に定義されたオプションは上書きされます。 + + + 以下のオプションは、あらゆるコンテンツの外にいる場合にのみ適用されます。 + + + 以下のオプションは、PvEコンテンツにのみ適用されます。 + + + 以下のオプションは、PvPコンテンツにのみ適用されます。 + + + チャット(試験的機能) + + + その他(試験的機能) + + + チャットでグループ番号の後ろに接頭辞を挿入する + + + 有効にすると、タグとアイコンは、チャットでグループ/アライアンス番号の前ではなく後ろに挿入されます。 + + + ネームプレートプロパティ + + + ネームプレートのフリーカンパニー要素が表示されるかどうかを定義します。 + + + ネームプレートの称号の位置を定義します。名前の上に置くか下に置くか?あなたが決めてください。 + + + ネームプレートの称号をいつ表示するかどうかを定義する。 + + + チャット + + + ネームプレートにロールアイコンを表示 + + + ネームプレートにジョブアイコンを表示 + + + ネームプレートにジョブアイコンを表示させるかどうか。 + + + ジョブのアイコンをセット + + + ジョブアイコンを表示するために使用するアイコンセットです。ロールアイコンを選択して、代わりにロールアイコンを表示することもできます。 + + + 詳細なチャットオプション + + + 対象チャットの種類 + + + このタグのチャット機能を有効にするチャットの種類を定義します。 + + + ステータスアイコンの優先順位 + + + コンテンツ中 + + + コンテンツ内で優先的に表示されるべきステータスアイコン。 + + + In Foray + + + Foray内で優先的に表示されるべきステータスアイコン。 + + + オーバーワールド + + + オーバーワールドで優先的に表示されるべきステータスアイコン。 + + + 既定値に戻す + + + すべての条件セットを初期設定に戻す + + + 空に戻す + + + すべての条件セットを空のコレクションにクリアします。ステータスアイコンは優先されません。 + + + 優先順位付けされたアイコンを使用 + + + このオプションをオンにすると、ジョブアイコンを有効にすると、ステータスアイコンのセットがジョブアイコンよりも優先されます。 +無効にすると、ステータスアイコンのみが優先されます。 + + + 取り込み中 + + + 切断中 + + + コンテンツファインダー + + + グループポーズ + + + 放置中 + + + 戦闘中 + + + メンター + + + 製作採集メンター + + + バトルメンター + + + PvPメンター + + + 若葉マーク + + + PTリーダー + + + PTメンバー + + + リターナー + + + ロールプレイ中 + + + カットシーン中 + + + テンプレート + + + 基本 + + + Emptyと同じですが、フォーマットとカラーリングのための非常に基本的な事前設定を含んでいます。 +独自の設定をしたいが、基本的な書式が欲しい場合にも使用できる。 + + + ここでは、以下のすべての設定のテンプレートを選択することができます。 +テンプレートはプロパティの基本セットとして使用されます。あなたが行うすべての変更は、保存されます。しかし、このテンプレートのオプションはすべて保存されません。 +これは、多くのプロパティを上書きする必要がないため、またはテンプレートを使用せずに完全に独自の設定を行うために役立ちます。 + +警告 +この設定を変更すると、プロパティがリセットされることがあります。設定の一部が失われる可能性があります。 +この設定を変更した後、すべてがあなたの好きなように設定されていることを確認してください。 + + + フル + + + ジョブタグをカラーで表示し、プレイヤー名要素に色を付けます。 + + + + + + 設定が一つもありません。これは完全に空のテンプレートです。 +コントロール下にあるすべてのオプションを設定したい場合、またはいくつかの設定だけを作成したい場合は、これを使用します。 + + + シンプル + + + タイトルを置き換えることで、ジョブタグとロールアイコンをカラーで表示します。 + + + グレーアウト + + + 無視 + + + 含む + + + 死んだプレイヤーの処理 + + + 任意のタグを適用しますが、ネームプレートを灰色表示にします。 + + + 死んだプレイヤーは処理せず、タグも適用しない。 + + + 死んだプレイヤーも生きているのと同じように扱う。死んだプレイヤーと生きているプレイヤーの違いはありません。 + + + 可能であれば、ステータスアイコンをネームプレートのテキストに移動する。 + + + 現在のステータスアイコンがフォントアイコンとして利用できる場合、それをネームプレートのプレイヤー名のテキストに移動し、ジョブアイコンなどの別のアイコンを使用できるようにします。 + + + チャットにロールアイコンを表示 + + + 未定義のチャットタイプを含む + + + このタグを有効にすると、定義されていないすべてのチャットメッセージに適用されます。 +このケースは、ゲームがアップデートされ、すべてのチャットタイプの列挙がシフトされた値によって無効になった場合、またはプラグインが何らかの理由でカスタムチャットタイプを作成した場合に発生します。 + + \ No newline at end of file From bde3726ca98e61dd0116a28a653f1591753537cf Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 9 Jan 2023 06:17:46 +0100 Subject: [PATCH 171/174] adjust for API 8 --- PlayerTags/PlayerTags.csproj | 6 +++--- PlayerTags/packages.lock.json | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/PlayerTags/PlayerTags.csproj b/PlayerTags/PlayerTags.csproj index dd4d875..643e2a2 100644 --- a/PlayerTags/PlayerTags.csproj +++ b/PlayerTags/PlayerTags.csproj @@ -1,11 +1,11 @@  r00telement;Pilzinsel64 - 1.8.4.1 + 1.9.0.0 - net6.0-windows + net7.0-windows x64 annotations latest @@ -25,7 +25,7 @@ - + $(DalamudLibPath)FFXIVClientStructs.dll diff --git a/PlayerTags/packages.lock.json b/PlayerTags/packages.lock.json index d25458d..8c25d84 100644 --- a/PlayerTags/packages.lock.json +++ b/PlayerTags/packages.lock.json @@ -1,7 +1,7 @@ { "version": 1, "dependencies": { - "net6.0-windows7.0": { + "net7.0-windows7.0": { "Dalamud.ContextMenu": { "type": "Direct", "requested": "[1.2.1, )", @@ -10,9 +10,9 @@ }, "DalamudPackager": { "type": "Direct", - "requested": "[2.1.8, )", - "resolved": "2.1.8", - "contentHash": "YqagNXs9InxmqkXzq7kLveImxnodkBEicAhydMXVp7dFjC7xb76U6zGgAax4/BWIWfZeWzr5DJyQSev31kj81A==" + "requested": "[2.1.10, )", + "resolved": "2.1.10", + "contentHash": "S6NrvvOnLgT4GDdgwuKVJjbFo+8ZEj+JsEYk9ojjOR/MMfv1dIFpT8aRJQfI24rtDcw1uF+GnSSMN4WW1yt7fw==" }, "pilz.dalamud": { "type": "Project" From fa567b598553dc522397f1a4531ff5ccfc163566 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Mon, 9 Jan 2023 06:19:34 +0100 Subject: [PATCH 172/174] adjust for API8 also for Pilz.Dalamud (stupid Visual Studio didn't show this change :/) --- Pilz.Dalamud/Pilz.Dalamud.csproj | 6 ++---- Pilz.Dalamud/packages.lock.json | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Pilz.Dalamud/Pilz.Dalamud.csproj b/Pilz.Dalamud/Pilz.Dalamud.csproj index 540e7f5..262ee3e 100644 --- a/Pilz.Dalamud/Pilz.Dalamud.csproj +++ b/Pilz.Dalamud/Pilz.Dalamud.csproj @@ -1,7 +1,7 @@  - net6.0-windows + net7.0-windows enable annotations true @@ -23,9 +23,7 @@ https://github.com/Pilzinsel64/Pilz.Dalamud https://github.com/Pilzinsel64/Pilz.Dalamud git - 0.1.1.0 - 0.1.1.0 - 0.1.1 + 0.2.0 True diff --git a/Pilz.Dalamud/packages.lock.json b/Pilz.Dalamud/packages.lock.json index 8ee9f35..4ead528 100644 --- a/Pilz.Dalamud/packages.lock.json +++ b/Pilz.Dalamud/packages.lock.json @@ -1,6 +1,6 @@ { "version": 1, "dependencies": { - "net6.0-windows7.0": {} + "net7.0-windows7.0": {} } } \ No newline at end of file From c24d7f3ddb6c9ad020bcb64e20cad5cf826645b0 Mon Sep 17 00:00:00 2001 From: Pilzinsel64 Date: Wed, 11 Jan 2023 08:42:21 +0100 Subject: [PATCH 173/174] minimal polishing up --- PlayerTags/Configuration/PluginConfigurationUI.cs | 2 +- PlayerTags/Localizer.cs | 10 ++++------ PlayerTags/Plugin.cs | 8 +++----- PlayerTags/Resources/Strings.Designer.cs | 9 +++++++++ PlayerTags/Resources/Strings.resx | 3 +++ 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/PlayerTags/Configuration/PluginConfigurationUI.cs b/PlayerTags/Configuration/PluginConfigurationUI.cs index eceea73..4b10c34 100644 --- a/PlayerTags/Configuration/PluginConfigurationUI.cs +++ b/PlayerTags/Configuration/PluginConfigurationUI.cs @@ -1202,7 +1202,7 @@ private void DrawMultiselect(string localizedStringName, InheritableRefer var entryName = Enum.GetName(typeofEnum, entry.Value); var tempval = entry.Enabled; - isClicked = ImGui.Checkbox(Localizer.GetString(entryName), ref isDisabled ? ref tempval : ref entry.Enabled); + isClicked = ImGui.Checkbox(Localizer.GetString(entryName, false), ref isDisabled ? ref tempval : ref entry.Enabled); if (ImGui.IsItemHovered()) ImGui.SetTooltip(Localizer.GetString(entryName, true)); diff --git a/PlayerTags/Localizer.cs b/PlayerTags/Localizer.cs index 41a3f72..fffc28d 100644 --- a/PlayerTags/Localizer.cs +++ b/PlayerTags/Localizer.cs @@ -2,14 +2,13 @@ using Dalamud.Plugin; using PlayerTags.Resources; using System; +using System.ComponentModel; using System.Globalization; namespace PlayerTags { public static class Localizer { - private static CultureInfo culture = null; - public static void SetLanguage(string langCode) { SetLanguage(new CultureInfo(langCode)); @@ -17,7 +16,7 @@ public static void SetLanguage(string langCode) public static void SetLanguage(CultureInfo cultureInfo) { - culture = cultureInfo; + Strings.Culture = cultureInfo; } public static string GetName(TEnum value) @@ -51,11 +50,10 @@ public static string GetString(string localizedStringName, bool isDescription) public static string GetString(string localizedStringId) { - string? value = Strings.ResourceManager.GetString(localizedStringId, culture ?? Strings.Culture); + string? value = Strings.ResourceManager.GetString(localizedStringId, Strings.Culture); + if (value != null) - { return value; - } PluginLog.Error($"Failed to get localized string for id {localizedStringId}"); return localizedStringId; diff --git a/PlayerTags/Plugin.cs b/PlayerTags/Plugin.cs index a1d6d1a..2fc7d8c 100644 --- a/PlayerTags/Plugin.cs +++ b/PlayerTags/Plugin.cs @@ -40,10 +40,10 @@ public Plugin(DalamudPluginInterface pluginInterface) PluginServices.DalamudPluginInterface.UiBuilder.Draw += UiBuilder_Draw; PluginServices.DalamudPluginInterface.UiBuilder.OpenConfigUi += UiBuilder_OpenConfigUi; - PluginServices.CommandManager.AddHandler(c_CommandName, new CommandInfo((string command, string arguments) => + PluginServices.CommandManager.AddHandler(c_CommandName, new CommandInfo((string command, string arguments) => UiBuilder_OpenConfigUi()) { - UiBuilder_OpenConfigUi(); - }) { HelpMessage = "Shows the config" }); + HelpMessage = Resources.Strings.Loc_Command_playertags + }); m_CustomTagsContextMenuFeature = new CustomTagsContextMenuFeature(m_PluginConfiguration, m_PluginData); m_NameplatesTagTargetFeature = new NameplateTagTargetFeature(m_PluginConfiguration, m_PluginData); m_ChatTagTargetFeature = new ChatTagTargetFeature(m_PluginConfiguration, m_PluginData); @@ -68,9 +68,7 @@ private void DalamudPluginInterface_LanguageChanged(string langCode) private void UiBuilder_Draw() { if (m_PluginConfiguration.IsVisible) - { m_PluginConfigurationUI.Draw(); - } } private void UiBuilder_OpenConfigUi() diff --git a/PlayerTags/Resources/Strings.Designer.cs b/PlayerTags/Resources/Strings.Designer.cs index d14322a..907febf 100644 --- a/PlayerTags/Resources/Strings.Designer.cs +++ b/PlayerTags/Resources/Strings.Designer.cs @@ -186,6 +186,15 @@ public static string Loc_ChatFeatureCategory { } } + /// + /// Sucht eine lokalisierte Zeichenfolge, die Shows the config window for Player Tags ähnelt. + /// + public static string Loc_Command_playertags { + get { + return ResourceManager.GetString("Loc_Command_playertags", resourceCulture); + } + } + /// /// Sucht eine lokalisierte Zeichenfolge, die Custom id ähnelt. /// diff --git a/PlayerTags/Resources/Strings.resx b/PlayerTags/Resources/Strings.resx index 0850b13..96deaf9 100644 --- a/PlayerTags/Resources/Strings.resx +++ b/PlayerTags/Resources/Strings.resx @@ -829,4 +829,7 @@ Use this if you want to to have every option under your control or just want to When enabled the Tag will apply to all Chat messages that has not a defined type. This case can happen either if the Game updates and the Enumeration of all Chat Types gets invalid due to shifted values, or plugins creates a custom chat type for whatever reason. + + Shows the config window for Player Tags + \ No newline at end of file From ee1834618271b727e60b6f2c4cceda2c27522688 Mon Sep 17 00:00:00 2001 From: RaylaValdez Date: Fri, 13 Jan 2023 21:00:38 -0500 Subject: [PATCH 174/174] Update PlayerTags.json Added the "DalamudAPILevel": 8 tag required in order for dalamud to load plugin. should be good to push to testing :smile: --- PlayerTags/PlayerTags.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PlayerTags/PlayerTags.json b/PlayerTags/PlayerTags.json index 88fc079..b6aac56 100644 --- a/PlayerTags/PlayerTags.json +++ b/PlayerTags/PlayerTags.json @@ -5,5 +5,6 @@ "Punchline": "Lightweight job visibility in nameplates and chat.", "Tags": [ "Jobs", "UI" ], "CategoryTags": [ "jobs", "UI" ], - "RepoUrl": "https://github.com/Pilzinsel64/PlayerTags" + "RepoUrl": "https://github.com/Pilzinsel64/PlayerTags", + "DalamudAPILevel": 8 } \ No newline at end of file