Second pass with new config ui
This commit is contained in:
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29709.97
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlayerTags", "PlayerTags\PlayerTags.csproj", "{13C812E9-0D42-4B95-8646-40EEBF30636F}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlayerTags", "PlayerTags\PlayerTags.csproj", "{13C812E9-0D42-4B95-8646-40EEBF30636F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace PlayerTags.Config
|
||||
{
|
||||
public class CustomColorConfig
|
||||
{
|
||||
public ushort? Id = null;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace PlayerTags.Config
|
||||
{
|
||||
[Serializable]
|
||||
public class CustomTagConfig : TagConfig
|
||||
{
|
||||
public CustomColorConfig CustomColor = new CustomColorConfig();
|
||||
public string Name = "";
|
||||
public string FormattedGameObjectNames = "";
|
||||
|
||||
private string[] GameObjectNames
|
||||
{
|
||||
get
|
||||
{
|
||||
return FormattedGameObjectNames.Split(';').Select(gameObjectName => gameObjectName.ToLower().Trim()).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IncludesGameObjectName(string gameObjectName)
|
||||
{
|
||||
return GameObjectNames.Contains(gameObjectName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace PlayerTags.Config
|
||||
{
|
||||
public enum FreeCompanyNameplateVisibility
|
||||
{
|
||||
Default,
|
||||
Never
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace PlayerTags.Config
|
||||
{
|
||||
[Serializable]
|
||||
public class JobOverrideConfig
|
||||
{
|
||||
public CustomColorConfig CustomColor = new CustomColorConfig();
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
using Dalamud.Configuration;
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Plugin;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PlayerTags.Config
|
||||
{
|
||||
[Serializable]
|
||||
public class MainConfig : IPluginConfiguration
|
||||
{
|
||||
public static Dictionary<byte, Role> RolesById { get; } = new Dictionary<byte, Role>()
|
||||
{
|
||||
{ 0, Role.LandHand },
|
||||
{ 1, Role.Tank },
|
||||
{ 2, Role.DPS },
|
||||
{ 3, Role.DPS },
|
||||
{ 4, Role.Healer },
|
||||
};
|
||||
|
||||
public int Version { get; set; } = 0;
|
||||
|
||||
public FreeCompanyNameplateVisibility FreeCompanyVisibility = FreeCompanyNameplateVisibility.Default;
|
||||
public TitleNameplateVisibility TitleVisibility = TitleNameplateVisibility.Default;
|
||||
public TitleNameplatePosition TitlePosition = TitleNameplatePosition.Default;
|
||||
|
||||
public RoleTagConfig RoleTag = new RoleTagConfig();
|
||||
|
||||
public List<CustomTagConfig> CustomTagConfigs = new List<CustomTagConfig>();
|
||||
|
||||
public bool IsPlayerNameRandomlyGenerated = false;
|
||||
|
||||
[NonSerialized]
|
||||
private DalamudPluginInterface? m_PluginInterface;
|
||||
|
||||
public event System.Action? Saved;
|
||||
|
||||
public void Initialize(DalamudPluginInterface pluginInterface, DataManager dataManager)
|
||||
{
|
||||
m_PluginInterface = pluginInterface;
|
||||
|
||||
// Populate each role config with all of its jobs if they aren't already in it
|
||||
foreach (var roleConfigPair in RoleTag.RoleOverrideConfigs)
|
||||
{
|
||||
var role = roleConfigPair.Key;
|
||||
var roleConfig = roleConfigPair.Value;
|
||||
|
||||
var classJobs = dataManager.GetExcelSheet<ClassJob>();
|
||||
if (classJobs != null)
|
||||
{
|
||||
foreach (var classJob in classJobs.Where(classJob => RolesById[classJob.Role] == role))
|
||||
{
|
||||
if (!roleConfig.JobOverrideConfigs.ContainsKey(classJob.Abbreviation))
|
||||
{
|
||||
roleConfig.JobOverrideConfigs[classJob.Abbreviation] = new JobOverrideConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
if (m_PluginInterface != null)
|
||||
{
|
||||
m_PluginInterface.SavePluginConfig(this);
|
||||
Saved?.Invoke();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,403 +0,0 @@
|
||||
using Dalamud.Interface.Components;
|
||||
using Dalamud.Logging;
|
||||
using ImGuiNET;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using PlayerTags.Resources;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace PlayerTags.Config
|
||||
{
|
||||
public class MainConfigUI
|
||||
{
|
||||
private MainConfig m_Config;
|
||||
|
||||
private bool m_OpenPopupRequested;
|
||||
|
||||
private CustomColorConfig? m_ColorPickerPopupDataContext;
|
||||
|
||||
private bool m_IsVisible = false;
|
||||
public bool IsVisible
|
||||
{
|
||||
get { return m_IsVisible; }
|
||||
set { m_IsVisible = value; }
|
||||
}
|
||||
|
||||
public MainConfigUI(MainConfig config)
|
||||
{
|
||||
m_Config = config;
|
||||
}
|
||||
|
||||
private string GetLocString<TEnum>(bool isDescription)
|
||||
where TEnum : Enum
|
||||
{
|
||||
return GetLocString(typeof(TEnum).Name, isDescription);
|
||||
}
|
||||
|
||||
private string GetLocString<TEnum>(TEnum enumValue, bool isDescription)
|
||||
where TEnum : Enum
|
||||
{
|
||||
return GetLocString($"{typeof(TEnum).Name}_{enumValue}", isDescription);
|
||||
}
|
||||
|
||||
private string GetLocString(string locStringId, bool isDescription)
|
||||
{
|
||||
string completeLocStringId = $"Loc_{locStringId}";
|
||||
|
||||
if (isDescription)
|
||||
{
|
||||
completeLocStringId += "_Description";
|
||||
}
|
||||
|
||||
return GetLocString(completeLocStringId);
|
||||
}
|
||||
|
||||
private string GetLocString(string completeLocStringId)
|
||||
{
|
||||
string? value = Strings.ResourceManager.GetString(completeLocStringId, Strings.Culture);
|
||||
if (value != null)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
PluginLog.Error($"Failed to get localized string for id {completeLocStringId}");
|
||||
return completeLocStringId;
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
if (m_Config == null || !IsVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui.Begin(Strings.Loc_Static_PluginName, ref m_IsVisible))
|
||||
{
|
||||
if (ImGui.BeginTabBar("MainTabBar"))
|
||||
{
|
||||
if (ImGui.BeginTabItem(Strings.Loc_Static_General))
|
||||
{
|
||||
DrawHeading(Strings.Loc_Static_Nameplates);
|
||||
DrawEnumComboBox(
|
||||
ref m_Config.FreeCompanyVisibility,
|
||||
() => m_Config.Save());
|
||||
DrawEnumComboBox(
|
||||
ref m_Config.TitleVisibility,
|
||||
() => m_Config.Save());
|
||||
DrawEnumComboBox(
|
||||
ref m_Config.TitlePosition,
|
||||
() => m_Config.Save());
|
||||
DrawHeading(Strings.Loc_Static_Development);
|
||||
DrawCheckbox(
|
||||
nameof(m_Config.IsPlayerNameRandomlyGenerated),
|
||||
ref m_Config.IsPlayerNameRandomlyGenerated,
|
||||
() => m_Config.Save());
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui.BeginTabItem(Strings.Loc_Static_RoleAndJobTags))
|
||||
{
|
||||
DrawEnumComboBox(
|
||||
ref m_Config.RoleTag.Format,
|
||||
() => m_Config.Save());
|
||||
DrawTagConfig(m_Config.RoleTag);
|
||||
|
||||
DrawHeading(Strings.Loc_Static_Roles);
|
||||
if (ImGui.BeginTabBar("JobAndRolesTabBar"))
|
||||
{
|
||||
foreach (var rolePair in m_Config.RoleTag.RoleOverrideConfigs)
|
||||
{
|
||||
var role = rolePair.Key;
|
||||
var roleConfig = rolePair.Value;
|
||||
|
||||
if (ImGui.BeginTabItem(GetLocString($"{role.GetType().Name}_{role}", false)))
|
||||
{
|
||||
DrawCheckbox(
|
||||
$"{roleConfig.GetType().Name}_{nameof(roleConfig.IsEnabled)}",
|
||||
ref roleConfig.IsEnabled,
|
||||
() => m_Config.Save());
|
||||
DrawTextBox(
|
||||
$"{roleConfig.GetType().Name}_{nameof(roleConfig.Name)}",
|
||||
ref roleConfig.Name,
|
||||
() => m_Config.Save());
|
||||
DrawOptionalCustomColor(
|
||||
$"{roleConfig.CustomColor.GetType().Name}_IsEnabled",
|
||||
roleConfig.CustomColor.Id.ToString()!,
|
||||
roleConfig.CustomColor);
|
||||
DrawHeading(Strings.Loc_Static_Jobs);
|
||||
foreach (var key in roleConfig.JobOverrideConfigs.Keys.OrderBy(key => key))
|
||||
{
|
||||
if (string.IsNullOrEmpty(key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
JobOverrideConfig jobConfig = roleConfig.JobOverrideConfigs[key];
|
||||
|
||||
ImGui.Columns(2, "columns", false);
|
||||
ImGui.SetColumnWidth(0, 42);
|
||||
ImGui.Text(key);
|
||||
ImGui.NextColumn();
|
||||
DrawOptionalCustomColor(
|
||||
$"{roleConfig.CustomColor.GetType().Name}_IsEnabled",
|
||||
key,
|
||||
jobConfig.CustomColor);
|
||||
|
||||
ImGui.Columns();
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndTabBar();
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui.BeginTabItem(Strings.Loc_Static_CustomTags))
|
||||
{
|
||||
if (ImGui.Button(Strings.Loc_Static_AddCustomTag))
|
||||
{
|
||||
m_Config.CustomTagConfigs.Add(new CustomTagConfig());
|
||||
m_Config.Save();
|
||||
}
|
||||
|
||||
if (!m_Config.CustomTagConfigs.Any())
|
||||
{
|
||||
ImGui.Text(Strings.Loc_Static_NoCustomTagsAdded);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var customTagConfig in m_Config.CustomTagConfigs.ToArray())
|
||||
{
|
||||
ImGui.PushID(customTagConfig.GetHashCode().ToString());
|
||||
ImGui.Separator();
|
||||
DrawTextBox(
|
||||
$"{customTagConfig.GetType().Name}_{nameof(customTagConfig.Name)}",
|
||||
ref customTagConfig.Name,
|
||||
() => { m_Config.Save(); });
|
||||
DrawOptionalCustomColor(
|
||||
$"{customTagConfig.CustomColor.GetType().Name}_IsEnabled",
|
||||
customTagConfig.CustomColor.Id.ToString()!,
|
||||
customTagConfig.CustomColor);
|
||||
DrawTextBox(
|
||||
$"{customTagConfig.GetType().Name}_{nameof(customTagConfig.FormattedGameObjectNames)}",
|
||||
ref customTagConfig.FormattedGameObjectNames,
|
||||
() => { m_Config.Save(); });
|
||||
DrawTagConfig(customTagConfig);
|
||||
ImGui.Spacing();
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, new Vector4(0.4f, 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));
|
||||
if (ImGui.Button(Strings.Loc_Static_RemoveCustomTag))
|
||||
{
|
||||
m_Config.CustomTagConfigs.Remove(customTagConfig);
|
||||
m_Config.Save();
|
||||
}
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PopID();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
|
||||
ImGui.EndTabBar();
|
||||
}
|
||||
|
||||
if (m_OpenPopupRequested == true)
|
||||
{
|
||||
m_OpenPopupRequested = false;
|
||||
ImGui.OpenPopup("ColorPickerPopup");
|
||||
}
|
||||
|
||||
ImGui.SetNextWindowSize(new Vector2(400, 284));
|
||||
if (ImGui.BeginPopup("ColorPickerPopup"))
|
||||
{
|
||||
DrawUIColorPicker(
|
||||
(UIColor value) =>
|
||||
{
|
||||
if (m_ColorPickerPopupDataContext != null)
|
||||
{
|
||||
m_ColorPickerPopupDataContext.Id = (ushort)value.RowId;
|
||||
m_ColorPickerPopupDataContext = null;
|
||||
m_Config.Save();
|
||||
}
|
||||
|
||||
ImGui.CloseCurrentPopup();
|
||||
});
|
||||
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
|
||||
ImGui.End();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTagConfig(TagConfig tagConfig)
|
||||
{
|
||||
if (m_Config == null || !IsVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DrawHeading(Strings.Loc_Static_ChatTag);
|
||||
ImGui.PushID("Chat");
|
||||
DrawEnumComboBox(
|
||||
ref tagConfig.ChatPosition,
|
||||
() => m_Config.Save());
|
||||
ImGui.PopID();
|
||||
DrawHeading(Strings.Loc_Static_NameplateTag);
|
||||
ImGui.PushID("Nameplate");
|
||||
DrawEnumComboBox(
|
||||
ref tagConfig.NameplatePosition,
|
||||
() => m_Config.Save());
|
||||
DrawEnumComboBox(
|
||||
ref tagConfig.NameplateElement,
|
||||
() => m_Config.Save());
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
||||
private void DrawOptionalCustomColor(string locStringId, string colorId, CustomColorConfig customColorConfig)
|
||||
{
|
||||
if (customColorConfig.Id.HasValue)
|
||||
{
|
||||
DrawColorButton(
|
||||
colorId,
|
||||
UIColorHelper.ToColor(customColorConfig.Id.Value),
|
||||
() =>
|
||||
{
|
||||
m_ColorPickerPopupDataContext = customColorConfig;
|
||||
m_OpenPopupRequested = true;
|
||||
});
|
||||
|
||||
ImGui.SameLine();
|
||||
}
|
||||
|
||||
var isChecked = customColorConfig.Id != null;
|
||||
DrawCheckbox(
|
||||
locStringId,
|
||||
ref isChecked,
|
||||
() =>
|
||||
{
|
||||
if (!isChecked)
|
||||
{
|
||||
customColorConfig.Id = null;
|
||||
m_Config.Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
customColorConfig.Id = (ushort)UIColorHelper.UIColors.First().RowId;
|
||||
m_Config.Save();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void DrawSeparator()
|
||||
{
|
||||
ImGui.Spacing();
|
||||
ImGui.Spacing();
|
||||
ImGui.Spacing();
|
||||
ImGui.Spacing();
|
||||
}
|
||||
|
||||
private void DrawHeading(string label)
|
||||
{
|
||||
ImGui.TextColored(new Vector4(0.7f, 0.6f, 1f, 1f), label);
|
||||
}
|
||||
|
||||
private void DrawEnumComboBox<TEnum>(ref TEnum currentValue, System.Action changed)
|
||||
where TEnum : Enum
|
||||
{
|
||||
ImGui.Text(GetLocString<TEnum>(false));
|
||||
ImGuiComponents.HelpMarker(GetLocString<TEnum>(true));
|
||||
|
||||
if (ImGui.BeginCombo($"###{currentValue.GetType().Name}", GetLocString(currentValue, false)))
|
||||
{
|
||||
foreach (string enumValueString in typeof(TEnum).GetEnumNames())
|
||||
{
|
||||
TEnum enumValue = (TEnum)Enum.Parse(typeof(TEnum), enumValueString);
|
||||
bool isSelected = enumValueString == currentValue.ToString();
|
||||
if (ImGui.Selectable($"{GetLocString(enumValue, false)}###{enumValueString}", isSelected))
|
||||
{
|
||||
currentValue = (TEnum)Enum.Parse(typeof(TEnum), enumValueString);
|
||||
ImGui.SetItemDefaultFocus();
|
||||
changed();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetTooltip(GetLocString(enumValue, true));
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetTooltip(GetLocString(currentValue, true));
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCheckbox(string locStringId, ref bool isChecked, System.Action changed)
|
||||
{
|
||||
if (ImGui.Checkbox(GetLocString(locStringId, false), ref isChecked))
|
||||
{
|
||||
changed();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetTooltip(GetLocString(locStringId, true));
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawColorButton(string colorId, Vector4 color, System.Action clicked)
|
||||
{
|
||||
if (ImGui.ColorButton(colorId, color))
|
||||
{
|
||||
clicked();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTextBox(string locStringId, ref string text, System.Action changed)
|
||||
{
|
||||
ImGui.Text(GetLocString(locStringId, false));
|
||||
ImGuiComponents.HelpMarker(GetLocString(locStringId, true));
|
||||
|
||||
var oldText = text;
|
||||
ImGui.InputText($"###{locStringId}", ref text, 1024);
|
||||
if (text != oldText)
|
||||
{
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawUIColorPicker(System.Action<UIColor> clicked)
|
||||
{
|
||||
ImGui.PushID(clicked.GetHashCode());
|
||||
ImGui.Columns(12, "columns", false);
|
||||
foreach (var uiColor in UIColorHelper.UIColors)
|
||||
{
|
||||
DrawColorButton(
|
||||
uiColor.RowId.ToString(),
|
||||
UIColorHelper.ToColor(uiColor),
|
||||
() =>
|
||||
{
|
||||
clicked(uiColor);
|
||||
});
|
||||
|
||||
ImGui.NextColumn();
|
||||
}
|
||||
ImGui.Columns();
|
||||
ImGui.PopID();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PlayerTags.Config
|
||||
{
|
||||
[Serializable]
|
||||
public class RoleOverrideConfig
|
||||
{
|
||||
public bool IsEnabled = true;
|
||||
public string Name = "";
|
||||
public CustomColorConfig CustomColor = new CustomColorConfig();
|
||||
public Dictionary<string, JobOverrideConfig> JobOverrideConfigs = new Dictionary<string, JobOverrideConfig>();
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PlayerTags.Config
|
||||
{
|
||||
[Serializable]
|
||||
public class RoleTagConfig : TagConfig
|
||||
{
|
||||
public RoleTagFormat Format = RoleTagFormat.AbbreviatedJobName;
|
||||
|
||||
public Dictionary<Role, RoleOverrideConfig> RoleOverrideConfigs = new Dictionary<Role, RoleOverrideConfig>()
|
||||
{
|
||||
{ Role.LandHand, new RoleOverrideConfig() { IsEnabled = true, Name = "Land/Hand", CustomColor = new CustomColorConfig() { Id = 3 } } },
|
||||
{ Role.Tank, new RoleOverrideConfig() { IsEnabled = true, Name = "Tank", CustomColor = new CustomColorConfig() { Id = 542 } } },
|
||||
{ Role.Healer, new RoleOverrideConfig() { IsEnabled = true, Name = "Healer", CustomColor = new CustomColorConfig() { Id = 45 } } },
|
||||
{ Role.DPS, new RoleOverrideConfig() { IsEnabled = true, Name = "DPS", CustomColor = new CustomColorConfig() { Id = 511 } } },
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace PlayerTags.Config
|
||||
{
|
||||
public enum RoleTagFormat
|
||||
{
|
||||
AbbreviatedJobName,
|
||||
JobName,
|
||||
RoleName
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace PlayerTags.Config
|
||||
{
|
||||
public enum StringPosition
|
||||
{
|
||||
None,
|
||||
Before,
|
||||
After,
|
||||
Replace
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace PlayerTags.Config
|
||||
{
|
||||
[Serializable]
|
||||
public class TagConfig
|
||||
{
|
||||
public NameplateElement NameplateElement = NameplateElement.Name;
|
||||
|
||||
public StringPosition NameplatePosition = StringPosition.Before;
|
||||
|
||||
public StringPosition ChatPosition = StringPosition.Before;
|
||||
}
|
||||
}
|
||||
97
PlayerTags/DefaultPluginData.cs
Normal file
97
PlayerTags/DefaultPluginData.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PlayerTags
|
||||
{
|
||||
public class DefaultPluginData
|
||||
{
|
||||
public Dictionary<byte, Role> RolesById { get; } = new Dictionary<byte, Role>()
|
||||
{
|
||||
{ 0, Role.LandHand },
|
||||
{ 1, Role.Tank },
|
||||
{ 2, Role.DPS },
|
||||
{ 3, Role.DPS },
|
||||
{ 4, Role.Healer },
|
||||
};
|
||||
|
||||
public Dictionary<string, Role> RolesByJobAbbreviation { get; } = new Dictionary<string, Role>();
|
||||
|
||||
public Dictionary<string, InheritableData> AllTagsChanges = new Dictionary<string, InheritableData>();
|
||||
public Dictionary<string, InheritableData> AllRoleTagsChanges = new Dictionary<string, InheritableData>();
|
||||
public Dictionary<Role, Dictionary<string, InheritableData>> RoleTagsChanges = new Dictionary<Role, Dictionary<string, InheritableData>>();
|
||||
public Dictionary<string, Dictionary<string, InheritableData>> JobTagsChanges = new Dictionary<string, Dictionary<string, InheritableData>>();
|
||||
public Dictionary<string, InheritableData> AllCustomTagsChanges = new Dictionary<string, InheritableData>();
|
||||
|
||||
public void Initialize(DataManager dataManager)
|
||||
{
|
||||
AllTagsChanges = new Tag(new LiteralPluginString(""))
|
||||
{
|
||||
TagPositionInChat = TagPosition.Before,
|
||||
TagPositionInNameplates = TagPosition.Replace,
|
||||
TagTargetInNameplates = NameplateElement.Title,
|
||||
IsTextItalic = true,
|
||||
}.GetChanges();
|
||||
|
||||
AllRoleTagsChanges = new Tag(new LiteralPluginString(""))
|
||||
{
|
||||
IsIconVisibleInChat = true,
|
||||
IsTextVisibleInNameplates = true,
|
||||
}.GetChanges();
|
||||
|
||||
RoleTagsChanges[Role.LandHand] = new Tag(new LiteralPluginString(""))
|
||||
{
|
||||
Icon = BitmapFontIcon.Crafter,
|
||||
TextColor = 3,
|
||||
}.GetChanges();
|
||||
|
||||
RoleTagsChanges[Role.Tank] = new Tag(new LiteralPluginString(""))
|
||||
{
|
||||
Icon = BitmapFontIcon.Tank,
|
||||
TextColor = 546,
|
||||
}.GetChanges();
|
||||
|
||||
RoleTagsChanges[Role.Healer] = new Tag(new LiteralPluginString(""))
|
||||
{
|
||||
Icon = BitmapFontIcon.Healer,
|
||||
TextColor = 43,
|
||||
}.GetChanges();
|
||||
|
||||
RoleTagsChanges[Role.DPS] = new Tag(new LiteralPluginString(""))
|
||||
{
|
||||
Icon = BitmapFontIcon.DPS,
|
||||
TextColor = 508,
|
||||
}.GetChanges();
|
||||
|
||||
foreach ((var role, var roleTagChanges) in RoleTagsChanges)
|
||||
{
|
||||
var classJobs = dataManager.GetExcelSheet<ClassJob>();
|
||||
if (classJobs == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (var classJob in classJobs.Where(classJob => RolesById[classJob.Role] == role && !string.IsNullOrEmpty(classJob.Abbreviation.RawString)))
|
||||
{
|
||||
RolesByJobAbbreviation[classJob.Abbreviation.RawString] = role;
|
||||
|
||||
if (!JobTagsChanges.ContainsKey(classJob.Abbreviation.RawString))
|
||||
{
|
||||
JobTagsChanges[classJob.Abbreviation.RawString] = new Tag(new LiteralPluginString(""))
|
||||
{
|
||||
Text = classJob.Abbreviation.RawString,
|
||||
}.GetChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AllCustomTagsChanges = new Tag(new LiteralPluginString(""))
|
||||
{
|
||||
IsTextVisibleInChat = true,
|
||||
IsTextVisibleInNameplates = true,
|
||||
}.GetChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
30
PlayerTags/GeneralConverter.cs
Normal file
30
PlayerTags/GeneralConverter.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
13
PlayerTags/IInheritable.cs
Normal file
13
PlayerTags/IInheritable.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace PlayerTags
|
||||
{
|
||||
public interface IInheritable
|
||||
{
|
||||
public IInheritable? Parent { get; set; }
|
||||
|
||||
public InheritableBehavior Behavior { get; set; }
|
||||
|
||||
public abstract void SetData(InheritableData inheritableData);
|
||||
|
||||
public abstract InheritableData GetData();
|
||||
}
|
||||
}
|
||||
7
PlayerTags/IPluginString.cs
Normal file
7
PlayerTags/IPluginString.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace PlayerTags
|
||||
{
|
||||
public interface IPluginString
|
||||
{
|
||||
public string Value { get; }
|
||||
}
|
||||
}
|
||||
9
PlayerTags/InheritableBehavior.cs
Normal file
9
PlayerTags/InheritableBehavior.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace PlayerTags
|
||||
{
|
||||
public enum InheritableBehavior
|
||||
{
|
||||
Inherit,
|
||||
Enabled,
|
||||
Disabled
|
||||
}
|
||||
}
|
||||
17
PlayerTags/InheritableData.cs
Normal file
17
PlayerTags/InheritableData.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using System;
|
||||
|
||||
namespace PlayerTags
|
||||
{
|
||||
[Serializable]
|
||||
public struct InheritableData
|
||||
{
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
[JsonProperty("Behavior")]
|
||||
public InheritableBehavior Behavior;
|
||||
[JsonProperty("Value")]
|
||||
[JsonConverter(typeof(GeneralConverter))]
|
||||
public object Value;
|
||||
}
|
||||
}
|
||||
60
PlayerTags/InheritableReference.cs
Normal file
60
PlayerTags/InheritableReference.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
namespace PlayerTags
|
||||
{
|
||||
public class InheritableReference<T> : IInheritable
|
||||
where T : class
|
||||
{
|
||||
public IInheritable? Parent { get; set; }
|
||||
|
||||
public InheritableBehavior Behavior { get; set; }
|
||||
|
||||
public T Value;
|
||||
|
||||
public T? InheritedValue
|
||||
{
|
||||
get
|
||||
{
|
||||
IInheritable? current = this;
|
||||
while (current != null)
|
||||
{
|
||||
if (current.Behavior == InheritableBehavior.Enabled && current is InheritableReference<T> currentOfSameType)
|
||||
{
|
||||
return currentOfSameType.Value;
|
||||
}
|
||||
else if (current.Behavior == InheritableBehavior.Disabled)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator InheritableReference<T>(T value) => new InheritableReference<T>(value)
|
||||
{
|
||||
Behavior = InheritableBehavior.Enabled
|
||||
};
|
||||
|
||||
public InheritableReference(T value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public void SetData(InheritableData inheritableData)
|
||||
{
|
||||
Behavior = inheritableData.Behavior;
|
||||
Value = (T)inheritableData.Value;
|
||||
}
|
||||
|
||||
public InheritableData GetData()
|
||||
{
|
||||
return new InheritableData
|
||||
{
|
||||
Behavior = Behavior,
|
||||
Value = Value
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
90
PlayerTags/InheritableValue.cs
Normal file
90
PlayerTags/InheritableValue.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using Dalamud.Logging;
|
||||
using System;
|
||||
|
||||
namespace PlayerTags
|
||||
{
|
||||
public class InheritableValue<T> : IInheritable
|
||||
where T : struct
|
||||
{
|
||||
public IInheritable? Parent { get; set; }
|
||||
|
||||
public InheritableBehavior Behavior { get; set; }
|
||||
|
||||
public T Value;
|
||||
|
||||
public T? InheritedValue
|
||||
{
|
||||
get
|
||||
{
|
||||
IInheritable? current = this;
|
||||
while (current != null)
|
||||
{
|
||||
if (current.Behavior == InheritableBehavior.Enabled && current is InheritableValue<T> currentOfSameType)
|
||||
{
|
||||
return currentOfSameType.Value;
|
||||
}
|
||||
else if (current.Behavior == InheritableBehavior.Disabled)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator InheritableValue<T>(T value) => new InheritableValue<T>(value)
|
||||
{
|
||||
Behavior = InheritableBehavior.Enabled
|
||||
};
|
||||
|
||||
public InheritableValue(T value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public void SetData(InheritableData inheritableData)
|
||||
{
|
||||
Behavior = inheritableData.Behavior;
|
||||
|
||||
try
|
||||
{
|
||||
if (typeof(T).IsEnum && inheritableData.Value != null)
|
||||
{
|
||||
if (inheritableData.Value is string stringValue)
|
||||
{
|
||||
Value = (T)Enum.Parse(typeof(T), stringValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = (T)Enum.ToObject(typeof(T), inheritableData.Value);
|
||||
}
|
||||
}
|
||||
else if (inheritableData.Value == null)
|
||||
{
|
||||
// This should never happen
|
||||
PluginLog.Error($"Expected value of type {Value.GetType()} but received null");
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = (T)Convert.ChangeType(inheritableData.Value, typeof(T));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.Error(ex, $"Failed to convert {inheritableData.Value.GetType()} value '{inheritableData.Value}' to {Value.GetType()}");
|
||||
}
|
||||
}
|
||||
|
||||
public InheritableData GetData()
|
||||
{
|
||||
return new InheritableData
|
||||
{
|
||||
Behavior = Behavior,
|
||||
Value = Value
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
18
PlayerTags/LiteralPluginString.cs
Normal file
18
PlayerTags/LiteralPluginString.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace PlayerTags
|
||||
{
|
||||
public class LiteralPluginString : IPluginString
|
||||
{
|
||||
private string m_Value;
|
||||
public string Value => m_Value;
|
||||
|
||||
public LiteralPluginString(string value)
|
||||
{
|
||||
m_Value = value;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
PlayerTags/LocalizedPluginString.cs
Normal file
18
PlayerTags/LocalizedPluginString.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace PlayerTags
|
||||
{
|
||||
public class LocalizedPluginString : IPluginString
|
||||
{
|
||||
public string Key { get; init; }
|
||||
public string Value => Localizer.GetString(Key, false);
|
||||
|
||||
public LocalizedPluginString(string key)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
PlayerTags/Localizer.cs
Normal file
50
PlayerTags/Localizer.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using Dalamud.Logging;
|
||||
using PlayerTags.Resources;
|
||||
using System;
|
||||
|
||||
namespace PlayerTags
|
||||
{
|
||||
public static class Localizer
|
||||
{
|
||||
public static string GetName<TEnum>(TEnum value)
|
||||
{
|
||||
return $"{typeof(TEnum).Name}_{value}";
|
||||
}
|
||||
|
||||
public static string GetString<TEnum>(bool isDescription)
|
||||
where TEnum : Enum
|
||||
{
|
||||
return GetString(typeof(TEnum).Name, isDescription);
|
||||
}
|
||||
|
||||
public static string GetString<TEnum>(TEnum value, bool isDescription)
|
||||
where TEnum : Enum
|
||||
{
|
||||
return GetString(GetName(value), isDescription);
|
||||
}
|
||||
|
||||
public static string GetString(string localizedStringName, bool isDescription)
|
||||
{
|
||||
string localizedStringId = $"Loc_{localizedStringName}";
|
||||
|
||||
if (isDescription)
|
||||
{
|
||||
localizedStringId += "_Description";
|
||||
}
|
||||
|
||||
return GetString(localizedStringId);
|
||||
}
|
||||
|
||||
public static string GetString(string localizedStringId)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PlayerTags.Config
|
||||
namespace PlayerTags
|
||||
{
|
||||
public enum NameplateElement
|
||||
{
|
||||
8
PlayerTags/NameplateFreeCompanyVisibility.cs
Normal file
8
PlayerTags/NameplateFreeCompanyVisibility.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace PlayerTags
|
||||
{
|
||||
public enum NameplateFreeCompanyVisibility
|
||||
{
|
||||
Default,
|
||||
Never
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace PlayerTags.Config
|
||||
namespace PlayerTags
|
||||
{
|
||||
public enum TitleNameplatePosition
|
||||
public enum NameplateTitlePosition
|
||||
{
|
||||
Default,
|
||||
AlwaysAboveName,
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace PlayerTags.Config
|
||||
namespace PlayerTags
|
||||
{
|
||||
public enum TitleNameplateVisibility
|
||||
public enum NameplateTitleVisibility
|
||||
{
|
||||
Default,
|
||||
Always,
|
||||
@@ -3,9 +3,10 @@
|
||||
"Name": "Player Tags",
|
||||
"Description": "See tags for players in nameplates and chat, such as their role and job, or custom tags for players you know.",
|
||||
"RepoUrl": "https://github.com/r00telement/PlayerTags",
|
||||
"IconUrl": "https://github.com/r00telement/PlayerTags/raw/main/PlayerTags/Resources/Promo/Chat_1.png",
|
||||
"IconUrl": "https://github.com/r00telement/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/r00telement/PlayerTags/raw/main/PlayerTags/Resources/Promo/Nameplates_1.png"
|
||||
"https://github.com/r00telement/PlayerTags/raw/main/PlayerTags/Resources/Promo/Chat_2.png"
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Game;
|
||||
using Dalamud.Game.ClientState;
|
||||
using Dalamud.Game.ClientState.Objects;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Game.Command;
|
||||
@@ -10,7 +11,6 @@ using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Plugin;
|
||||
using PlayerTags.Config;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -44,80 +44,114 @@ namespace PlayerTags
|
||||
[PluginService]
|
||||
private static CommandManager CommandManager { get; set; } = null!;
|
||||
|
||||
private MainConfig m_Config;
|
||||
[PluginService]
|
||||
private static ClientState ClientState { get; set; } = null!;
|
||||
|
||||
private MainConfigUI m_ConfigUI;
|
||||
private PluginConfiguration m_PluginConfiguration;
|
||||
|
||||
private Dictionary<string, Payload[]> m_JobTagPayloads = new Dictionary<string, Payload[]>();
|
||||
private PluginConfigurationUI m_PluginConfigurationUI;
|
||||
|
||||
private Dictionary<CustomTagConfig, Payload[]> m_CustomTagPayloads = new Dictionary<CustomTagConfig, Payload[]>();
|
||||
private RandomNameGenerator m_RandomNameGenerator = new RandomNameGenerator();
|
||||
|
||||
private PluginHooks? m_PluginHooks = null;
|
||||
|
||||
private Dictionary<Tag, Dictionary<TagTarget, Payload[]>> m_TagTargetPayloads = new Dictionary<Tag, Dictionary<TagTarget, Payload[]>>();
|
||||
|
||||
private TextPayload m_SpaceTextPayload = new TextPayload($" ");
|
||||
|
||||
private PluginHooks m_PluginHooks;
|
||||
|
||||
private RandomNameGenerator? m_RandomNameGenerator = null;
|
||||
private PluginData m_PluginData = new PluginData();
|
||||
|
||||
public Plugin()
|
||||
{
|
||||
UIColorHelper.Initialize(DataManager);
|
||||
m_PluginConfiguration = PluginInterface.GetPluginConfig() as PluginConfiguration ?? new PluginConfiguration();
|
||||
m_PluginConfiguration.Initialize(PluginInterface);
|
||||
m_PluginData.Initialize(DataManager, m_PluginConfiguration);
|
||||
m_PluginConfigurationUI = new PluginConfigurationUI(m_PluginConfiguration, m_PluginData);
|
||||
|
||||
m_Config = PluginInterface.GetPluginConfig() as MainConfig ?? new MainConfig();
|
||||
m_Config.Initialize(PluginInterface, DataManager);
|
||||
m_Config.Saved += Configuration_Saved;
|
||||
|
||||
m_ConfigUI = new MainConfigUI(m_Config);
|
||||
|
||||
ClientState.Login += ClientState_Login;
|
||||
ClientState.Logout += ClientState_Logout;
|
||||
ClientState.TerritoryChanged += ClientState_TerritoryChanged;
|
||||
ChatGui.ChatMessage += Chat_ChatMessage;
|
||||
PluginInterface.UiBuilder.Draw += UiBuilder_Draw;
|
||||
PluginInterface.UiBuilder.OpenConfigUi += UiBuilder_OpenConfigUi;
|
||||
m_PluginConfiguration.Saved += PluginConfiguration_Saved;
|
||||
CommandManager.AddHandler(c_CommandName, new CommandInfo((string command, string arguments) =>
|
||||
{
|
||||
m_ConfigUI.IsVisible = true;
|
||||
m_PluginConfiguration.IsVisible = true;
|
||||
m_PluginConfiguration.Save(m_PluginData);
|
||||
})
|
||||
{
|
||||
HelpMessage = "Shows the config"
|
||||
});
|
||||
|
||||
PluginInterface.UiBuilder.Draw += UiBuilder_Draw;
|
||||
PluginInterface.UiBuilder.OpenConfigUi += UiBuilder_OpenConfigUi;
|
||||
|
||||
m_PluginHooks = new PluginHooks(Framework, ObjectTable, GameGui, SetNameplate);
|
||||
|
||||
ChatGui.ChatMessage += Chat_ChatMessage;
|
||||
|
||||
if (m_Config.IsPlayerNameRandomlyGenerated && m_RandomNameGenerator == null)
|
||||
{
|
||||
m_RandomNameGenerator = new RandomNameGenerator();
|
||||
}
|
||||
Hook();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
PluginInterface.UiBuilder.OpenConfigUi -= UiBuilder_OpenConfigUi;
|
||||
Unhook();
|
||||
CommandManager.RemoveHandler(c_CommandName);
|
||||
m_PluginConfiguration.Saved -= PluginConfiguration_Saved;
|
||||
PluginInterface.UiBuilder.OpenConfigUi -= UiBuilder_OpenConfigUi;
|
||||
PluginInterface.UiBuilder.Draw -= UiBuilder_Draw;
|
||||
ChatGui.ChatMessage -= Chat_ChatMessage;
|
||||
m_Config.Saved -= Configuration_Saved;
|
||||
m_PluginHooks?.Dispose();
|
||||
ClientState.TerritoryChanged -= ClientState_TerritoryChanged;
|
||||
ClientState.Logout -= ClientState_Logout;
|
||||
ClientState.Login -= ClientState_Login;
|
||||
}
|
||||
|
||||
private void Configuration_Saved()
|
||||
private void Hook()
|
||||
{
|
||||
if (m_PluginHooks == null)
|
||||
{
|
||||
m_PluginHooks = new PluginHooks(Framework, ObjectTable, GameGui, SetNameplate);
|
||||
}
|
||||
}
|
||||
|
||||
private void Unhook()
|
||||
{
|
||||
if (m_PluginHooks != null)
|
||||
{
|
||||
m_PluginHooks.Dispose();
|
||||
m_PluginHooks = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void Rehook()
|
||||
{
|
||||
Unhook();
|
||||
Hook();
|
||||
}
|
||||
|
||||
private void ClientState_Login(object? sender, EventArgs e)
|
||||
{
|
||||
Hook();
|
||||
}
|
||||
|
||||
private void ClientState_Logout(object? sender, EventArgs e)
|
||||
{
|
||||
Unhook();
|
||||
}
|
||||
|
||||
private void ClientState_TerritoryChanged(object? sender, ushort e)
|
||||
{
|
||||
Rehook();
|
||||
}
|
||||
|
||||
private void PluginConfiguration_Saved()
|
||||
{
|
||||
// Invalidate the cached payloads so they get remade
|
||||
m_JobTagPayloads.Clear();
|
||||
m_CustomTagPayloads.Clear();
|
||||
|
||||
if (m_Config.IsPlayerNameRandomlyGenerated && m_RandomNameGenerator == null)
|
||||
{
|
||||
m_RandomNameGenerator = new RandomNameGenerator();
|
||||
}
|
||||
m_TagTargetPayloads.Clear();
|
||||
}
|
||||
|
||||
private void UiBuilder_Draw()
|
||||
{
|
||||
m_ConfigUI.Draw();
|
||||
m_PluginConfigurationUI.Draw();
|
||||
}
|
||||
|
||||
private void UiBuilder_OpenConfigUi()
|
||||
{
|
||||
m_ConfigUI.IsVisible = true;
|
||||
m_PluginConfiguration.IsVisible = true;
|
||||
}
|
||||
|
||||
private void Chat_ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled)
|
||||
@@ -143,105 +177,101 @@ namespace PlayerTags
|
||||
{
|
||||
AddTagsToNameplate(gameObject, name, title, freeCompany, out isNameChanged, out isTitleChanged, out isFreeCompanyChanged);
|
||||
|
||||
if (m_Config.TitlePosition == TitleNameplatePosition.AlwaysAboveName)
|
||||
if (m_PluginConfiguration.NameplateTitlePosition == NameplateTitlePosition.AlwaysAboveName)
|
||||
{
|
||||
isTitleAboveName = true;
|
||||
}
|
||||
else if (m_Config.TitlePosition == TitleNameplatePosition.AlwaysBelowName)
|
||||
else if (m_PluginConfiguration.NameplateTitlePosition == NameplateTitlePosition.AlwaysBelowName)
|
||||
{
|
||||
isTitleAboveName = false;
|
||||
}
|
||||
|
||||
if (m_Config.TitleVisibility == TitleNameplateVisibility.Default)
|
||||
if (m_PluginConfiguration.NameplateTitleVisibility == NameplateTitleVisibility.Default)
|
||||
{
|
||||
}
|
||||
else if (m_Config.TitleVisibility == TitleNameplateVisibility.Always)
|
||||
else if (m_PluginConfiguration.NameplateTitleVisibility == NameplateTitleVisibility.Always)
|
||||
{
|
||||
isTitleVisible = true;
|
||||
}
|
||||
else if (m_Config.TitleVisibility == TitleNameplateVisibility.Never)
|
||||
else if (m_PluginConfiguration.NameplateTitleVisibility == NameplateTitleVisibility.Never)
|
||||
{
|
||||
isTitleVisible = false;
|
||||
}
|
||||
else if (m_Config.TitleVisibility == TitleNameplateVisibility.WhenHasTags)
|
||||
else if (m_PluginConfiguration.NameplateTitleVisibility == NameplateTitleVisibility.WhenHasTags)
|
||||
{
|
||||
isTitleVisible = isTitleChanged;
|
||||
}
|
||||
|
||||
if (m_Config.FreeCompanyVisibility == FreeCompanyNameplateVisibility.Default)
|
||||
if (m_PluginConfiguration.NameplateFreeCompanyVisibility == NameplateFreeCompanyVisibility.Default)
|
||||
{
|
||||
}
|
||||
else if (m_Config.FreeCompanyVisibility == FreeCompanyNameplateVisibility.Never)
|
||||
else if (m_PluginConfiguration.NameplateFreeCompanyVisibility == NameplateFreeCompanyVisibility.Never)
|
||||
{
|
||||
freeCompany.Payloads.Clear();
|
||||
isFreeCompanyChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the job tag payloads for the given character. If the payloads don't yet exist then they are created.
|
||||
/// </summary>
|
||||
/// <param name="character">The character to get job tag payloads for.</param>
|
||||
/// <returns>A list of job tag payloads for the given character.</returns>
|
||||
private IEnumerable<Payload> GetJobTagPayloads(Character character)
|
||||
private Payload[] CreateTagPayloads(TagTarget tagTarget, Tag tag)
|
||||
{
|
||||
var roleId = character.ClassJob.GameData.Role;
|
||||
var jobAbbreviation = character.ClassJob.GameData.Abbreviation;
|
||||
var role = MainConfig.RolesById[roleId];
|
||||
|
||||
var roleConfig = m_Config.RoleTag.RoleOverrideConfigs[role];
|
||||
if (!roleConfig.IsEnabled)
|
||||
{
|
||||
return new Payload[] { };
|
||||
}
|
||||
|
||||
if (m_JobTagPayloads.TryGetValue(jobAbbreviation, out var payloads))
|
||||
{
|
||||
return payloads;
|
||||
}
|
||||
|
||||
string text = "";
|
||||
if (m_Config.RoleTag.Format == RoleTagFormat.AbbreviatedJobName)
|
||||
{
|
||||
text = character.ClassJob.GameData.Abbreviation;
|
||||
}
|
||||
else if (m_Config.RoleTag.Format == RoleTagFormat.JobName)
|
||||
{
|
||||
text = character.ClassJob.GameData.NameEnglish;
|
||||
}
|
||||
else if (m_Config.RoleTag.Format == RoleTagFormat.RoleName)
|
||||
{
|
||||
text = m_Config.RoleTag.RoleOverrideConfigs[role].Name;
|
||||
}
|
||||
|
||||
List<Payload> newPayloads = new List<Payload>();
|
||||
|
||||
// There will always be a text payload
|
||||
newPayloads.Add(new TextPayload(text));
|
||||
|
||||
ushort? colorId = null;
|
||||
|
||||
// Pick a color id if one is available
|
||||
if (roleConfig.JobOverrideConfigs[jobAbbreviation].CustomColor.Id != null)
|
||||
BitmapFontIcon? icon = null;
|
||||
if (tagTarget == TagTarget.Chat && tag.IsIconVisibleInChat.InheritedValue != null && tag.IsIconVisibleInChat.InheritedValue.Value)
|
||||
{
|
||||
colorId = roleConfig.JobOverrideConfigs[jobAbbreviation].CustomColor.Id!.Value;
|
||||
icon = tag.Icon.InheritedValue;
|
||||
}
|
||||
else if (roleConfig.CustomColor.Id != null)
|
||||
else if (tagTarget == TagTarget.Nameplate && tag.IsIconVisibleInNameplates.InheritedValue != null && tag.IsIconVisibleInNameplates.InheritedValue.Value)
|
||||
{
|
||||
colorId = roleConfig.CustomColor.Id.Value;
|
||||
icon = tag.Icon.InheritedValue;
|
||||
}
|
||||
|
||||
// If we picked a color id, add the payloads for it
|
||||
if (colorId != null)
|
||||
string? text = null;
|
||||
if (tagTarget == TagTarget.Chat && tag.IsTextVisibleInChat.InheritedValue != null && tag.IsTextVisibleInChat.InheritedValue.Value)
|
||||
{
|
||||
newPayloads.Insert(0, new UIForegroundPayload(colorId.Value));
|
||||
newPayloads.Add(new UIForegroundPayload(0));
|
||||
text = tag.Text.InheritedValue;
|
||||
}
|
||||
else if (tagTarget == TagTarget.Nameplate && tag.IsTextVisibleInNameplates.InheritedValue != null && tag.IsTextVisibleInNameplates.InheritedValue.Value)
|
||||
{
|
||||
text = tag.Text.InheritedValue;
|
||||
}
|
||||
|
||||
var newPayloadsArray = newPayloads.ToArray();
|
||||
m_JobTagPayloads[jobAbbreviation] = newPayloadsArray;
|
||||
if (!m_TagTargetPayloads.ContainsKey(tag))
|
||||
{
|
||||
m_TagTargetPayloads[tag] = new Dictionary<TagTarget, Payload[]>();
|
||||
}
|
||||
|
||||
return newPayloadsArray;
|
||||
if (icon != null && icon.Value != BitmapFontIcon.None)
|
||||
{
|
||||
newPayloads.Add(new IconPayload(icon.Value));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
if (tag.IsTextItalic.InheritedValue != null && tag.IsTextItalic.InheritedValue.Value)
|
||||
{
|
||||
newPayloads.Add(new EmphasisItalicPayload(true));
|
||||
}
|
||||
|
||||
if (tag.TextColor.InheritedValue != null)
|
||||
{
|
||||
newPayloads.Add(new UIForegroundPayload(tag.TextColor.InheritedValue.Value));
|
||||
}
|
||||
|
||||
newPayloads.Add(new TextPayload(text));
|
||||
|
||||
if (tag.IsTextItalic.InheritedValue != null && tag.IsTextItalic.InheritedValue.Value)
|
||||
{
|
||||
newPayloads.Add(new EmphasisItalicPayload(false));
|
||||
}
|
||||
|
||||
if (tag.TextColor.InheritedValue != null)
|
||||
{
|
||||
newPayloads.Add(new UIForegroundPayload(0));
|
||||
}
|
||||
}
|
||||
|
||||
return newPayloads.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -249,51 +279,83 @@ namespace PlayerTags
|
||||
/// </summary>
|
||||
/// <param name="customTagConfig">The custom tag config to get payloads for.</param>
|
||||
/// <returns>A list of payloads for the given custom tag.</returns>
|
||||
private IEnumerable<Payload> GetCustomTagPayloads(CustomTagConfig customTagConfig)
|
||||
private IEnumerable<Payload> GetTagPayloads(TagTarget tagTarget, Tag tag)
|
||||
{
|
||||
if (m_CustomTagPayloads.TryGetValue(customTagConfig, out var payloads))
|
||||
if (m_TagTargetPayloads.TryGetValue(tag, out var tagTargetPayloads))
|
||||
{
|
||||
return payloads;
|
||||
if (tagTargetPayloads.TryGetValue(tagTarget, out var payloads))
|
||||
{
|
||||
return payloads;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_TagTargetPayloads[tag] = new Dictionary<TagTarget, Payload[]>();
|
||||
}
|
||||
|
||||
List<Payload> newPayloads = new List<Payload>();
|
||||
|
||||
// There will always be a text payload
|
||||
newPayloads.Add(new TextPayload(customTagConfig.Name));
|
||||
|
||||
ushort? colorId = null;
|
||||
|
||||
// Pick a color id if one is available
|
||||
if (customTagConfig.CustomColor.Id != null)
|
||||
{
|
||||
colorId = customTagConfig.CustomColor.Id!.Value;
|
||||
}
|
||||
|
||||
// If we picked a color id, add the payloads for it
|
||||
if (colorId != null)
|
||||
{
|
||||
newPayloads.Insert(0, new UIForegroundPayload(colorId.Value));
|
||||
newPayloads.Add(new UIForegroundPayload(0));
|
||||
}
|
||||
|
||||
var newPayloadsArray = newPayloads.ToArray();
|
||||
m_CustomTagPayloads[customTagConfig] = newPayloadsArray;
|
||||
|
||||
return newPayloadsArray;
|
||||
m_TagTargetPayloads[tag][tagTarget] = CreateTagPayloads(tagTarget, tag);
|
||||
return m_TagTargetPayloads[tag][tagTarget];
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds an additional space text payload in between any existing text payloads.
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="payloads">The payloads to add spaces between.</param>
|
||||
private void AddSpacesBetweenTextPayloads(List<Payload> payloads)
|
||||
private void AddSpacesBetweenTextPayloads(List<Payload> payloads, TagPosition tagPosition)
|
||||
{
|
||||
var textPayloads = payloads.Where(payload => payload is TextPayload).ToList();
|
||||
foreach (var textPayload in textPayloads.Skip(1))
|
||||
if (payloads == null)
|
||||
{
|
||||
var index = payloads.IndexOf(textPayload);
|
||||
payloads.Insert(index, m_SpaceTextPayload);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!payloads.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<int> indicesToInsertSpacesAt = new List<int>();
|
||||
int lastTextPayloadIndex = -1;
|
||||
foreach (var payload in payloads.Reverse<Payload>())
|
||||
{
|
||||
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, m_SpaceTextPayload);
|
||||
}
|
||||
|
||||
// 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(m_SpaceTextPayload);
|
||||
}
|
||||
}
|
||||
// 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, m_SpaceTextPayload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,15 +375,19 @@ namespace PlayerTags
|
||||
public TextPayload TextPayload { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The matching game object.
|
||||
/// The matching game object if one exists
|
||||
/// </summary>
|
||||
public GameObject? GameObject { get; init; }
|
||||
|
||||
public StringMatch(SeString seString, TextPayload textPayload, GameObject? gameObject = null)
|
||||
/// <summary>
|
||||
/// A matching player payload if one exists.
|
||||
/// </summary>
|
||||
public PlayerPayload? PlayerPayload { get; init; }
|
||||
|
||||
public StringMatch(SeString seString, TextPayload textPayload)
|
||||
{
|
||||
SeString = seString;
|
||||
TextPayload = textPayload;
|
||||
GameObject = gameObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -358,7 +424,11 @@ namespace PlayerTags
|
||||
// The next payload MUST be a text payload
|
||||
if (payloadIndex + 1 < seString.Payloads.Count && seString.Payloads[payloadIndex + 1] is TextPayload textPayload)
|
||||
{
|
||||
var stringMatch = new StringMatch(seString, textPayload, gameObject);
|
||||
var stringMatch = new StringMatch(seString, textPayload)
|
||||
{
|
||||
GameObject = gameObject,
|
||||
PlayerPayload = playerPayload
|
||||
};
|
||||
stringMatches.Add(stringMatch);
|
||||
|
||||
// Don't handle the text payload twice
|
||||
@@ -370,18 +440,25 @@ namespace PlayerTags
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: Not sure if this is desirable. Enabling this allows tags to appear next to the name of the local player by text in chat because the local player doesn't have a player payload.
|
||||
/// But because it's just a simple string comparison, it won't work in all circumstances. E.g. in party chat the player name is wrapped in (). To be comprehensive we need to search substring.
|
||||
/// This means we would need to think about breaking down existing payloads to split them out.
|
||||
/// If we decide to do that, we could even for example find unlinked player names in chat and add player payloads for them.
|
||||
// If it's just a text payload then either a character NEEDS to exist for it, or it needs to be identified as a character by custom tag configs
|
||||
else if (payload is TextPayload textPayload)
|
||||
{
|
||||
var gameObject = ObjectTable.FirstOrDefault(gameObject => gameObject.Name.TextValue == textPayload.Text);
|
||||
var isIncludedInCustomTagConfig = m_Config.CustomTagConfigs.Any(customTagConfig => customTagConfig.IncludesGameObjectName(textPayload.Text));
|
||||
//else if (payload is TextPayload textPayload)
|
||||
//{
|
||||
// var gameObject = ObjectTable.FirstOrDefault(gameObject => gameObject.Name.TextValue == textPayload.Text);
|
||||
// var isIncludedInCustomTagConfig = m_Config.CustomTags.Any(customTagConfig => customTagConfig.IncludesGameObjectName(textPayload.Text));
|
||||
|
||||
if (gameObject != null || isIncludedInCustomTagConfig)
|
||||
{
|
||||
var stringMatch = new StringMatch(seString, textPayload, gameObject);
|
||||
stringMatches.Add(stringMatch);
|
||||
}
|
||||
}
|
||||
// if (gameObject != null || isIncludedInCustomTagConfig)
|
||||
// {
|
||||
// var stringMatch = new StringMatch(seString, textPayload)
|
||||
// {
|
||||
// GameObject = gameObject
|
||||
// };
|
||||
// stringMatches.Add(stringMatch);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
return stringMatches;
|
||||
@@ -390,32 +467,37 @@ namespace PlayerTags
|
||||
/// <summary>
|
||||
/// Adds the given payload changes to the dictionary.
|
||||
/// </summary>
|
||||
/// <param name="stringPosition">The position of the string to add changes to.</param>
|
||||
/// <param name="tagPosition">The position to add changes to.</param>
|
||||
/// <param name="payloads">The payloads to add.</param>
|
||||
/// <param name="stringChanges">The dictionary to add the changes to.</param>
|
||||
private void AddPayloadChanges(StringPosition stringPosition, IEnumerable<Payload> payloads, Dictionary<StringPosition, List<Payload>> stringChanges)
|
||||
private void AddPayloadChanges(TagPosition tagPosition, IEnumerable<Payload> payloads, Dictionary<TagPosition, List<Payload>> stringChanges)
|
||||
{
|
||||
if (!payloads.Any())
|
||||
if (payloads == null || !payloads.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!stringChanges.Keys.Contains(stringPosition))
|
||||
if (stringChanges == null)
|
||||
{
|
||||
stringChanges[stringPosition] = new List<Payload>();
|
||||
return;
|
||||
}
|
||||
|
||||
stringChanges[stringPosition].AddRange(payloads);
|
||||
if (!stringChanges.Keys.Contains(tagPosition))
|
||||
{
|
||||
stringChanges[tagPosition] = new List<Payload>();
|
||||
}
|
||||
|
||||
stringChanges[tagPosition].AddRange(payloads);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given payload changes to the dictionary.
|
||||
/// </summary>
|
||||
/// <param name="nameplateElement">The nameplate element to add changes to.</param>
|
||||
/// <param name="stringPosition">The position of the string to add changes to.</param>
|
||||
/// <param name="tagPosition">The position to add changes to.</param>
|
||||
/// <param name="payloads">The payloads to add.</param>
|
||||
/// <param name="nameplateChanges">The dictionary to add the changes to.</param>
|
||||
private void AddPayloadChanges(NameplateElement nameplateElement, StringPosition stringPosition, IEnumerable<Payload> payloads, Dictionary<NameplateElement, Dictionary<StringPosition, List<Payload>>> nameplateChanges)
|
||||
private void AddPayloadChanges(NameplateElement nameplateElement, TagPosition tagPosition, IEnumerable<Payload> payloads, Dictionary<NameplateElement, Dictionary<TagPosition, List<Payload>>> nameplateChanges)
|
||||
{
|
||||
if (!payloads.Any())
|
||||
{
|
||||
@@ -424,10 +506,10 @@ namespace PlayerTags
|
||||
|
||||
if (!nameplateChanges.Keys.Contains(nameplateElement))
|
||||
{
|
||||
nameplateChanges[nameplateElement] = new Dictionary<StringPosition, List<Payload>>();
|
||||
nameplateChanges[nameplateElement] = new Dictionary<TagPosition, List<Payload>>();
|
||||
}
|
||||
|
||||
AddPayloadChanges(stringPosition, payloads, nameplateChanges[nameplateElement]);
|
||||
AddPayloadChanges(tagPosition, payloads, nameplateChanges[nameplateElement]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -436,53 +518,71 @@ namespace PlayerTags
|
||||
/// <param name="seString">The string to apply changes to.</param>
|
||||
/// <param name="stringChanges">The changes to apply.</param>
|
||||
/// <param name="anchorPayload">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.</param>
|
||||
private void ApplyStringChanges(SeString seString, Dictionary<StringPosition, List<Payload>> stringChanges, Payload? anchorPayload = null)
|
||||
private void ApplyStringChanges(SeString seString, Dictionary<TagPosition, List<Payload>> stringChanges, Payload? anchorPayload = null)
|
||||
{
|
||||
foreach ((var stringPosition, var payloads) in stringChanges)
|
||||
if (stringChanges.Count == 0)
|
||||
{
|
||||
if (!payloads.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
AddSpacesBetweenTextPayloads(payloads);
|
||||
List<TagPosition> tagPositionsOrdered = new List<TagPosition>();
|
||||
// If there's no anchor payload, do replaces first so that befores and afters are based on the replaced data
|
||||
if (anchorPayload == null)
|
||||
{
|
||||
tagPositionsOrdered.Add(TagPosition.Replace);
|
||||
}
|
||||
|
||||
if (stringPosition == StringPosition.Before)
|
||||
tagPositionsOrdered.Add(TagPosition.Before);
|
||||
tagPositionsOrdered.Add(TagPosition.After);
|
||||
|
||||
// If there is an anchor payload, do replaces last so that we still know which payload needs to be removed
|
||||
if (anchorPayload != null)
|
||||
{
|
||||
tagPositionsOrdered.Add(TagPosition.Replace);
|
||||
}
|
||||
|
||||
foreach (var tagPosition in tagPositionsOrdered)
|
||||
{
|
||||
if (stringChanges.TryGetValue(tagPosition, out var payloads) && payloads.Any())
|
||||
{
|
||||
if (anchorPayload != null)
|
||||
AddSpacesBetweenTextPayloads(stringChanges[tagPosition], tagPosition);
|
||||
if (tagPosition == TagPosition.Before)
|
||||
{
|
||||
var payloadIndex = seString.Payloads.IndexOf(anchorPayload);
|
||||
seString.Payloads.InsertRange(payloadIndex, payloads.Append(m_SpaceTextPayload));
|
||||
if (anchorPayload != null)
|
||||
{
|
||||
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorPayload);
|
||||
seString.Payloads.InsertRange(anchorPayloadIndex, payloads);
|
||||
}
|
||||
else
|
||||
{
|
||||
seString.Payloads.InsertRange(0, payloads);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (tagPosition == TagPosition.After)
|
||||
{
|
||||
seString.Payloads.InsertRange(0, payloads.Append(m_SpaceTextPayload));
|
||||
if (anchorPayload != null)
|
||||
{
|
||||
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorPayload);
|
||||
seString.Payloads.InsertRange(anchorPayloadIndex + 1, payloads);
|
||||
}
|
||||
else
|
||||
{
|
||||
seString.Payloads.AddRange(payloads);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (stringPosition == StringPosition.After)
|
||||
{
|
||||
if (anchorPayload != null)
|
||||
else if (tagPosition == TagPosition.Replace)
|
||||
{
|
||||
var payloadIndex = seString.Payloads.IndexOf(anchorPayload);
|
||||
seString.Payloads.InsertRange(payloadIndex + 1, payloads.Prepend(m_SpaceTextPayload));
|
||||
}
|
||||
else
|
||||
{
|
||||
seString.Payloads.AddRange(payloads.Prepend(m_SpaceTextPayload));
|
||||
}
|
||||
}
|
||||
else if (stringPosition == StringPosition.Replace)
|
||||
{
|
||||
if (anchorPayload != null)
|
||||
{
|
||||
var payloadIndex = seString.Payloads.IndexOf(anchorPayload);
|
||||
seString.Payloads.InsertRange(payloadIndex, payloads);
|
||||
seString.Payloads.Remove(anchorPayload);
|
||||
}
|
||||
else
|
||||
{
|
||||
seString.Payloads.Clear();
|
||||
seString.Payloads.AddRange(payloads);
|
||||
if (anchorPayload != null)
|
||||
{
|
||||
var anchorPayloadIndex = seString.Payloads.IndexOf(anchorPayload);
|
||||
seString.Payloads.InsertRange(anchorPayloadIndex, payloads);
|
||||
seString.Payloads.Remove(anchorPayload);
|
||||
}
|
||||
else
|
||||
{
|
||||
seString.Payloads.Clear();
|
||||
seString.Payloads.AddRange(payloads);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -504,18 +604,25 @@ namespace PlayerTags
|
||||
isTitleChanged = false;
|
||||
isFreeCompanyChanged = false;
|
||||
|
||||
Dictionary<NameplateElement, Dictionary<StringPosition, List<Payload>>> nameplateChanges = new Dictionary<NameplateElement, Dictionary<StringPosition, List<Payload>>>();
|
||||
Dictionary<NameplateElement, Dictionary<TagPosition, List<Payload>>> nameplateChanges = new Dictionary<NameplateElement, Dictionary<TagPosition, List<Payload>>>();
|
||||
|
||||
if (gameObject is Character character)
|
||||
{
|
||||
// Add the role tag payloads
|
||||
if (m_Config.RoleTag.NameplatePosition != StringPosition.None)
|
||||
// Add the job tag
|
||||
if (m_PluginData.JobTags.TryGetValue(character.ClassJob.GameData.Abbreviation, out var jobTag))
|
||||
{
|
||||
AddPayloadChanges(m_Config.RoleTag.NameplateElement, m_Config.RoleTag.NameplatePosition, GetJobTagPayloads(character), nameplateChanges);
|
||||
if (jobTag.TagTargetInNameplates.InheritedValue != null && jobTag.TagPositionInNameplates.InheritedValue != null)
|
||||
{
|
||||
var payloads = GetTagPayloads(TagTarget.Nameplate, jobTag);
|
||||
if (payloads.Any())
|
||||
{
|
||||
AddPayloadChanges(jobTag.TagTargetInNameplates.InheritedValue.Value, jobTag.TagPositionInNameplates.InheritedValue.Value, payloads, nameplateChanges);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add randomly generated name tag payload
|
||||
if (m_Config.IsPlayerNameRandomlyGenerated && m_RandomNameGenerator != null)
|
||||
// Add the randomly generated name tag payload
|
||||
if (m_PluginConfiguration.IsPlayerNameRandomlyGenerated && m_RandomNameGenerator != null)
|
||||
{
|
||||
var characterName = character.Name.TextValue;
|
||||
if (characterName != null)
|
||||
@@ -523,18 +630,25 @@ namespace PlayerTags
|
||||
var generatedName = m_RandomNameGenerator.GetGeneratedName(characterName);
|
||||
if (generatedName != null)
|
||||
{
|
||||
AddPayloadChanges(NameplateElement.Name, StringPosition.Replace, Enumerable.Empty<Payload>().Append(new TextPayload(generatedName)), nameplateChanges);
|
||||
AddPayloadChanges(NameplateElement.Name, TagPosition.Replace, Enumerable.Empty<Payload>().Append(new TextPayload(generatedName)), nameplateChanges);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the custom tag payloads
|
||||
foreach (var customTagConfig in m_Config.CustomTagConfigs)
|
||||
foreach (var customTag in m_PluginData.CustomTags)
|
||||
{
|
||||
if (customTagConfig.NameplatePosition != StringPosition.None && customTagConfig.FormattedGameObjectNames.Split(',').Contains(gameObject.Name.TextValue))
|
||||
if (customTag.TagTargetInNameplates.InheritedValue != null && customTag.TagPositionInNameplates.InheritedValue != null)
|
||||
{
|
||||
AddPayloadChanges(customTagConfig.NameplateElement, customTagConfig.NameplatePosition, GetCustomTagPayloads(customTagConfig), nameplateChanges);
|
||||
if (customTag.IncludesGameObjectNameToApplyTo(gameObject.Name.TextValue))
|
||||
{
|
||||
var payloads = GetTagPayloads(TagTarget.Nameplate, customTag);
|
||||
if (payloads.Any())
|
||||
{
|
||||
AddPayloadChanges(customTag.TagTargetInNameplates.InheritedValue.Value, customTag.TagPositionInNameplates.InheritedValue.Value, payloads, nameplateChanges);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,37 +691,52 @@ namespace PlayerTags
|
||||
var stringMatches = GetStringMatches(message);
|
||||
foreach (var stringMatch in stringMatches)
|
||||
{
|
||||
Dictionary<StringPosition, List<Payload>> stringChanges = new Dictionary<StringPosition, List<Payload>>();
|
||||
Dictionary<TagPosition, List<Payload>> stringChanges = new Dictionary<TagPosition, List<Payload>>();
|
||||
|
||||
// The role tag payloads
|
||||
if (stringMatch.GameObject is Character character)
|
||||
{
|
||||
if (m_Config.RoleTag.ChatPosition != StringPosition.None)
|
||||
// Add the job tag
|
||||
if (m_PluginData.JobTags.TryGetValue(character.ClassJob.GameData.Abbreviation, out var jobTag))
|
||||
{
|
||||
AddPayloadChanges(m_Config.RoleTag.ChatPosition, GetJobTagPayloads(character), stringChanges);
|
||||
}
|
||||
}
|
||||
|
||||
// Add randomly generated name tag payload
|
||||
if (m_Config.IsPlayerNameRandomlyGenerated && m_RandomNameGenerator != null)
|
||||
{
|
||||
var playerName = stringMatch.GetMatchText();
|
||||
if (playerName != null)
|
||||
{
|
||||
var generatedName = m_RandomNameGenerator.GetGeneratedName(playerName);
|
||||
if (generatedName != null)
|
||||
if (jobTag.TagPositionInChat.InheritedValue != null)
|
||||
{
|
||||
AddPayloadChanges(StringPosition.Replace, Enumerable.Empty<Payload>().Append(new TextPayload(generatedName)), stringChanges);
|
||||
var payloads = GetTagPayloads(TagTarget.Chat, jobTag);
|
||||
if (payloads.Any())
|
||||
{
|
||||
AddPayloadChanges(jobTag.TagPositionInChat.InheritedValue.Value, payloads, stringChanges);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add randomly generated name tag payload
|
||||
if (m_PluginConfiguration.IsPlayerNameRandomlyGenerated && m_RandomNameGenerator != null)
|
||||
{
|
||||
var playerName = stringMatch.GetMatchText();
|
||||
if (playerName != null)
|
||||
{
|
||||
var generatedName = m_RandomNameGenerator.GetGeneratedName(playerName);
|
||||
if (generatedName != null)
|
||||
{
|
||||
AddPayloadChanges(TagPosition.Replace, Enumerable.Empty<Payload>().Append(new TextPayload(generatedName)), stringChanges);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the custom tag payloads
|
||||
foreach (var customTagConfig in m_Config.CustomTagConfigs)
|
||||
foreach (var customTag in m_PluginData.CustomTags)
|
||||
{
|
||||
if (customTagConfig.IncludesGameObjectName(stringMatch.GetMatchText()))
|
||||
if (customTag.TagPositionInChat.InheritedValue != null)
|
||||
{
|
||||
AddPayloadChanges(customTagConfig.ChatPosition, GetCustomTagPayloads(customTagConfig), stringChanges);
|
||||
if (customTag.IncludesGameObjectNameToApplyTo(stringMatch.GetMatchText()))
|
||||
{
|
||||
var customTagPayloads = GetTagPayloads(TagTarget.Chat, customTag);
|
||||
if (customTagPayloads.Any())
|
||||
{
|
||||
AddPayloadChanges(customTag.TagPositionInChat.InheritedValue.Value, customTagPayloads, stringChanges);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
94
PlayerTags/PluginConfiguration.cs
Normal file
94
PlayerTags/PluginConfiguration.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
using Dalamud.Configuration;
|
||||
using Dalamud.Plugin;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PlayerTags
|
||||
{
|
||||
[Serializable]
|
||||
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;
|
||||
public bool IsPlayerNameRandomlyGenerated = false;
|
||||
|
||||
[JsonProperty(TypeNameHandling = TypeNameHandling.None, ItemTypeNameHandling = TypeNameHandling.None)]
|
||||
public Dictionary<string, InheritableData> AllTagsChanges = new Dictionary<string, InheritableData>();
|
||||
|
||||
[JsonProperty(TypeNameHandling = TypeNameHandling.None, ItemTypeNameHandling = TypeNameHandling.None)]
|
||||
public Dictionary<string, InheritableData> AllRoleTagsChanges = new Dictionary<string, InheritableData>();
|
||||
|
||||
[JsonProperty(TypeNameHandling = TypeNameHandling.None, ItemTypeNameHandling = TypeNameHandling.None)]
|
||||
public Dictionary<Role, Dictionary<string, InheritableData>> RoleTagsChanges = new Dictionary<Role, Dictionary<string, InheritableData>>();
|
||||
|
||||
[JsonProperty(TypeNameHandling = TypeNameHandling.None, ItemTypeNameHandling = TypeNameHandling.None)]
|
||||
public Dictionary<string, Dictionary<string, InheritableData>> JobTagsChanges = new Dictionary<string, Dictionary<string, InheritableData>>();
|
||||
|
||||
[JsonProperty(TypeNameHandling = TypeNameHandling.None, ItemTypeNameHandling = TypeNameHandling.None)]
|
||||
public Dictionary<string, InheritableData> AllCustomTagsChanges = new Dictionary<string, InheritableData>();
|
||||
|
||||
[JsonProperty(TypeNameHandling = TypeNameHandling.None, ItemTypeNameHandling = TypeNameHandling.None)]
|
||||
public List<Dictionary<string, InheritableData>> CustomTagsChanges = new List<Dictionary<string, InheritableData>>();
|
||||
|
||||
[NonSerialized]
|
||||
private DalamudPluginInterface? m_PluginInterface;
|
||||
|
||||
public event System.Action? Saved;
|
||||
|
||||
public void Initialize(DalamudPluginInterface pluginInterface)
|
||||
{
|
||||
m_PluginInterface = pluginInterface;
|
||||
}
|
||||
|
||||
public void Save(PluginData pluginData)
|
||||
{
|
||||
AllTagsChanges = pluginData.AllTags.GetChanges(pluginData.Default.AllTagsChanges);
|
||||
AllRoleTagsChanges = pluginData.AllRoleTags.GetChanges(pluginData.Default.AllRoleTagsChanges);
|
||||
|
||||
RoleTagsChanges = new Dictionary<Role, Dictionary<string, InheritableData>>();
|
||||
foreach ((var role, var roleTag) in pluginData.RoleTags)
|
||||
{
|
||||
Dictionary<string, InheritableData>? defaultChanges;
|
||||
pluginData.Default.RoleTagsChanges.TryGetValue(role, out defaultChanges);
|
||||
|
||||
var changes = roleTag.GetChanges(defaultChanges);
|
||||
if (changes.Any())
|
||||
{
|
||||
RoleTagsChanges[role] = changes;
|
||||
}
|
||||
}
|
||||
|
||||
JobTagsChanges = new Dictionary<string, Dictionary<string, InheritableData>>();
|
||||
foreach ((var jobAbbreviation, var jobTag) in pluginData.JobTags)
|
||||
{
|
||||
Dictionary<string, InheritableData>? defaultChanges;
|
||||
pluginData.Default.JobTagsChanges.TryGetValue(jobAbbreviation, out defaultChanges);
|
||||
|
||||
var changes = jobTag.GetChanges(defaultChanges);
|
||||
if (changes.Any())
|
||||
{
|
||||
JobTagsChanges[jobAbbreviation] = changes;
|
||||
}
|
||||
}
|
||||
|
||||
AllCustomTagsChanges = pluginData.AllCustomTags.GetChanges(pluginData.Default.AllCustomTagsChanges);
|
||||
|
||||
CustomTagsChanges = new List<Dictionary<string, InheritableData>>();
|
||||
foreach (var customTag in pluginData.CustomTags)
|
||||
{
|
||||
CustomTagsChanges.Add(customTag.GetChanges());
|
||||
}
|
||||
|
||||
if (m_PluginInterface != null)
|
||||
{
|
||||
m_PluginInterface.SavePluginConfig(this);
|
||||
Saved?.Invoke();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
571
PlayerTags/PluginConfigurationUI.cs
Normal file
571
PlayerTags/PluginConfigurationUI.cs
Normal file
@@ -0,0 +1,571 @@
|
||||
using ImGuiNET;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using PlayerTags.Resources;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace PlayerTags
|
||||
{
|
||||
public class PluginConfigurationUI
|
||||
{
|
||||
private PluginConfiguration m_PluginConfiguration;
|
||||
|
||||
private PluginData m_PluginData;
|
||||
|
||||
private InheritableValue<ushort>? m_ColorPickerPopupDataContext;
|
||||
|
||||
public PluginConfigurationUI(PluginConfiguration config, PluginData pluginData)
|
||||
{
|
||||
m_PluginConfiguration = config;
|
||||
m_PluginData = pluginData;
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
if (m_PluginConfiguration == null || !m_PluginConfiguration.IsVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
DrawHeading(Strings.Loc_Static_Nameplates);
|
||||
ImGui.TreePush();
|
||||
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));
|
||||
ImGui.TreePop();
|
||||
|
||||
DrawHeading(Strings.Loc_Static_Development);
|
||||
ImGui.TreePush();
|
||||
DrawCheckbox(nameof(m_PluginConfiguration.IsPlayerNameRandomlyGenerated), true, ref m_PluginConfiguration.IsPlayerNameRandomlyGenerated, () => m_PluginConfiguration.Save(m_PluginData));
|
||||
ImGui.TreePop();
|
||||
ImGui.EndTabItem();
|
||||
|
||||
DrawHeading(Strings.Loc_Static_Tags);
|
||||
ImGui.TreePush();
|
||||
int depth = 0;
|
||||
Draw(m_PluginData.AllTags, ref depth);
|
||||
|
||||
if (ImGui.Button(Strings.Loc_Static_AddCustomTag))
|
||||
{
|
||||
var newTag = new Tag(new LocalizedPluginString(nameof(PluginData.CustomTags)))
|
||||
{
|
||||
Text = "",
|
||||
GameObjectNamesToApplyTo = ""
|
||||
};
|
||||
|
||||
m_PluginData.CustomTags.Add(newTag);
|
||||
newTag.Parent = m_PluginData.AllCustomTags;
|
||||
}
|
||||
ImGui.TreePop();
|
||||
ImGui.End();
|
||||
}
|
||||
|
||||
if (!m_PluginConfiguration.IsVisible)
|
||||
{
|
||||
m_PluginConfiguration.Save(m_PluginData);
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(Tag tag, ref int depth)
|
||||
{
|
||||
ImGui.PushID(tag.GetHashCode().ToString());
|
||||
|
||||
ImGui.BeginGroup();
|
||||
ImGui.BeginChild(tag.GetHashCode().ToString(), new Vector2(100, 60));
|
||||
|
||||
var text = tag.Name.Value;
|
||||
var textSize = ImGui.CalcTextSize(text);
|
||||
var addButtonSize = new Vector2(23, 23);
|
||||
var panelSize = ImGui.GetItemRectSize();
|
||||
|
||||
ImGui.SetCursorPosX(panelSize.X - textSize.X);
|
||||
ImGui.Text(text);
|
||||
|
||||
if (ImGui.IsPopupOpen("AddPopup"))
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, new Vector4(0.2f, 0.6f, 0.2f, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, new Vector4(0.1f, 0.3f, 0.1f, 1));
|
||||
}
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, new Vector4(0.2f, 0.6f, 0.2f, 1));
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonActive, new Vector4(0.2f, 0.6f, 0.2f, 1));
|
||||
ImGui.SetCursorPosX(panelSize.X - addButtonSize.X);
|
||||
var addPopupPos = ImGui.GetCursorPos();
|
||||
addPopupPos.Y -= addButtonSize.Y + 2;
|
||||
if (ImGui.Button("+", addButtonSize))
|
||||
{
|
||||
ImGui.OpenPopup("AddPopup");
|
||||
}
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
bool wasPaddingConsumed = false;
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, 5));
|
||||
ImGui.SetNextWindowPos(ImGui.GetCursorScreenPos() + addPopupPos);
|
||||
if (ImGui.BeginPopup("AddPopup"))
|
||||
{
|
||||
wasPaddingConsumed = true;
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
ImGui.PushStyleColor(ImGuiCol.FrameBg, new Vector4(0f, 0f, 0f, 0));
|
||||
if (ImGui.BeginListBox("###SelectableInheritables"))
|
||||
{
|
||||
var selectableInheritables = tag.Inheritables.Where(inheritable => inheritable.Value.Behavior == InheritableBehavior.Inherit).ToDictionary(item => item.Key, item => item.Value);
|
||||
var selectableInheritablesWithLocalizedNames = selectableInheritables
|
||||
.Select(inheritable => new { Name = inheritable.Key, LocalizedName = Localizer.GetString(inheritable.Key, false) })
|
||||
.OrderBy(item => item.LocalizedName);
|
||||
|
||||
foreach (var inheritableLocalizedName in selectableInheritablesWithLocalizedNames)
|
||||
{
|
||||
bool isSelected = false;
|
||||
if (ImGui.Selectable(inheritableLocalizedName.LocalizedName, isSelected))
|
||||
{
|
||||
selectableInheritables[inheritableLocalizedName.Name].Behavior = InheritableBehavior.Enabled;
|
||||
|
||||
if (selectableInheritables[inheritableLocalizedName.Name] is InheritableValue<bool> inheritableBool)
|
||||
{
|
||||
inheritableBool.Value = true;
|
||||
}
|
||||
|
||||
m_PluginConfiguration.Save(m_PluginData);
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
ImGui.SetItemDefaultFocus();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetTooltip(Localizer.GetString(inheritableLocalizedName.Name, true));
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndListBox();
|
||||
}
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
if (!wasPaddingConsumed)
|
||||
{
|
||||
ImGui.PopStyleVar();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetTooltip(Strings.Loc_Static_AddPropertyOverride_Description);
|
||||
}
|
||||
ImGui.EndChild();
|
||||
ImGui.EndGroup();
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.BeginGroup();
|
||||
|
||||
var selectedInheritables = tag.Inheritables.Where(inheritable => inheritable.Value.Behavior != InheritableBehavior.Inherit).ToDictionary(item => item.Key, item => item.Value);
|
||||
var selectedInheritablesWithLocalizedNames = selectedInheritables
|
||||
.Select(inheritable => new { Name = inheritable.Key, LocalizedName = Localizer.GetString(inheritable.Key, false) })
|
||||
.OrderBy(item => item.LocalizedName);
|
||||
|
||||
foreach (var selectedInheritablesWithLocalizedName in selectedInheritablesWithLocalizedNames)
|
||||
{
|
||||
switch (selectedInheritablesWithLocalizedName.Name)
|
||||
{
|
||||
case nameof(tag.Icon):
|
||||
ImGui.SameLine();
|
||||
DrawInheritable(nameof(tag.Icon), false, true, tag.Icon);
|
||||
break;
|
||||
case nameof(tag.IsIconVisibleInChat):
|
||||
ImGui.SameLine();
|
||||
DrawInheritable(nameof(tag.IsIconVisibleInChat), tag.IsIconVisibleInChat);
|
||||
break;
|
||||
case nameof(tag.IsIconVisibleInNameplates):
|
||||
ImGui.SameLine();
|
||||
DrawInheritable(nameof(tag.IsIconVisibleInNameplates), tag.IsIconVisibleInNameplates);
|
||||
break;
|
||||
case nameof(tag.Text):
|
||||
ImGui.SameLine();
|
||||
DrawInheritable(nameof(tag.Text), tag.Text);
|
||||
break;
|
||||
case nameof(tag.TextColor):
|
||||
ImGui.SameLine();
|
||||
DrawInheritable(nameof(tag.TextColor), tag.TextColor);
|
||||
break;
|
||||
case nameof(tag.IsTextItalic):
|
||||
ImGui.SameLine();
|
||||
DrawInheritable(nameof(tag.IsTextItalic), tag.IsTextItalic);
|
||||
break;
|
||||
case nameof(tag.IsTextVisibleInChat):
|
||||
ImGui.SameLine();
|
||||
DrawInheritable(nameof(tag.IsTextVisibleInChat), tag.IsTextVisibleInChat);
|
||||
break;
|
||||
case nameof(tag.IsTextVisibleInNameplates):
|
||||
ImGui.SameLine();
|
||||
DrawInheritable(nameof(tag.IsTextVisibleInNameplates), tag.IsTextVisibleInNameplates);
|
||||
break;
|
||||
case nameof(tag.TagPositionInChat):
|
||||
ImGui.SameLine();
|
||||
DrawInheritable(nameof(tag.TagPositionInChat), true, false, tag.TagPositionInChat);
|
||||
break;
|
||||
case nameof(tag.TagPositionInNameplates):
|
||||
ImGui.SameLine();
|
||||
DrawInheritable(nameof(tag.TagPositionInNameplates), true, false, tag.TagPositionInNameplates);
|
||||
break;
|
||||
case nameof(tag.TagTargetInNameplates):
|
||||
ImGui.SameLine();
|
||||
DrawInheritable(nameof(tag.TagTargetInNameplates), true, false, tag.TagTargetInNameplates);
|
||||
break;
|
||||
case nameof(tag.GameObjectNamesToApplyTo):
|
||||
ImGui.SameLine();
|
||||
DrawInheritable(nameof(tag.GameObjectNamesToApplyTo), tag.GameObjectNamesToApplyTo);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_PluginData.CustomTags.Contains(tag))
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.BeginGroup();
|
||||
ImGui.Indent();
|
||||
if (ImGui.Button(Strings.Loc_Static_RemoveCustomTag))
|
||||
{
|
||||
m_PluginData.AllCustomTags.Children.Remove(tag);
|
||||
m_PluginData.CustomTags.Remove(tag);
|
||||
m_PluginConfiguration.Save(m_PluginData);
|
||||
}
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
ImGui.EndGroup();
|
||||
|
||||
foreach (var childTag in tag.Children.ToArray())
|
||||
{
|
||||
depth++;
|
||||
Draw(childTag, ref depth);
|
||||
}
|
||||
depth++;
|
||||
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
||||
private void DrawRemoveButton(IInheritable inheritable)
|
||||
{
|
||||
|
||||
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));
|
||||
|
||||
if (ImGui.Button($"x", new Vector2(23, 23)))
|
||||
{
|
||||
inheritable.Behavior = InheritableBehavior.Inherit;
|
||||
m_PluginConfiguration.Save(m_PluginData);
|
||||
}
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PopStyleVar();
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetTooltip(Strings.Loc_Static_RemovePropertyOverride_Description);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawInheritable(string localizedStringName, InheritableValue<bool> inheritable)
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
ImGui.Indent();
|
||||
ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(180, 47));
|
||||
|
||||
ImGui.Text(Localizer.GetString(localizedStringName, false));
|
||||
DrawCheckbox("IsEnabled", false, ref inheritable.Value, () =>
|
||||
{
|
||||
m_PluginConfiguration.Save(m_PluginData);
|
||||
});
|
||||
ImGui.SameLine();
|
||||
DrawRemoveButton(inheritable);
|
||||
|
||||
ImGui.EndChild();
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
private void DrawInheritable<TEnum>(string localizedStringName, bool shouldLocalizeNames, bool shouldOrderNames, InheritableValue<TEnum> inheritable)
|
||||
where TEnum : struct, Enum
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
ImGui.Indent();
|
||||
ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(180, 47));
|
||||
|
||||
ImGui.Text(Localizer.GetString(localizedStringName, false));
|
||||
|
||||
bool isEnabled = inheritable.Behavior == InheritableBehavior.Enabled;
|
||||
DrawCheckbox("IsEnabled", false, ref isEnabled, () =>
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
inheritable.Behavior = InheritableBehavior.Enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
inheritable.Behavior = InheritableBehavior.Disabled;
|
||||
}
|
||||
m_PluginConfiguration.Save(m_PluginData);
|
||||
});
|
||||
|
||||
if (isEnabled)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
DrawComboBox(false, shouldLocalizeNames, shouldOrderNames, ref inheritable.Value, () => { m_PluginConfiguration.Save(m_PluginData); });
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
DrawRemoveButton(inheritable);
|
||||
|
||||
ImGui.EndChild();
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
private void DrawInheritable(string localizedStringName, InheritableValue<ushort> inheritable)
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
ImGui.Indent();
|
||||
ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(180, 47));
|
||||
|
||||
ImGui.Text(Localizer.GetString(localizedStringName, false));
|
||||
|
||||
bool isEnabled = inheritable.Behavior == InheritableBehavior.Enabled;
|
||||
DrawCheckbox("IsEnabled", false, ref isEnabled, () =>
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
inheritable.Behavior = InheritableBehavior.Enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
inheritable.Behavior = InheritableBehavior.Disabled;
|
||||
}
|
||||
m_PluginConfiguration.Save(m_PluginData);
|
||||
});
|
||||
|
||||
if (isEnabled)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
DrawColorButton(
|
||||
inheritable.Value.ToString(),
|
||||
UIColorHelper.ToColor(inheritable.Value),
|
||||
() =>
|
||||
{
|
||||
m_ColorPickerPopupDataContext = inheritable;
|
||||
ImGui.OpenPopup("ColorPickerPopup");
|
||||
});
|
||||
}
|
||||
|
||||
bool wasStyleConsumed = false;
|
||||
ImGui.SetNextWindowPos(ImGui.GetCursorScreenPos() + new Vector2(31, 0));
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, 0));
|
||||
if (ImGui.BeginPopup("ColorPickerPopup"))
|
||||
{
|
||||
wasStyleConsumed = true;
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
DrawUIColorPicker(
|
||||
(UIColor value) =>
|
||||
{
|
||||
if (m_ColorPickerPopupDataContext != null)
|
||||
{
|
||||
m_ColorPickerPopupDataContext.Value = (ushort)value.RowId;
|
||||
m_ColorPickerPopupDataContext = null;
|
||||
m_PluginConfiguration.Save(m_PluginData);
|
||||
}
|
||||
|
||||
ImGui.CloseCurrentPopup();
|
||||
});
|
||||
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
if (!wasStyleConsumed)
|
||||
{
|
||||
ImGui.PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
DrawRemoveButton(inheritable);
|
||||
|
||||
ImGui.EndChild();
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
private void DrawInheritable(string localizedStringName, InheritableReference<string> inheritable)
|
||||
{
|
||||
ImGui.BeginGroup();
|
||||
ImGui.Indent();
|
||||
ImGui.BeginChild(inheritable.GetHashCode().ToString(), new Vector2(180, 47));
|
||||
|
||||
ImGui.Text(Localizer.GetString(localizedStringName, false));
|
||||
|
||||
bool isEnabled = inheritable.Behavior == InheritableBehavior.Enabled;
|
||||
DrawCheckbox("IsEnabled", false, ref isEnabled, () =>
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
inheritable.Behavior = InheritableBehavior.Enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
inheritable.Behavior = InheritableBehavior.Disabled;
|
||||
}
|
||||
m_PluginConfiguration.Save(m_PluginData);
|
||||
});
|
||||
|
||||
if (isEnabled)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
DrawTextBox(localizedStringName, ref inheritable.Value, () => { m_PluginConfiguration.Save(m_PluginData); });
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
DrawRemoveButton(inheritable);
|
||||
|
||||
ImGui.EndChild();
|
||||
ImGui.EndGroup();
|
||||
}
|
||||
|
||||
private void DrawHeading(string label)
|
||||
{
|
||||
ImGui.TextColored(new Vector4(0.7f, 0.6f, 1f, 1f), label);
|
||||
}
|
||||
|
||||
private void DrawComboBox<TEnum>(bool isLabelVisible, bool shouldLocalizeNames, bool shouldOrderNames, ref TEnum currentValue, System.Action changed)
|
||||
where TEnum : Enum
|
||||
{
|
||||
if (isLabelVisible)
|
||||
{
|
||||
ImGui.Text(Localizer.GetString<TEnum>(false));
|
||||
}
|
||||
|
||||
var currentDisplayName = shouldLocalizeNames ? Localizer.GetString(currentValue, false) : currentValue.ToString();
|
||||
|
||||
ImGui.SetNextItemWidth(ImGui.CalcItemWidth());
|
||||
if (ImGui.BeginCombo($"###{currentValue.GetType().Name}", currentDisplayName))
|
||||
{
|
||||
var displayNames = Enum.GetValues(typeof(TEnum)).Cast<TEnum>()
|
||||
.Select(value => new { Value = value, DisplayName = shouldLocalizeNames ? Localizer.GetString(value, false) : value.ToString() });
|
||||
|
||||
if (shouldOrderNames)
|
||||
{
|
||||
displayNames = displayNames.OrderBy(displayEnum => displayEnum.DisplayName);
|
||||
}
|
||||
|
||||
foreach (var orderedDisplayName in displayNames)
|
||||
{
|
||||
bool isSelected = orderedDisplayName.Value.Equals(currentValue);
|
||||
if (ImGui.Selectable(orderedDisplayName.DisplayName, isSelected))
|
||||
{
|
||||
currentValue = orderedDisplayName.Value;
|
||||
changed();
|
||||
}
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
ImGui.SetItemDefaultFocus();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered() && shouldLocalizeNames)
|
||||
{
|
||||
ImGui.SetTooltip(Localizer.GetString(orderedDisplayName.Value, true));
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered() && shouldLocalizeNames)
|
||||
{
|
||||
ImGui.SetTooltip(Localizer.GetString(currentValue, true));
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCheckbox(string localizedStringName, bool hasLabel, ref bool isChecked, System.Action changed)
|
||||
{
|
||||
if (ImGui.Checkbox(hasLabel ? Localizer.GetString(localizedStringName, false) : $"###{Localizer.GetString(localizedStringName, false)}", ref isChecked))
|
||||
{
|
||||
changed();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetTooltip(Localizer.GetString(localizedStringName, true));
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawColorButton(string colorId, Vector4 color, System.Action clicked)
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, color);
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, color);
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonActive, color);
|
||||
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)))
|
||||
{
|
||||
clicked();
|
||||
}
|
||||
ImGui.PopStyleVar();
|
||||
ImGui.PopStyleVar();
|
||||
ImGui.PopStyleVar();
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetTooltip(colorId);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTextBox(string localizedStringName, ref string text, System.Action changed)
|
||||
{
|
||||
ImGui.SetNextItemWidth(ImGui.CalcItemWidth());
|
||||
|
||||
var oldText = text;
|
||||
ImGui.InputText($"###{localizedStringName}", ref text, 1024);
|
||||
if (text != oldText)
|
||||
{
|
||||
changed();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetTooltip(Localizer.GetString(localizedStringName, true));
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawUIColorPicker(System.Action<UIColor> colorSelected)
|
||||
{
|
||||
const int columnCount = 12;
|
||||
|
||||
int currentColumn = 0;
|
||||
foreach (var uiColor in UIColorHelper.UIColors)
|
||||
{
|
||||
if (currentColumn % columnCount != 0)
|
||||
{
|
||||
ImGui.SameLine(0, 0);
|
||||
}
|
||||
|
||||
DrawColorButton(uiColor.RowId.ToString(), UIColorHelper.ToColor(uiColor), () => { colorSelected(uiColor); });
|
||||
currentColumn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
99
PlayerTags/PluginData.cs
Normal file
99
PlayerTags/PluginData.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using Dalamud.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PlayerTags
|
||||
{
|
||||
public class PluginData
|
||||
{
|
||||
public DefaultPluginData Default;
|
||||
public Tag AllTags;
|
||||
public Tag AllRoleTags;
|
||||
public Dictionary<Role, Tag> RoleTags;
|
||||
public Dictionary<string, Tag> JobTags;
|
||||
public Tag AllCustomTags;
|
||||
public List<Tag> CustomTags;
|
||||
|
||||
public PluginData()
|
||||
{
|
||||
Default = new DefaultPluginData();
|
||||
AllTags = new Tag(new LocalizedPluginString(nameof(AllTags)));
|
||||
AllRoleTags = new Tag(new LocalizedPluginString(nameof(AllRoleTags)));
|
||||
RoleTags = new Dictionary<Role, Tag>();
|
||||
JobTags = new Dictionary<string, Tag>();
|
||||
AllCustomTags = new Tag(new LocalizedPluginString(nameof(AllCustomTags)));
|
||||
CustomTags = new List<Tag>();
|
||||
}
|
||||
|
||||
public void Initialize(DataManager dataManager, PluginConfiguration pluginConfiguration)
|
||||
{
|
||||
Default.Initialize(dataManager);
|
||||
|
||||
// Set the default changes and saved changes
|
||||
AllTags.SetChanges(Default.AllTagsChanges);
|
||||
AllTags.SetChanges(pluginConfiguration.AllTagsChanges);
|
||||
|
||||
AllRoleTags.SetChanges(Default.AllRoleTagsChanges);
|
||||
AllRoleTags.SetChanges(pluginConfiguration.AllRoleTagsChanges);
|
||||
|
||||
foreach (var role in Enum.GetValues<Role>())
|
||||
{
|
||||
RoleTags[role] = new Tag(new LocalizedPluginString(Localizer.GetName(role)));
|
||||
|
||||
if (Default.RoleTagsChanges.TryGetValue(role, out var defaultChanges))
|
||||
{
|
||||
RoleTags[role].SetChanges(defaultChanges);
|
||||
}
|
||||
|
||||
if (pluginConfiguration.RoleTagsChanges.TryGetValue(role, out var savedChanges))
|
||||
{
|
||||
RoleTags[role].SetChanges(savedChanges);
|
||||
}
|
||||
}
|
||||
|
||||
JobTags = new Dictionary<string, Tag>();
|
||||
foreach ((var jobAbbreviation, var role) in Default.RolesByJobAbbreviation)
|
||||
{
|
||||
JobTags[jobAbbreviation] = new Tag(new LiteralPluginString(jobAbbreviation));
|
||||
|
||||
if (Default.JobTagsChanges.TryGetValue(jobAbbreviation, out var defaultChanges))
|
||||
{
|
||||
JobTags[jobAbbreviation].SetChanges(defaultChanges);
|
||||
}
|
||||
|
||||
if (pluginConfiguration.JobTagsChanges.TryGetValue(jobAbbreviation, out var savedChanges))
|
||||
{
|
||||
JobTags[jobAbbreviation].SetChanges(savedChanges);
|
||||
}
|
||||
}
|
||||
|
||||
AllCustomTags.SetChanges(Default.AllCustomTagsChanges);
|
||||
AllCustomTags.SetChanges(pluginConfiguration.AllCustomTagsChanges);
|
||||
|
||||
foreach (var savedChanges in pluginConfiguration.CustomTagsChanges)
|
||||
{
|
||||
var tag = new Tag(new LocalizedPluginString(nameof(CustomTags)));
|
||||
tag.SetChanges(savedChanges);
|
||||
CustomTags.Add(tag);
|
||||
}
|
||||
|
||||
// Set up the inheritance heirarchy
|
||||
AllRoleTags.Parent = AllTags;
|
||||
foreach ((var role, var roleTag) in RoleTags)
|
||||
{
|
||||
roleTag.Parent = AllRoleTags;
|
||||
}
|
||||
|
||||
foreach ((var jobAbbreviation, var jobTag) in JobTags)
|
||||
{
|
||||
jobTag.Parent = RoleTags[Default.RolesByJobAbbreviation[jobAbbreviation]];
|
||||
}
|
||||
|
||||
AllCustomTags.Parent = AllTags;
|
||||
foreach (var tag in CustomTags)
|
||||
{
|
||||
tag.Parent = AllCustomTags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 87 KiB |
BIN
PlayerTags/Resources/Promo/Chat_2.png
Normal file
BIN
PlayerTags/Resources/Promo/Chat_2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
BIN
PlayerTags/Resources/Promo/Icon.png
Normal file
BIN
PlayerTags/Resources/Promo/Icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 847 KiB After Width: | Height: | Size: 699 KiB |
700
PlayerTags/Resources/Strings.Designer.cs
generated
700
PlayerTags/Resources/Strings.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@@ -120,256 +120,241 @@
|
||||
<data name="Loc_Static_PluginName" xml:space="preserve">
|
||||
<value>Player Tags</value>
|
||||
</data>
|
||||
<data name="Loc_Static_General" xml:space="preserve">
|
||||
<value>General</value>
|
||||
</data>
|
||||
<data name="Loc_Static_Development" xml:space="preserve">
|
||||
<value>Development</value>
|
||||
</data>
|
||||
<data name="Loc_Static_CustomTags" xml:space="preserve">
|
||||
<value>Custom tags</value>
|
||||
</data>
|
||||
<data name="Loc_Static_AddCustomTag" xml:space="preserve">
|
||||
<value>Add custom tag</value>
|
||||
</data>
|
||||
<data name="Loc_Static_RemoveCustomTag" xml:space="preserve">
|
||||
<value>Remove custom tag</value>
|
||||
</data>
|
||||
<data name="Loc_Static_NoCustomTagsAdded" xml:space="preserve">
|
||||
<value>No custom tags added.</value>
|
||||
</data>
|
||||
<data name="Loc_Static_RoleAndJobTags" xml:space="preserve">
|
||||
<value>Role and job tags</value>
|
||||
</data>
|
||||
<data name="Loc_Static_Roles" xml:space="preserve">
|
||||
<value>Roles</value>
|
||||
</data>
|
||||
<data name="Loc_Static_Jobs" xml:space="preserve">
|
||||
<value>Jobs</value>
|
||||
</data>
|
||||
<data name="Loc_Static_ChatTag" xml:space="preserve">
|
||||
<value>Chat tag</value>
|
||||
</data>
|
||||
<data name="Loc_Static_NameplateTag" xml:space="preserve">
|
||||
<value>Nameplate tag</value>
|
||||
<data name="Loc_Static_WarningMessage" xml:space="preserve">
|
||||
<value>This plugin can modify nameplates. When combined with other plugins that modify nameplates, you are likely to see unexpected behavior.</value>
|
||||
</data>
|
||||
<data name="Loc_Static_Nameplates" xml:space="preserve">
|
||||
<value>Nameplates</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateFreeCompanyVisibility" xml:space="preserve">
|
||||
<value>Free company visibility</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateFreeCompanyVisibility_Default" xml:space="preserve">
|
||||
<value>Default</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateFreeCompanyVisibility_Default_Description" xml:space="preserve">
|
||||
<value>The free company on nameplates will only be visible when the character is in a free company.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateFreeCompanyVisibility_Never" xml:space="preserve">
|
||||
<value>Never visible</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateFreeCompanyVisibility_Never_Description" xml:space="preserve">
|
||||
<value>The free company on nameplates will never be visible.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitleVisibility" xml:space="preserve">
|
||||
<value>Title visibility</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitleVisibility_Always" xml:space="preserve">
|
||||
<value>Always visible</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitleVisibility_Always_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will always be visible, even when the character does not have a title.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitleVisibility_Default" xml:space="preserve">
|
||||
<value>Default</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitleVisibility_Default_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will only be visible when the character has a title.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitleVisibility_Never" xml:space="preserve">
|
||||
<value>Never visible</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitleVisibility_Never_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will never visible.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitleVisibility_WhenHasTags" xml:space="preserve">
|
||||
<value>Only visible when it has tags</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitleVisibility_WhenHasTags_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will only be visible when it has tags.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitlePosition" xml:space="preserve">
|
||||
<value>Title position</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitlePosition_AlwaysAboveName" xml:space="preserve">
|
||||
<value>Always above name</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitlePosition_AlwaysAboveName_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will always be positioned above the name.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitlePosition_AlwaysBelowName" xml:space="preserve">
|
||||
<value>Always below name</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitlePosition_AlwaysBelowName_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will always be positioned below the name.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitlePosition_Default" xml:space="preserve">
|
||||
<value>Default</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateTitlePosition_Default_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will be positioned depending on the title.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_FreeCompany" xml:space="preserve">
|
||||
<value>Free company</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_FreeCompany_Description" xml:space="preserve">
|
||||
<value>The free company element on nameplates.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_Name" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_Name_Description" xml:space="preserve">
|
||||
<value>The name element on nameplates.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_Title" xml:space="preserve">
|
||||
<value>Title</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_Title_Description" xml:space="preserve">
|
||||
<value>The title element on nameplates.</value>
|
||||
</data>
|
||||
<data name="Loc_Static_Development" xml:space="preserve">
|
||||
<value>Development</value>
|
||||
</data>
|
||||
<data name="Loc_IsPlayerNameRandomlyGenerated" xml:space="preserve">
|
||||
<value>Randomly generate player names</value>
|
||||
</data>
|
||||
<data name="Loc_IsPlayerNameRandomlyGenerated_Description" xml:space="preserve">
|
||||
<value>Use tags to replace every player's name with a randomly generated one. Helpful for preserving anonymity when taking screenshots.</value>
|
||||
</data>
|
||||
<data name="Loc_RoleOverrideConfig_IsEnabled" xml:space="preserve">
|
||||
<value>Enabled</value>
|
||||
<data name="Loc_Static_Tags" xml:space="preserve">
|
||||
<value>Tags</value>
|
||||
</data>
|
||||
<data name="Loc_RoleOverrideConfig_IsEnabled_Description" xml:space="preserve">
|
||||
<value>Enable the tag for this role.</value>
|
||||
<data name="Loc_AllTags" xml:space="preserve">
|
||||
<value>All</value>
|
||||
</data>
|
||||
<data name="Loc_RoleOverrideConfig_Name" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="Loc_RoleOverrideConfig_Name_Description" xml:space="preserve">
|
||||
<value>The name to use for this role when the format is set to use role names.</value>
|
||||
</data>
|
||||
<data name="Loc_CustomColorConfig_IsEnabled" xml:space="preserve">
|
||||
<value>Color</value>
|
||||
</data>
|
||||
<data name="Loc_CustomColorConfig_IsEnabled_Description" xml:space="preserve">
|
||||
<value>Enable a custom color.</value>
|
||||
</data>
|
||||
<data name="Loc_CustomTagConfig_Name" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="Loc_CustomTagConfig_Name_Description" xml:space="preserve">
|
||||
<value>The name of the tag to display.</value>
|
||||
</data>
|
||||
<data name="Loc_CustomTagConfig_FormattedGameObjectNames" xml:space="preserve">
|
||||
<value>Apply to game object names</value>
|
||||
</data>
|
||||
<data name="Loc_CustomTagConfig_FormattedGameObjectNames_Description" xml:space="preserve">
|
||||
<value>A list of game object names to apply the tag to, separated by commas. E.g. "Cloud Strife, Tifa Lockhart"</value>
|
||||
</data>
|
||||
<data name="Loc_FreeCompanyNameplateVisibility" xml:space="preserve">
|
||||
<value>Free company visibility</value>
|
||||
</data>
|
||||
<data name="Loc_FreeCompanyNameplateVisibility_Description" xml:space="preserve">
|
||||
<value>The visibility of the free company on nameplates.</value>
|
||||
</data>
|
||||
<data name="Loc_FreeCompanyNameplateVisibility_Default" xml:space="preserve">
|
||||
<value>Default</value>
|
||||
</data>
|
||||
<data name="Loc_FreeCompanyNameplateVisibility_Default_Description" xml:space="preserve">
|
||||
<value>The free company on nameplates will only be visible when the character is in a free company.</value>
|
||||
</data>
|
||||
<data name="Loc_FreeCompanyNameplateVisibility_Never" xml:space="preserve">
|
||||
<value>Never visible</value>
|
||||
</data>
|
||||
<data name="Loc_FreeCompanyNameplateVisibility_Never_Description" xml:space="preserve">
|
||||
<value>The free company on nameplates will never be visible.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement" xml:space="preserve">
|
||||
<value>Data element</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_Description" xml:space="preserve">
|
||||
<value>A data element on nameplates.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_FreeCompany" xml:space="preserve">
|
||||
<value>Free company</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_FreeCompany_Description" xml:space="preserve">
|
||||
<value>The free company on nameplates.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_Name" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_Name_Description" xml:space="preserve">
|
||||
<value>The name on nameplates.</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_Title" xml:space="preserve">
|
||||
<value>Title</value>
|
||||
</data>
|
||||
<data name="Loc_NameplateElement_Title_Description" xml:space="preserve">
|
||||
<value>The title on nameplates.</value>
|
||||
</data>
|
||||
<data name="Loc_RoleTagFormat" xml:space="preserve">
|
||||
<value>Tag format</value>
|
||||
</data>
|
||||
<data name="Loc_RoleTagFormat_Description" xml:space="preserve">
|
||||
<value>The format that the role tag should be displayed as.</value>
|
||||
</data>
|
||||
<data name="Loc_RoleTagFormat_AbbreviatedJobName" xml:space="preserve">
|
||||
<value>Abbreviated job name</value>
|
||||
</data>
|
||||
<data name="Loc_RoleTagFormat_JobName" xml:space="preserve">
|
||||
<value>Job name</value>
|
||||
</data>
|
||||
<data name="Loc_RoleTagFormat_AbbreviatedJobName_Description" xml:space="preserve">
|
||||
<value>The tag will appear as an abbreviated job name, e.g. SAM, WHM, GNB.</value>
|
||||
</data>
|
||||
<data name="Loc_RoleTagFormat_JobName_Description" xml:space="preserve">
|
||||
<value>The tag will appear as a job name in English, e.g. Samurai, White Mage, Gunbreaker.</value>
|
||||
</data>
|
||||
<data name="Loc_RoleTagFormat_RoleName" xml:space="preserve">
|
||||
<value>Role name</value>
|
||||
</data>
|
||||
<data name="Loc_RoleTagFormat_RoleName_Description" xml:space="preserve">
|
||||
<value>The tag will appear as the configured role name, e.g. DPS, Healer, Tank.</value>
|
||||
</data>
|
||||
<data name="Loc_Role" xml:space="preserve">
|
||||
<value>Role</value>
|
||||
</data>
|
||||
<data name="Loc_Role_Description" xml:space="preserve">
|
||||
<value>A character role.</value>
|
||||
</data>
|
||||
<data name="Loc_Role_DPS" xml:space="preserve">
|
||||
<value>DPS</value>
|
||||
</data>
|
||||
<data name="Loc_Role_DPS_Description" xml:space="preserve">
|
||||
<value>The DPS role.</value>
|
||||
</data>
|
||||
<data name="Loc_Role_Healer" xml:space="preserve">
|
||||
<value>Healer</value>
|
||||
</data>
|
||||
<data name="Loc_Role_Healer_Description" xml:space="preserve">
|
||||
<value>The healer role.</value>
|
||||
<data name="Loc_AllRoleTags" xml:space="preserve">
|
||||
<value>All Roles</value>
|
||||
</data>
|
||||
<data name="Loc_Role_LandHand" xml:space="preserve">
|
||||
<value>Land/Hand</value>
|
||||
</data>
|
||||
<data name="Loc_Role_LandHand_Description" xml:space="preserve">
|
||||
<value>The land/hand role.</value>
|
||||
</data>
|
||||
<data name="Loc_Role_Tank" xml:space="preserve">
|
||||
<value>Tank</value>
|
||||
</data>
|
||||
<data name="Loc_Role_Tank_Description" xml:space="preserve">
|
||||
<value>The tank role.</value>
|
||||
<data name="Loc_Role_Healer" xml:space="preserve">
|
||||
<value>Healer</value>
|
||||
</data>
|
||||
<data name="Loc_StringPosition" xml:space="preserve">
|
||||
<value>String position</value>
|
||||
<data name="Loc_Role_DPS" xml:space="preserve">
|
||||
<value>DPS</value>
|
||||
</data>
|
||||
<data name="Loc_StringPosition_Description" xml:space="preserve">
|
||||
<value>The position in a string where tags will be displayed.</value>
|
||||
<data name="Loc_AllCustomTags" xml:space="preserve">
|
||||
<value>All Custom</value>
|
||||
</data>
|
||||
<data name="Loc_StringPosition_After" xml:space="preserve">
|
||||
<data name="Loc_CustomTags" xml:space="preserve">
|
||||
<value>Custom</value>
|
||||
</data>
|
||||
<data name="Loc_IsEnabled_Description" xml:space="preserve">
|
||||
<value>Enable the value of this override.</value>
|
||||
</data>
|
||||
<data name="Loc_Static_AddPropertyOverride_Description" xml:space="preserve">
|
||||
<value>Add an override.</value>
|
||||
</data>
|
||||
<data name="Loc_Static_RemovePropertyOverride_Description" xml:space="preserve">
|
||||
<value>Remove this override. The value will be inherited.</value>
|
||||
</data>
|
||||
<data name="Loc_Static_AddCustomTag" xml:space="preserve">
|
||||
<value>Add a custom tag</value>
|
||||
</data>
|
||||
<data name="Loc_Static_RemoveCustomTag" xml:space="preserve">
|
||||
<value>Remove this custom tag</value>
|
||||
</data>
|
||||
|
||||
<data name="Loc_Icon" xml:space="preserve">
|
||||
<value>Icon</value>
|
||||
</data>
|
||||
<data name="Loc_Icon_Description" xml:space="preserve">
|
||||
<value>The icon that will be displayed in the tag.</value>
|
||||
</data>
|
||||
<data name="Loc_IsIconVisibleInChat" xml:space="preserve">
|
||||
<value>Icon visible in chat</value>
|
||||
</data>
|
||||
<data name="Loc_IsIconVisibleInChat_Description" xml:space="preserve">
|
||||
<value>Whether the icon is visible in the tag in chat.</value>
|
||||
</data>
|
||||
<data name="Loc_IsIconVisibleInNameplates" xml:space="preserve">
|
||||
<value>Icon visible in nameplates</value>
|
||||
</data>
|
||||
<data name="Loc_IsIconVisibleInNameplates_Description" xml:space="preserve">
|
||||
<value>Whether the icon is visible in the tag in nameplates.</value>
|
||||
</data>
|
||||
|
||||
<data name="Loc_Text" xml:space="preserve">
|
||||
<value>Text</value>
|
||||
</data>
|
||||
<data name="Loc_Text_Description" xml:space="preserve">
|
||||
<value>The text that will be displayed in the tag.</value>
|
||||
</data>
|
||||
<data name="Loc_TextColor" xml:space="preserve">
|
||||
<value>Text color</value>
|
||||
</data>
|
||||
<data name="Loc_TextColor_Description" xml:space="preserve">
|
||||
<value>The color of the text in the tag.</value>
|
||||
</data>
|
||||
<data name="Loc_IsTextItalic" xml:space="preserve">
|
||||
<value>Text italic</value>
|
||||
</data>
|
||||
<data name="Loc_IsTextItalic_Description" xml:space="preserve">
|
||||
<value>Whether the text in the tag is italic.</value>
|
||||
</data>
|
||||
<data name="Loc_IsTextVisibleInChat" xml:space="preserve">
|
||||
<value>Text visible in chat</value>
|
||||
</data>
|
||||
<data name="Loc_IsTextVisibleInChat_Description" xml:space="preserve">
|
||||
<value>Whether the text is visible in the tag in chat.</value>
|
||||
</data>
|
||||
<data name="Loc_IsTextVisibleInNameplates" xml:space="preserve">
|
||||
<value>Text visible in nameplates</value>
|
||||
</data>
|
||||
<data name="Loc_IsTextVisibleInNameplates_Description" xml:space="preserve">
|
||||
<value>Whether the text is visible in the tag in nameplates.</value>
|
||||
</data>
|
||||
|
||||
<data name="Loc_TagPositionInChat" xml:space="preserve">
|
||||
<value>Tag position in chat</value>
|
||||
</data>
|
||||
<data name="Loc_TagPositionInChat_Description" xml:space="preserve">
|
||||
<value>Where the tag should be positioned in chat.</value>
|
||||
</data>
|
||||
<data name="Loc_TagPositionInNameplates" xml:space="preserve">
|
||||
<value>Tag position in nameplates</value>
|
||||
</data>
|
||||
<data name="Loc_TagPositionInNameplates_Description" xml:space="preserve">
|
||||
<value>Where the tag should be positioned in nameplates.</value>
|
||||
</data>
|
||||
<data name="Loc_TagTargetInNameplates" xml:space="preserve">
|
||||
<value>Tag target in nameplates</value>
|
||||
</data>
|
||||
<data name="Loc_TagTargetInNameplates_Description" xml:space="preserve">
|
||||
<value>The element that the tag should target in nameplates.</value>
|
||||
</data>
|
||||
|
||||
<data name="Loc_GameObjectNamesToApplyTo" xml:space="preserve">
|
||||
<value>Game object names to apply to</value>
|
||||
</data>
|
||||
<data name="Loc_GameObjectNamesToApplyTo_Description" xml:space="preserve">
|
||||
<value>A list of game object names to always apply tags to, separated by commas or semi-colons. E.g. "Cloud Strife, Tifa Lockhart".</value>
|
||||
</data>
|
||||
|
||||
<data name="Loc_TagPosition_After" xml:space="preserve">
|
||||
<value>After</value>
|
||||
</data>
|
||||
<data name="Loc_StringPosition_After_Description" xml:space="preserve">
|
||||
<value>The tag will be positioned after the data element.</value>
|
||||
<data name="Loc_TagPosition_After_Description" xml:space="preserve">
|
||||
<value>Display the tag after the target element.</value>
|
||||
</data>
|
||||
<data name="Loc_StringPosition_Before" xml:space="preserve">
|
||||
<data name="Loc_TagPosition_Before" xml:space="preserve">
|
||||
<value>Before</value>
|
||||
</data>
|
||||
<data name="Loc_StringPosition_Before_Description" xml:space="preserve">
|
||||
<value>The tag will be positioned before the data element.</value>
|
||||
<data name="Loc_TagPosition_Before_Description" xml:space="preserve">
|
||||
<value>Display the tag before the target element.</value>
|
||||
</data>
|
||||
<data name="Loc_StringPosition_None" xml:space="preserve">
|
||||
<value>None</value>
|
||||
</data>
|
||||
<data name="Loc_StringPosition_None_Description" xml:space="preserve">
|
||||
<value>The tag will not be positioned in the string.</value>
|
||||
</data>
|
||||
<data name="Loc_StringPosition_Replace" xml:space="preserve">
|
||||
<data name="Loc_TagPosition_Replace" xml:space="preserve">
|
||||
<value>Replace</value>
|
||||
</data>
|
||||
<data name="Loc_StringPosition_Replace_Description" xml:space="preserve">
|
||||
<value>The tag will replace its data element.</value>
|
||||
<data name="Loc_TagPosition_Replace_Description" xml:space="preserve">
|
||||
<value>Replace the target element with the tag.</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplatePosition" xml:space="preserve">
|
||||
<value>Title position</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplatePosition_Description" xml:space="preserve">
|
||||
<value>The position of the title on nameplates.</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplatePosition_AlwaysAboveName" xml:space="preserve">
|
||||
<value>Always above the name</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplatePosition_AlwaysAboveName_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will always be positioned above the name.</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplatePosition_AlwaysBelowName" xml:space="preserve">
|
||||
<value>Always below the name</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplatePosition_AlwaysBelowName_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will always be positioned below the name.</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplatePosition_Default" xml:space="preserve">
|
||||
<value>Default</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplatePosition_Default_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will be positioned depending on the title.</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplateVisibility" xml:space="preserve">
|
||||
<value>Title visibility</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplateVisibility_Description" xml:space="preserve">
|
||||
<value>The visibility of the title on nameplates.</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplateVisibility_Always" xml:space="preserve">
|
||||
<value>Always</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplateVisibility_Always_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will always be visible, even when the character does not have a title.</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplateVisibility_Default" xml:space="preserve">
|
||||
<value>Default</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplateVisibility_Default_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will only be visible when the character has a title.</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplateVisibility_Never" xml:space="preserve">
|
||||
<value>Never</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplateVisibility_Never_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will never visible.</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplateVisibility_WhenHasTags" xml:space="preserve">
|
||||
<value>When it has tags</value>
|
||||
</data>
|
||||
<data name="Loc_TitleNameplateVisibility_WhenHasTags_Description" xml:space="preserve">
|
||||
<value>The title on nameplates will only be visible when it has tags.</value>
|
||||
|
||||
<data name="Loc_IsEnabled" xml:space="preserve">
|
||||
<value>Enabled</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -189,6 +189,7 @@ beta
|
||||
better
|
||||
bewildered
|
||||
bewitched
|
||||
biblical
|
||||
big
|
||||
biggish
|
||||
bigheaded
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PlayerTags.Config
|
||||
namespace PlayerTags
|
||||
{
|
||||
public enum Role
|
||||
{
|
||||
140
PlayerTags/Tag.cs
Normal file
140
PlayerTags/Tag.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PlayerTags
|
||||
{
|
||||
public class Tag
|
||||
{
|
||||
public IPluginString Name { get; init; }
|
||||
|
||||
private Tag? m_Parent = null;
|
||||
public Tag? Parent
|
||||
{
|
||||
get => m_Parent;
|
||||
set
|
||||
{
|
||||
if (m_Parent != value)
|
||||
{
|
||||
if (m_Parent != null)
|
||||
{
|
||||
if (m_Parent.Children.Contains(this))
|
||||
{
|
||||
m_Parent.Children.Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
m_Parent = value;
|
||||
if (m_Parent != null)
|
||||
{
|
||||
m_Parent.Children.Add(this);
|
||||
foreach ((var name, IInheritable inheritable) in Inheritables)
|
||||
{
|
||||
inheritable.Parent = m_Parent.Inheritables[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Tag> Children { get; } = new List<Tag>();
|
||||
|
||||
private Dictionary<string, IInheritable>? m_Inheritables = null;
|
||||
public Dictionary<string, IInheritable> Inheritables
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Inheritables == null)
|
||||
{
|
||||
m_Inheritables = new Dictionary<string, IInheritable>();
|
||||
|
||||
var inheritableFields = GetType().GetFields().Where(field => typeof(IInheritable).IsAssignableFrom(field.FieldType));
|
||||
foreach (var inheritableField in inheritableFields)
|
||||
{
|
||||
IInheritable? inheritable = inheritableField.GetValue(this) as IInheritable;
|
||||
if (inheritable != null)
|
||||
{
|
||||
Inheritables[inheritableField.Name] = inheritable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_Inheritables!;
|
||||
}
|
||||
}
|
||||
|
||||
public InheritableValue<BitmapFontIcon> Icon = new InheritableValue<BitmapFontIcon>(BitmapFontIcon.Aethernet);
|
||||
public InheritableValue<bool> IsIconVisibleInChat = new InheritableValue<bool>(false);
|
||||
public InheritableValue<bool> IsIconVisibleInNameplates = new InheritableValue<bool>(false);
|
||||
|
||||
public InheritableReference<string> Text = new InheritableReference<string>("");
|
||||
public InheritableValue<ushort> TextColor = new InheritableValue<ushort>(6);
|
||||
public InheritableValue<bool> IsTextItalic = new InheritableValue<bool>(false);
|
||||
public InheritableValue<bool> IsTextVisibleInChat = new InheritableValue<bool>(false);
|
||||
public InheritableValue<bool> IsTextVisibleInNameplates = new InheritableValue<bool>(false);
|
||||
|
||||
public InheritableValue<TagPosition> TagPositionInChat = new InheritableValue<TagPosition>(TagPosition.Before);
|
||||
public InheritableValue<TagPosition> TagPositionInNameplates = new InheritableValue<TagPosition>(TagPosition.Before);
|
||||
public InheritableValue<NameplateElement> TagTargetInNameplates = new InheritableValue<NameplateElement>(NameplateElement.Name);
|
||||
|
||||
public InheritableReference<string> GameObjectNamesToApplyTo = new InheritableReference<string>("");
|
||||
|
||||
private string[] CleanGameObjectNamesToApplyTo
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GameObjectNamesToApplyTo == null || GameObjectNamesToApplyTo.InheritedValue == null)
|
||||
{
|
||||
return new string[] { };
|
||||
}
|
||||
|
||||
return GameObjectNamesToApplyTo.InheritedValue.Split(';', ',').Select(gameObjectName => gameObjectName.ToLower().Trim()).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public Tag(IPluginString name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public bool IncludesGameObjectNameToApplyTo(string gameObjectName)
|
||||
{
|
||||
return CleanGameObjectNamesToApplyTo.Contains(gameObjectName.ToLower());
|
||||
}
|
||||
|
||||
public Dictionary<string, InheritableData> GetChanges(Dictionary<string, InheritableData>? defaultChanges = null)
|
||||
{
|
||||
Dictionary<string, InheritableData> changes = new Dictionary<string, InheritableData>();
|
||||
|
||||
foreach ((var name, var inheritable) in Inheritables)
|
||||
{
|
||||
// If there's a default for this name, only set the value if it's different from the default
|
||||
if (defaultChanges != null && defaultChanges.TryGetValue(name, out var defaultInheritableData))
|
||||
{
|
||||
var inheritableData = inheritable.GetData();
|
||||
if (inheritableData.Behavior != defaultInheritableData.Behavior ||
|
||||
!inheritableData.Value.Equals(defaultInheritableData.Value))
|
||||
{
|
||||
changes[name] = inheritable.GetData();
|
||||
}
|
||||
}
|
||||
// If there's no default, then only set the value if it's not inherited
|
||||
else if (inheritable.Behavior != InheritableBehavior.Inherit)
|
||||
{
|
||||
changes[name] = inheritable.GetData();
|
||||
}
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
public void SetChanges(Dictionary<string, InheritableData> changes)
|
||||
{
|
||||
foreach ((var name, var inheritableData) in changes)
|
||||
{
|
||||
Inheritables[name].SetData(inheritableData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
PlayerTags/TagPosition.cs
Normal file
9
PlayerTags/TagPosition.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace PlayerTags
|
||||
{
|
||||
public enum TagPosition
|
||||
{
|
||||
Before,
|
||||
After,
|
||||
Replace
|
||||
}
|
||||
}
|
||||
8
PlayerTags/TagTarget.cs
Normal file
8
PlayerTags/TagTarget.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace PlayerTags
|
||||
{
|
||||
public enum TagTarget
|
||||
{
|
||||
Chat,
|
||||
Nameplate
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user