Files
HSUI/Interface/Nameplates/NameplateConfig.cs
T
KnackAtNite 95c42af5b8 Combo highlight config, tooltips, nameplates, hotbars fixes
- Combo highlight: configurable color, glow, line style (solid/dashed/dotted), thickness
- Tooltips: font selection, scaling slider, improved wrap/cramping handling
- Nameplates: custom quest icons with config, position smoothing fix for jitter
- Hotbars: hide keybinds on empty slots, combo highlight within icon bounds
- HudHelper: restore default nameplates on plugin disable

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-31 02:05:30 -05:00

799 lines
31 KiB
C#

using HSUI.Config;
using HSUI.Config.Attributes;
using HSUI.Enums;
using HSUI.Helpers;
using HSUI.Interface.Bars;
using HSUI.Interface.StatusEffects;
using System;
using System.Numerics;
namespace HSUI.Interface.GeneralElements
{
public enum NameplatesOcclusionMode
{
None = 0,
Simple = 1,
Full
};
public enum NameplatesOcclusionType
{
Walls = 0,
WallsAndObjects = 1
};
[DisableParentSettings("Strata", "Position")]
[Section("Nameplates")]
[SubSection("General", 0)]
public class NameplatesGeneralConfig : MovablePluginConfigObject
{
public new static NameplatesGeneralConfig DefaultConfig() => new NameplatesGeneralConfig();
[Combo("Occlusion Mode", new string[] { "Disabled", "Simple", "Full" }, help = "This controls wheter you'll see nameplates through walls and objects.\n\nDisabled: Nameplates will always be seen for units in range.\nSimple: Uses simple calculations to check if a nameplate is being covered by walls or objects. Use this for better performance.\nFull: Uses more complex calculations to check if a nameplate is being covered by walls or objects. Use this for better results.")]
[Order(10)]
public NameplatesOcclusionMode OcclusionMode = NameplatesOcclusionMode.Full;
[Combo("Occlusion Type", new string[] { "Walls", "Walls and Objects" }, help = "This controls which kind of objects will cover nameplates.\n\n\nWalls: Default setting. Only walls will cover nameplates.\n\nWalls and Objects: Some objects like columns and trees will also cover nameplates.\nThis Occlusion Type can yield some unexpected results like nameplates for NPCs behind counters not being visible.")]
[Order(11)]
public NameplatesOcclusionType OcclusionType = NameplatesOcclusionType.Walls;
[Checkbox("Try to keep nameplates on screen", spacing = true, help = "Disclaimer: HSUI relies heavily on the the game's default nameplates so this setting won't be a huge improvement.\nThis setting tries to prevent nameplates from being cutoff in the border of the screen, but it won't keep showing nameplates that the game wouldn't.")]
[Order(20)]
public bool ClampToScreen = true;
[Checkbox("Always show nameplate for target")]
[Order(21)]
public bool AlwaysShowTargetNameplate = true;
public int RaycastFlag() => OcclusionType == NameplatesOcclusionType.WallsAndObjects ? 0x2000 : 0x4000;
}
[DisableParentSettings("HideWhenInactive")]
[Section("Nameplates")]
[SubSection("Player", 0)]
public class PlayerNameplateConfig : NameplateWithPlayerBarConfig
{
public PlayerNameplateConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig,
NameplatePlayerBarConfig barConfig)
: base(position, nameLabel, titleLabelConfig, barConfig)
{
}
public new static PlayerNameplateConfig DefaultConfig()
{
return NameplatesHelper.GetNameplateWithBarConfig<PlayerNameplateConfig, NameplatePlayerBarConfig>(
0xFFD0E5E0,
0xFF30444A,
HUDConstants.DefaultPlayerNameplateBarSize
);
}
}
[DisableParentSettings("HideWhenInactive", "TitleLabelConfig", "SwapLabelsWhenNeeded")]
[Section("Nameplates")]
[SubSection("Enemies", 0)]
public class EnemyNameplateConfig : NameplateWithEnemyBarConfig
{
public EnemyNameplateConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig,
NameplateEnemyBarConfig barConfig)
: base(position, nameLabel, titleLabelConfig, barConfig)
{
}
public new static EnemyNameplateConfig DefaultConfig()
{
EnemyNameplateConfig config = NameplatesHelper.GetNameplateWithBarConfig<EnemyNameplateConfig, NameplateEnemyBarConfig>(
0xFF993535,
0xFF000000,
HUDConstants.DefaultEnemyNameplateBarSize
);
config.SwapLabelsWhenNeeded = false;
config.NameLabelConfig.Position = new Vector2(-8, 0);
config.NameLabelConfig.Text = "Lv[level] [name]";
config.NameLabelConfig.FrameAnchor = DrawAnchor.TopRight;
config.NameLabelConfig.TextAnchor = DrawAnchor.Right;
config.NameLabelConfig.Color = PluginConfigColor.FromHex(0xFFFFFFFF);
config.BarConfig.LeftLabelConfig.Enabled = true;
config.BarConfig.OnlyShowWhenNotFull = false;
// debuffs
LabelConfig durationConfig = new LabelConfig(new Vector2(0, -4), "", DrawAnchor.Bottom, DrawAnchor.Center);
durationConfig.FontID = FontsConfig.DefaultMediumFontKey;
LabelConfig stacksConfig = new LabelConfig(new Vector2(-3, 4), "", DrawAnchor.TopRight, DrawAnchor.Center);
durationConfig.FontID = FontsConfig.DefaultMediumFontKey;
stacksConfig.Color = new(Vector4.UnitW);
stacksConfig.OutlineColor = new(Vector4.One);
StatusEffectIconConfig iconConfig = new StatusEffectIconConfig(durationConfig, stacksConfig);
iconConfig.Size = new Vector2(30, 30);
iconConfig.DispellableBorderConfig.Enabled = false;
Vector2 pos = new Vector2(2, -20);
Vector2 size = new Vector2(230, 70);
EnemyNameplateStatusEffectsListConfig debuffs = new EnemyNameplateStatusEffectsListConfig(
DrawAnchor.TopLeft,
pos,
size,
false,
true,
false,
GrowthDirections.Right | GrowthDirections.Up,
iconConfig
);
debuffs.Limit = 7;
debuffs.ShowPermanentEffects = true;
debuffs.IconConfig.DispellableBorderConfig.Enabled = false;
debuffs.IconPadding = new Vector2(1, 6);
debuffs.ShowOnlyMine = true;
debuffs.ShowTooltips = false;
debuffs.DisableInteraction = true;
config.DebuffsConfig = debuffs;
// castbar
Vector2 castbarSize = new Vector2(config.BarConfig.Size.X, 10);
LabelConfig castNameConfig = new LabelConfig(new Vector2(0, -1), "", DrawAnchor.Center, DrawAnchor.Center);
castNameConfig.FontID = FontsConfig.DefaultSmallFontKey;
NumericLabelConfig castTimeConfig = new NumericLabelConfig(new Vector2(-5, 0), "", DrawAnchor.Right, DrawAnchor.Right);
castTimeConfig.Enabled = false;
castTimeConfig.FontID = FontsConfig.DefaultSmallFontKey;
castTimeConfig.NumberFormat = 1;
NameplateCastbarConfig castbarConfig = new NameplateCastbarConfig(Vector2.Zero, castbarSize, castNameConfig, castTimeConfig);
castbarConfig.HealthBarAnchor = DrawAnchor.BottomLeft;
castbarConfig.Anchor = DrawAnchor.TopLeft;
castbarConfig.ShowIcon = false;
config.CastbarConfig = castbarConfig;
return config;
}
}
[DisableParentSettings("HideWhenInactive")]
[Section("Nameplates")]
[SubSection("Party Members", 0)]
public class PartyMembersNameplateConfig : NameplateWithPlayerBarConfig
{
public PartyMembersNameplateConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig,
NameplatePlayerBarConfig barConfig)
: base(position, nameLabel, titleLabelConfig, barConfig)
{
}
public new static PartyMembersNameplateConfig DefaultConfig()
{
PartyMembersNameplateConfig config = NameplatesHelper.GetNameplateWithBarConfig<PartyMembersNameplateConfig, NameplatePlayerBarConfig>(
0xFFD0E5E0,
0xFF000000,
HUDConstants.DefaultPlayerNameplateBarSize
);
config.BarConfig.UseRoleColor = true;
config.NameLabelConfig.UseRoleColor = true;
config.TitleLabelConfig.UseRoleColor = true;
return config;
}
}
[DisableParentSettings("HideWhenInactive")]
[Section("Nameplates")]
[SubSection("Alliance Members", 0)]
public class AllianceMembersNameplateConfig : NameplateWithPlayerBarConfig
{
public AllianceMembersNameplateConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig,
NameplatePlayerBarConfig barConfig)
: base(position, nameLabel, titleLabelConfig, barConfig)
{
}
public new static AllianceMembersNameplateConfig DefaultConfig()
{
return NameplatesHelper.GetNameplateWithBarConfig<AllianceMembersNameplateConfig, NameplatePlayerBarConfig>(
0xFF99BE46,
0xFF3D4C1C,
HUDConstants.DefaultPlayerNameplateBarSize
);
}
}
[DisableParentSettings("HideWhenInactive")]
[Section("Nameplates")]
[SubSection("Friends", 0)]
public class FriendPlayerNameplateConfig : NameplateWithPlayerBarConfig
{
public FriendPlayerNameplateConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig,
NameplatePlayerBarConfig barConfig)
: base(position, nameLabel, titleLabelConfig, barConfig)
{
}
public new static FriendPlayerNameplateConfig DefaultConfig()
{
return NameplatesHelper.GetNameplateWithBarConfig<FriendPlayerNameplateConfig, NameplatePlayerBarConfig>(
0xFFEB6211,
0xFF4A2008,
HUDConstants.DefaultPlayerNameplateBarSize
);
}
}
[DisableParentSettings("HideWhenInactive")]
[Section("Nameplates")]
[SubSection("Other Players", 0)]
public class OtherPlayerNameplateConfig : NameplateWithPlayerBarConfig
{
public OtherPlayerNameplateConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig,
NameplatePlayerBarConfig barConfig)
: base(position, nameLabel, titleLabelConfig, barConfig)
{
}
public new static OtherPlayerNameplateConfig DefaultConfig()
{
return NameplatesHelper.GetNameplateWithBarConfig<OtherPlayerNameplateConfig, NameplatePlayerBarConfig>(
0xFF91BBD8,
0xFF33434E,
HUDConstants.DefaultPlayerNameplateBarSize
);
}
}
[DisableParentSettings("HideWhenInactive")]
[Section("Nameplates")]
[SubSection("Pets", 0)]
public class PetNameplateConfig : NameplateWithNPCBarConfig
{
public PetNameplateConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig,
NameplateBarConfig barConfig)
: base(position, nameLabel, titleLabelConfig, barConfig)
{
}
public new static PetNameplateConfig DefaultConfig()
{
PetNameplateConfig config = NameplatesHelper.GetNameplateWithBarConfig<PetNameplateConfig, NameplateBarConfig>(
0xFFD1E5C8,
0xFF2A2F28,
HUDConstants.DefaultPlayerNameplateBarSize
);
config.OnlyShowWhenTargeted = true;
config.SwapLabelsWhenNeeded = false;
config.NameLabelConfig.Text = "Lv[level] [name]";
config.NameLabelConfig.FontID = FontsConfig.DefaultSmallFontKey;
config.TitleLabelConfig.FontID = FontsConfig.DefaultSmallFontKey;
return config;
}
}
[DisableParentSettings("HideWhenInactive")]
[Section("Nameplates")]
[SubSection("NPCs", 0)]
public class NPCNameplateConfig : NameplateWithNPCBarConfig
{
public NPCNameplateConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig,
NameplateBarConfig barConfig)
: base(position, nameLabel, titleLabelConfig, barConfig)
{
}
public new static NPCNameplateConfig DefaultConfig()
{
NPCNameplateConfig config = NameplatesHelper.GetNameplateWithBarConfig<NPCNameplateConfig, NameplateBarConfig>(
0xFFD1E5C8,
0xFF3A4b1E,
HUDConstants.DefaultPlayerNameplateBarSize
);
config.NameLabelConfig.Position = new Vector2(0, -20);
config.TitleLabelConfig.Position = Vector2.Zero;
return config;
}
}
[DisableParentSettings("HideWhenInactive", "SwapLabelsWhenNeeded")]
[Section("Nameplates")]
[SubSection("Minions", 0)]
public class MinionNPCNameplateConfig : NameplateConfig
{
public MinionNPCNameplateConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig)
: base(position, nameLabel, titleLabelConfig)
{
}
public new static MinionNPCNameplateConfig DefaultConfig()
{
MinionNPCNameplateConfig config = NameplatesHelper.GetNameplateConfig<MinionNPCNameplateConfig>(0xFFFFFFFF, 0xFF000000);
config.OnlyShowWhenTargeted = true;
config.SwapLabelsWhenNeeded = false;
config.NameLabelConfig.Position = new Vector2(0, -17);
config.NameLabelConfig.FontID = FontsConfig.DefaultSmallFontKey;
config.TitleLabelConfig.Position = new Vector2(0, 0);
config.TitleLabelConfig.FontID = FontsConfig.DefaultSmallFontKey;
return config;
}
}
[DisableParentSettings("HideWhenInactive", "SwapLabelsWhenNeeded")]
[Section("Nameplates")]
[SubSection("Objects", 0)]
public class ObjectsNameplateConfig : NameplateConfig
{
public ObjectsNameplateConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig)
: base(position, nameLabel, titleLabelConfig)
{
}
public new static ObjectsNameplateConfig DefaultConfig()
{
ObjectsNameplateConfig config = NameplatesHelper.GetNameplateConfig<ObjectsNameplateConfig>(0xFFFFFFFF, 0xFF000000);
config.SwapLabelsWhenNeeded = false;
return config;
}
}
public class NameplateConfig : MovablePluginConfigObject
{
[Checkbox("Only show when targeted")]
[Order(1)]
public bool OnlyShowWhenTargeted = false;
[Checkbox("Swap Name and Title labels when needed", spacing = true, help = "This will swap the contents of these labels depending on if the title goes before or after the name of a player.")]
[Order(20)]
public bool SwapLabelsWhenNeeded = true;
[NestedConfig("Name Label", 21)]
public EditableLabelConfig NameLabelConfig = null!;
[NestedConfig("Title Label", 22)]
public EditableNonFormattableLabelConfig TitleLabelConfig = null!;
[NestedConfig("Change Alpha Based on Range", 145)]
public NameplateRangeConfig RangeConfig = new();
[NestedConfig("Visibility", 200)]
public VisibilityConfig VisibilityConfig = new VisibilityConfig();
public NameplateConfig(Vector2 position, EditableLabelConfig nameLabelConfig, EditableNonFormattableLabelConfig titleLabelConfig)
: base()
{
Position = position;
NameLabelConfig = nameLabelConfig;
TitleLabelConfig = titleLabelConfig;
}
public NameplateConfig() : base() { } // don't remove
}
public interface NameplateWithBarConfig
{
public NameplateBarConfig GetBarConfig();
}
public class NameplateWithNPCBarConfig : NameplateConfig, NameplateWithBarConfig
{
[NestedConfig("Health Bar", 40)]
public NameplateBarConfig BarConfig = null!;
/// <summary>Quest/state icon (e.g. ! ? above NPCs). Use Position and Size to resize and reposition around the nameplate.</summary>
[NestedConfig("Icon (Quest/State)", 42)]
public NameplateIconConfig IconConfig = new NameplateIconConfig(
new Vector2(0, -28),
new Vector2(32, 32),
DrawAnchor.Bottom,
DrawAnchor.Top
)
{ Strata = StrataLevel.LOWEST };
public NameplateBarConfig GetBarConfig() => BarConfig;
public NameplateWithNPCBarConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig,
NameplateBarConfig barConfig)
: base(position, nameLabel, titleLabelConfig)
{
BarConfig = barConfig;
}
public NameplateWithNPCBarConfig() : base() { } // don't remove
}
public class NameplateWithPlayerBarConfig : NameplateConfig, NameplateWithBarConfig
{
[NestedConfig("Health Bar", 40)]
public NameplatePlayerBarConfig BarConfig = null!;
[NestedConfig("Role/Job Icon", 50)]
public NameplateRoleJobIconConfig RoleIconConfig = new NameplateRoleJobIconConfig(
new Vector2(-5, 0),
new Vector2(30, 30),
DrawAnchor.Right,
DrawAnchor.Left
)
{ Strata = StrataLevel.LOWEST };
[NestedConfig("Player State Icon", 55)]
public NameplatePlayerIconConfig StateIconConfig = new NameplatePlayerIconConfig(
new Vector2(5, 0),
new Vector2(30, 30),
DrawAnchor.Left,
DrawAnchor.Right
)
{ Strata = StrataLevel.LOWEST };
public NameplateBarConfig GetBarConfig() => BarConfig;
public NameplateWithPlayerBarConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig,
NameplatePlayerBarConfig barConfig)
: base(position, nameLabel, titleLabelConfig)
{
BarConfig = barConfig;
}
public NameplateWithPlayerBarConfig() : base() { } // don't remove
}
public class NameplateWithEnemyBarConfig : NameplateConfig, NameplateWithBarConfig
{
[NestedConfig("Health Bar", 40)]
public NameplateEnemyBarConfig BarConfig = null!;
[NestedConfig("Icon", 45)]
public NameplateIconConfig IconConfig = new NameplateIconConfig(
new Vector2(0, 0),
new Vector2(40, 40),
DrawAnchor.Right,
DrawAnchor.Left
)
{ PrioritizeHealthBarAnchor = true, Strata = StrataLevel.LOWEST };
[NestedConfig("Debuffs", 50)]
public EnemyNameplateStatusEffectsListConfig DebuffsConfig = null!;
[NestedConfig("Castbar", 55)]
public NameplateCastbarConfig CastbarConfig = null!;
public NameplateBarConfig GetBarConfig() => BarConfig;
public NameplateWithEnemyBarConfig(
Vector2 position,
EditableLabelConfig nameLabel,
EditableNonFormattableLabelConfig titleLabelConfig,
NameplateEnemyBarConfig barConfig)
: base(position, nameLabel, titleLabelConfig)
{
BarConfig = barConfig;
}
public NameplateWithEnemyBarConfig() : base() { } // don't remove
}
[DisableParentSettings("HideWhenInactive")]
public class NameplateBarConfig : BarConfig
{
[Checkbox("Only Show when not at full Health")]
[Order(1)]
public bool OnlyShowWhenNotFull = true;
[Checkbox("Hide Health when fully depleted", help = "This will hide the healthbar when the characters HP has been brought to zero")]
[Order(2)]
public bool HideHealthAtZero = true;
[Checkbox("Disable Interaction")]
[Order(3)]
public bool DisableInteraction = false;
[Checkbox("Use Different Size when targeted", spacing = true)]
[Order(31)]
public bool UseDifferentSizeWhenTargeted = false;
[DragInt2("Size When Targeted", min = 1, max = 4000)]
[Order(32, collapseWith = nameof(UseDifferentSizeWhenTargeted))]
public Vector2 SizeWhenTargeted;
[ColorEdit4("Targeted Border Color")]
[Order(38, collapseWith = nameof(DrawBorder))]
public PluginConfigColor TargetedBorderColor = PluginConfigColor.FromHex(0xFFFFFFFF);
[DragInt("Targeted Border Thickness", min = 1, max = 10)]
[Order(39, collapseWith = nameof(DrawBorder))]
public int TargetedBorderThickness = 2;
[NestedConfig("Color Based On Health Value", 50, collapsingHeader = false)]
public ColorByHealthValueConfig ColorByHealth = new ColorByHealthValueConfig();
[Checkbox("Hide Health if Possible", spacing = true, help = "This will hide any label that has a health tag if the character doesn't have health (ie minions, friendly npcs, etc)")]
[Order(121)]
public bool HideHealthIfPossible = true;
[NestedConfig("Left Text", 125)]
public EditableLabelConfig LeftLabelConfig = null!;
[NestedConfig("Right Text", 130)]
public EditableLabelConfig RightLabelConfig = null!;
[NestedConfig("Optional Text", 131)]
public EditableLabelConfig OptionalLabelConfig = null!;
[NestedConfig("Shields", 140)]
public ShieldConfig ShieldConfig = new ShieldConfig();
[NestedConfig("Custom Mouseover Area", 150)]
public MouseoverAreaConfig MouseoverAreaConfig = new MouseoverAreaConfig();
public NameplateBarConfig(Vector2 position, Vector2 size, EditableLabelConfig leftLabelConfig, EditableLabelConfig rightLabelConfig, EditableLabelConfig optionalLabelConfig)
: base(position, size, new PluginConfigColor(new(40f / 255f, 40f / 255f, 40f / 255f, 100f / 100f)))
{
Position = position;
Size = size;
LeftLabelConfig = leftLabelConfig;
RightLabelConfig = rightLabelConfig;
OptionalLabelConfig = optionalLabelConfig;
BackgroundColor = new PluginConfigColor(new(0f / 255f, 0f / 255f, 0f / 255f, 100f / 100f));
ColorByHealth.Enabled = false;
MouseoverAreaConfig.Enabled = false;
}
public bool IsVisible(uint hp, uint maxHp)
{
return Enabled && (!OnlyShowWhenNotFull || hp < maxHp) && !(HideHealthAtZero && hp <= 0);
}
public Vector2 GetSize(bool targeted)
{
return targeted && UseDifferentSizeWhenTargeted ? SizeWhenTargeted : Size;
}
public NameplateBarConfig() : base(Vector2.Zero, Vector2.Zero, PluginConfigColor.Empty) { } // don't remove
}
public class NameplatePlayerBarConfig : NameplateBarConfig
{
[Checkbox("Use Job Color", spacing = true)]
[Order(45)]
public bool UseJobColor = false;
[Checkbox("Use Role Color")]
[Order(46)]
public bool UseRoleColor = false;
[Checkbox("Job Color As Background Color", spacing = true)]
[Order(50)]
public bool UseJobColorAsBackgroundColor = false;
[Checkbox("Role Color As Background Color")]
[Order(51)]
public bool UseRoleColorAsBackgroundColor = false;
public NameplatePlayerBarConfig(Vector2 position, Vector2 size, EditableLabelConfig leftLabelConfig, EditableLabelConfig rightLabelConfig, EditableLabelConfig optionalLabelConfig)
: base(position, size, leftLabelConfig, rightLabelConfig, optionalLabelConfig)
{
}
}
public class NameplateEnemyBarConfig : NameplateBarConfig
{
[Checkbox("Use State Colors", spacing = true)]
[Order(45)]
public bool UseStateColor = true;
[ColorEdit4("Unengaged")]
[Order(46, collapseWith = nameof(UseStateColor))]
public PluginConfigColor UnengagedColor = PluginConfigColor.FromHex(0xFFDA9D2E);
[ColorEdit4("Unengaged (Hostile)")]
[Order(47, collapseWith = nameof(UseStateColor))]
public PluginConfigColor UnengagedHostileColor = PluginConfigColor.FromHex(0xFF994B35);
[ColorEdit4("Engaged")]
[Order(48, collapseWith = nameof(UseStateColor))]
public PluginConfigColor EngagedColor = PluginConfigColor.FromHex(0xFF993535);
[ColorEdit4("Claimed")]
[Order(49, collapseWith = nameof(UseStateColor))]
public PluginConfigColor ClaimedColor = PluginConfigColor.FromHex(0xFFEA93EA);
[ColorEdit4("Unclaimed")]
[Order(50, collapseWith = nameof(UseStateColor))]
public PluginConfigColor UnclaimedColor = PluginConfigColor.FromHex(0xFFE5BB9E);
[Checkbox("Use Custom Color when being targeted", spacing = true, help = "This will change the color of the bar when the enemy is targeting the player.")]
[Order(51)]
public bool UseCustomColorWhenBeingTargeted = false;
[ColorEdit4("Targeted")]
[Order(52, collapseWith = nameof(UseCustomColorWhenBeingTargeted))]
public PluginConfigColor CustomColorWhenBeingTargeted = PluginConfigColor.FromHex(0xFFC4216D);
[NestedConfig("Order Label", 132)]
public DefaultFontLabelConfig OrderLabelConfig = new DefaultFontLabelConfig(new Vector2(5, 0), "", DrawAnchor.Right, DrawAnchor.Left)
{
Strata = StrataLevel.LOWEST
};
public NameplateEnemyBarConfig(Vector2 position, Vector2 size, EditableLabelConfig leftLabelConfig, EditableLabelConfig rightLabelConfig, EditableLabelConfig optionalLabelConfig)
: base(position, size, leftLabelConfig, rightLabelConfig, optionalLabelConfig)
{
}
}
[Exportable(false)]
public class NameplateRangeConfig : PluginConfigObject
{
[DragInt("Fade start range (yalms)", min = 1, max = 500)]
[Order(5)]
public int StartRange = 50;
[DragInt("Fade end range (yalms)", min = 1, max = 500)]
[Order(10)]
public int EndRange = 64;
public float AlphaForDistance(float distance, float maxAlpha = 1f)
{
float diff = distance - StartRange;
if (!Enabled || diff <= 0)
{
return maxAlpha;
}
float a = diff / (EndRange - StartRange);
return Math.Max(0, Math.Min(maxAlpha, 1 - a));
}
}
public class EnemyNameplateStatusEffectsListConfig : StatusEffectsListConfig
{
[Anchor("Health Bar Anchor")]
[Order(4)]
public DrawAnchor HealthBarAnchor = DrawAnchor.BottomLeft;
public EnemyNameplateStatusEffectsListConfig(DrawAnchor anchor, Vector2 position, Vector2 size, bool showBuffs, bool showDebuffs, bool showPermanentEffects,
GrowthDirections growthDirections, StatusEffectIconConfig iconConfig)
: base(position, size, showBuffs, showDebuffs, showPermanentEffects, growthDirections, iconConfig)
{
HealthBarAnchor = anchor;
}
}
[DisableParentSettings("AnchorToUnitFrame", "UnitFrameAnchor", "HideWhenInactive", "FillDirection")]
public class NameplateCastbarConfig : TargetCastbarConfig
{
[Checkbox("Match Width with Health Bar")]
[Order(11)]
public bool MatchWidth = false;
[Checkbox("Match Height with Health Bar")]
[Order(12)]
public bool MatchHeight = false;
[Anchor("Health Bar Anchor")]
[Order(16)]
public DrawAnchor HealthBarAnchor = DrawAnchor.BottomLeft;
public NameplateCastbarConfig(Vector2 position, Vector2 size, LabelConfig castNameConfig, NumericLabelConfig castTimeConfig)
: base(position, size, castNameConfig, castTimeConfig)
{
}
}
internal static class NameplatesHelper
{
internal static T GetNameplateConfig<T>(uint bgColor, uint borderColor) where T : NameplateConfig
{
EditableLabelConfig nameLabelConfig = new EditableLabelConfig(new Vector2(0, 0), "[name]", DrawAnchor.Top, DrawAnchor.Bottom)
{
Color = PluginConfigColor.FromHex(bgColor),
OutlineColor = PluginConfigColor.FromHex(borderColor),
FontID = FontsConfig.DefaultMediumFontKey
};
EditableNonFormattableLabelConfig titleLabelConfig = new EditableNonFormattableLabelConfig(new Vector2(0, -25), "<[title]>", DrawAnchor.Top, DrawAnchor.Bottom)
{
Color = PluginConfigColor.FromHex(bgColor),
OutlineColor = PluginConfigColor.FromHex(borderColor),
FontID = FontsConfig.DefaultMediumFontKey
};
return (T)Activator.CreateInstance(typeof(T), Vector2.Zero, nameLabelConfig, titleLabelConfig)!;
}
internal static T GetNameplateWithBarConfig<T, B>(uint bgColor, uint borderColor, Vector2 barSize)
where T : NameplateConfig
where B : NameplateBarConfig
{
EditableLabelConfig leftLabelConfig = new EditableLabelConfig(new Vector2(5, 0), "[health:current-short]", DrawAnchor.Left, DrawAnchor.Left)
{
Enabled = false,
FontID = FontsConfig.DefaultMediumFontKey,
Strata = StrataLevel.LOWEST
};
EditableLabelConfig rightLabelConfig = new EditableLabelConfig(new Vector2(-5, 0), "", DrawAnchor.Right, DrawAnchor.Right)
{
Enabled = false,
FontID = FontsConfig.DefaultMediumFontKey,
Strata = StrataLevel.LOWEST
};
EditableLabelConfig optionalLabelConfig = new EditableLabelConfig(new Vector2(0, 0), "", DrawAnchor.Center, DrawAnchor.Center)
{
Enabled = false,
FontID = FontsConfig.DefaultSmallFontKey,
Strata = StrataLevel.LOWEST
};
var barConfig = Activator.CreateInstance(typeof(B), new Vector2(0, -5), barSize, leftLabelConfig, rightLabelConfig, optionalLabelConfig)!;
if (barConfig is BarConfig bar)
{
bar.FillColor = PluginConfigColor.FromHex(bgColor);
bar.BackgroundColor = PluginConfigColor.FromHex(0xAA000000);
}
if (barConfig is NameplateBarConfig nameplateBar)
{
nameplateBar.SizeWhenTargeted = nameplateBar.Size;
}
EditableLabelConfig nameLabelConfig = new EditableLabelConfig(new Vector2(0, -20), "[name]", DrawAnchor.Top, DrawAnchor.Bottom)
{
Color = PluginConfigColor.FromHex(bgColor),
OutlineColor = PluginConfigColor.FromHex(borderColor),
FontID = FontsConfig.DefaultMediumFontKey,
Strata = StrataLevel.LOWEST
};
EditableNonFormattableLabelConfig titleLabelConfig = new EditableNonFormattableLabelConfig(new Vector2(0, 0), "<[title]>", DrawAnchor.Top, DrawAnchor.Bottom)
{
Color = PluginConfigColor.FromHex(bgColor),
OutlineColor = PluginConfigColor.FromHex(borderColor),
FontID = FontsConfig.DefaultMediumFontKey,
Strata = StrataLevel.LOWEST
};
return (T)Activator.CreateInstance(typeof(T), Vector2.Zero, nameLabelConfig, titleLabelConfig, barConfig)!;
}
}
}