80f45f5a31
Co-authored-by: Cursor <cursoragent@cursor.com>
707 lines
30 KiB
C#
707 lines
30 KiB
C#
using Dalamud.Game.ClientState.Objects.Enums;
|
|
using Dalamud.Game.ClientState.Objects.SubKinds;
|
|
using Dalamud.Game.ClientState.Objects.Types;
|
|
using HSUI.Config;
|
|
using HSUI.Enums;
|
|
using HSUI.Helpers;
|
|
using HSUI.Interface.Bars;
|
|
using HSUI.Interface.GeneralElements;
|
|
using HSUI.Interface.StatusEffects;
|
|
using Dalamud.Bindings.ImGui;
|
|
using System.Collections.Generic;
|
|
using System.Numerics;
|
|
using Action = System.Action;
|
|
using Character = Dalamud.Game.ClientState.Objects.Types.ICharacter;
|
|
using StructsCharacter = FFXIVClientStructs.FFXIV.Client.Game.Character.Character;
|
|
|
|
namespace HSUI.Interface.Nameplates
|
|
{
|
|
public class Nameplate
|
|
{
|
|
protected NameplateConfig _config;
|
|
public bool Enabled => _config.Enabled;
|
|
|
|
protected LabelHud _nameLabelHud;
|
|
protected LabelHud _titleLabelHud;
|
|
|
|
public Nameplate(NameplateConfig config)
|
|
{
|
|
_config = config;
|
|
|
|
_nameLabelHud = new LabelHud(config.NameLabelConfig);
|
|
_titleLabelHud = new LabelHud(config.TitleLabelConfig);
|
|
}
|
|
|
|
protected bool IsVisible(IGameObject? actor)
|
|
{
|
|
if (!_config.Enabled ||
|
|
actor == null ||
|
|
!_config.VisibilityConfig.IsElementVisible(null) ||
|
|
(_config.OnlyShowWhenTargeted && actor.Address != Plugin.TargetManager.Target?.Address))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public virtual List<(StrataLevel, Action)> GetElementsDrawActions(NameplateData data)
|
|
{
|
|
List<(StrataLevel, Action)> drawActions = new List<(StrataLevel, Action)>();
|
|
if (!IsVisible(data.GameObject)) { return drawActions; }
|
|
|
|
drawActions.AddRange(GetMainLabelDrawActions(data));
|
|
|
|
return drawActions;
|
|
}
|
|
|
|
protected List<(StrataLevel, Action)> GetMainLabelDrawActions(NameplateData data, NameplateAnchor? barAnchor = null)
|
|
{
|
|
List<(StrataLevel, Action)> drawActions = new List<(StrataLevel, Action)>();
|
|
Vector2 origin = _config.Position + (barAnchor?.Position ?? data.ScreenPosition);
|
|
|
|
Vector2 swapOffset = Vector2.Zero;
|
|
if (_config.SwapLabelsWhenNeeded && (data.IsTitlePrefix || data.Title.Length == 0))
|
|
{
|
|
swapOffset = _config.TitleLabelConfig.Position - _config.NameLabelConfig.Position;
|
|
}
|
|
|
|
// name
|
|
float nameAlpha = _config.RangeConfig.AlphaForDistance(data.Distance, _config.NameLabelConfig.Color.Vector.W);
|
|
var (nameText, namePos, nameSize, nameColor) = _nameLabelHud.PreCalculate(origin + swapOffset, barAnchor?.Size, data.GameObject, data.Name, isPlayerName: data.Kind == ObjectKind.Player);
|
|
drawActions.Add((_config.NameLabelConfig.StrataLevel, () =>
|
|
{
|
|
_nameLabelHud.DrawLabel(nameText, namePos, nameSize, nameColor, nameAlpha);
|
|
}
|
|
));
|
|
|
|
// title
|
|
float titleAlpha = _config.RangeConfig.AlphaForDistance(data.Distance, _config.TitleLabelConfig.Color.Vector.W);
|
|
var (titleText, titlePos, titleSize, titleColor) = _titleLabelHud.PreCalculate(origin - swapOffset, barAnchor?.Size, data.GameObject, title: data.Title);
|
|
if (data.Title.Length > 0)
|
|
{
|
|
drawActions.Add((_config.TitleLabelConfig.StrataLevel, () =>
|
|
{
|
|
_titleLabelHud.DrawLabel(titleText, titlePos, titleSize, titleColor, titleAlpha);
|
|
}
|
|
));
|
|
}
|
|
|
|
return drawActions;
|
|
}
|
|
}
|
|
|
|
public class NameplateWithBar : Nameplate
|
|
{
|
|
protected NameplateBarConfig BarConfig => ((NameplateWithBarConfig)_config).GetBarConfig();
|
|
|
|
private LabelHud _leftLabelHud;
|
|
private LabelHud _rightLabelHud;
|
|
private LabelHud _optionalLabelHud;
|
|
|
|
public NameplateWithBar(NameplateConfig config) : base(config)
|
|
{
|
|
_leftLabelHud = new LabelHud(BarConfig.LeftLabelConfig);
|
|
_rightLabelHud = new LabelHud(BarConfig.RightLabelConfig);
|
|
_optionalLabelHud = new LabelHud(BarConfig.OptionalLabelConfig);
|
|
}
|
|
|
|
public (bool, bool) GetMouseoverState(NameplateData data)
|
|
{
|
|
if (data.GameObject is not ICharacter character) { return (false, false); }
|
|
if (!BarConfig.IsVisible(character.CurrentHp, character.MaxHp) || BarConfig.DisableInteraction)
|
|
{
|
|
return (false, false);
|
|
}
|
|
|
|
bool targeted = Plugin.TargetManager.Target?.Address == character.Address;
|
|
Vector2 barSize = BarConfig.GetSize(targeted);
|
|
|
|
Vector2 origin = _config.Position + data.ScreenPosition;
|
|
Vector2 barPos = Utils.GetAnchoredPosition(origin, barSize, BarConfig.Anchor) + BarConfig.Position;
|
|
var (areaStart, areaEnd) = BarConfig.MouseoverAreaConfig.GetArea(barPos, barSize);
|
|
|
|
bool isHovering = ImGui.IsMouseHoveringRect(areaStart, areaEnd);
|
|
bool ignoreMouseover = BarConfig.MouseoverAreaConfig.Enabled && BarConfig.MouseoverAreaConfig.Ignore;
|
|
|
|
return (isHovering, ignoreMouseover);
|
|
}
|
|
|
|
public unsafe List<(StrataLevel, Action)> GetBarDrawActions(NameplateData data)
|
|
{
|
|
List<(StrataLevel, Action)> drawActions = new List<(StrataLevel, Action)>();
|
|
if (!IsVisible(data.GameObject)) { return drawActions; }
|
|
if (data.GameObject is not Character character) { return drawActions; }
|
|
|
|
uint currentHp = character.CurrentHp;
|
|
uint maxHp = character.MaxHp;
|
|
|
|
if (!BarConfig.IsVisible(currentHp, maxHp)) { return drawActions; }
|
|
|
|
// colors
|
|
PluginConfigColor fillColor = GetFillColor(character, currentHp, maxHp);
|
|
fillColor = fillColor.WithAlpha(_config.RangeConfig.AlphaForDistance(data.Distance, fillColor.Vector.W));
|
|
|
|
PluginConfigColor bgColor = GetBackgroundColor(character);
|
|
bgColor = bgColor.WithAlpha(_config.RangeConfig.AlphaForDistance(data.Distance, bgColor.Vector.W));
|
|
|
|
bool targeted = character.Address == Plugin.TargetManager.Target?.Address;
|
|
PluginConfigColor borderColor = targeted ? BarConfig.TargetedBorderColor : BarConfig.BorderColor;
|
|
borderColor = borderColor.WithAlpha(
|
|
_config.RangeConfig.AlphaForDistance(data.Distance, BarConfig.BorderColor.Vector.W)
|
|
);
|
|
|
|
// bar
|
|
Vector2 barSize = BarConfig.GetSize(targeted);
|
|
Rect background = new Rect(BarConfig.Position, barSize, bgColor);
|
|
Rect healthFill = BarUtilities.GetFillRect(BarConfig.Position, barSize, BarConfig.FillDirection, fillColor, currentHp, maxHp);
|
|
|
|
BarHud bar = new BarHud(
|
|
BarConfig.ID,
|
|
BarConfig.DrawBorder,
|
|
borderColor,
|
|
targeted ? BarConfig.TargetedBorderThickness : BarConfig.BorderThickness,
|
|
BarConfig.Anchor,
|
|
character,
|
|
current: currentHp,
|
|
max: maxHp,
|
|
shadowConfig: BarConfig.ShadowConfig,
|
|
barTextureName: BarConfig.BarTextureName,
|
|
barTextureDrawMode: BarConfig.BarTextureDrawMode
|
|
);
|
|
|
|
bar.NeedsInputs = true;
|
|
bar.SetBackground(background);
|
|
bar.AddForegrounds(healthFill);
|
|
|
|
// shield
|
|
PluginConfigColor shieldColor = BarConfig.ShieldConfig.Color.WithAlpha(
|
|
_config.RangeConfig.AlphaForDistance(data.Distance, BarConfig.ShieldConfig.Color.Vector.W)
|
|
);
|
|
BarUtilities.AddShield(bar, BarConfig, BarConfig.ShieldConfig, character, healthFill.Size, shieldColor);
|
|
|
|
// draw bar
|
|
Vector2 origin = _config.Position + data.ScreenPosition;
|
|
drawActions.AddRange(bar.GetDrawActions(origin, _config.StrataLevel));
|
|
|
|
// mouseover area
|
|
BarHud? mouseoverAreaBar = BarConfig.MouseoverAreaConfig.GetBar(
|
|
BarConfig.Position,
|
|
barSize,
|
|
BarConfig.ID + "_mouseoverArea",
|
|
BarConfig.Anchor
|
|
);
|
|
|
|
if (mouseoverAreaBar != null)
|
|
{
|
|
drawActions.AddRange(mouseoverAreaBar.GetDrawActions(origin, StrataLevel.HIGHEST));
|
|
}
|
|
|
|
// labels
|
|
Vector2 barPos = Utils.GetAnchoredPosition(origin, barSize, BarConfig.Anchor) + BarConfig.Position;
|
|
LabelHud[] labels = GetLabels(maxHp);
|
|
foreach (LabelHud label in labels)
|
|
{
|
|
LabelConfig labelConfig = (LabelConfig)label.GetConfig();
|
|
float alpha = _config.RangeConfig.AlphaForDistance(data.Distance, labelConfig.Color.Vector.W);
|
|
var (labelText, labelPos, labelSize, labelColor) = label.PreCalculate(barPos, barSize, data.GameObject, data.Name, currentHp, maxHp, data.Kind == ObjectKind.Player);
|
|
|
|
drawActions.Add((labelConfig.StrataLevel, () =>
|
|
{
|
|
label.DrawLabel(labelText, labelPos, labelSize, labelColor, alpha);
|
|
}
|
|
));
|
|
}
|
|
|
|
return drawActions;
|
|
}
|
|
|
|
public override List<(StrataLevel, Action)> GetElementsDrawActions(NameplateData data)
|
|
{
|
|
List<(StrataLevel, Action)> drawActions = new List<(StrataLevel, Action)>();
|
|
if (!IsVisible(data.GameObject)) { return drawActions; }
|
|
|
|
NameplateAnchor? barAnchor = GetBarAnchor(data);
|
|
drawActions.AddRange(GetMainLabelDrawActions(data, barAnchor));
|
|
|
|
// Quest/state icon (e.g. ! ? above NPCs) - drawn when we have icon config and game provided icon ID
|
|
if (_config is NameplateWithNPCBarConfig npcConfig &&
|
|
npcConfig.IconConfig.Enabled &&
|
|
data.NamePlateIconId > 0)
|
|
{
|
|
float alpha = _config.RangeConfig.AlphaForDistance(data.Distance, 1f);
|
|
Vector2 anchorPos = barAnchor?.Position ?? (_config.Position + data.ScreenPosition);
|
|
Vector2 anchorSize = barAnchor?.Size ?? Vector2.Zero;
|
|
var pos = Utils.GetAnchoredPosition(anchorPos, -anchorSize, npcConfig.IconConfig.FrameAnchor);
|
|
Vector2 iconPos = Utils.GetAnchoredPosition(pos + npcConfig.IconConfig.Position, npcConfig.IconConfig.Size, npcConfig.IconConfig.Anchor);
|
|
|
|
drawActions.Add((npcConfig.IconConfig.StrataLevel, () =>
|
|
{
|
|
DrawHelper.DrawInWindow(_config.ID + "_npcIcon", iconPos, npcConfig.IconConfig.Size, false, (drawList) =>
|
|
{
|
|
DrawHelper.DrawIcon((uint)data.NamePlateIconId, iconPos, npcConfig.IconConfig.Size, false, alpha, drawList);
|
|
});
|
|
}));
|
|
}
|
|
|
|
return drawActions;
|
|
}
|
|
|
|
protected virtual NameplateAnchor? GetBarAnchor(NameplateData data)
|
|
{
|
|
if (data.GameObject is Character chara &&
|
|
BarConfig.IsVisible(chara.CurrentHp, chara.MaxHp))
|
|
{
|
|
bool targeted = Plugin.TargetManager.Target?.Address == data.GameObject.Address;
|
|
Vector2 size = BarConfig.GetSize(targeted);
|
|
Vector2 pos = Utils.GetAnchoredPosition(data.ScreenPosition + BarConfig.Position, size, BarConfig.Anchor);
|
|
|
|
return new NameplateAnchor(pos, size);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private LabelHud[] GetLabels(uint maxHp)
|
|
{
|
|
List<LabelHud> labels = new List<LabelHud>();
|
|
|
|
if (BarConfig.HideHealthIfPossible && maxHp <= 0)
|
|
{
|
|
if (!Utils.IsHealthLabel(BarConfig.LeftLabelConfig))
|
|
{
|
|
labels.Add(_leftLabelHud);
|
|
}
|
|
|
|
if (!Utils.IsHealthLabel(BarConfig.RightLabelConfig))
|
|
{
|
|
labels.Add(_rightLabelHud);
|
|
}
|
|
|
|
if (!Utils.IsHealthLabel(BarConfig.OptionalLabelConfig))
|
|
{
|
|
labels.Add(_optionalLabelHud);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
labels.Add(_leftLabelHud);
|
|
labels.Add(_rightLabelHud);
|
|
labels.Add(_optionalLabelHud);
|
|
}
|
|
|
|
return labels.ToArray();
|
|
}
|
|
|
|
protected virtual PluginConfigColor GetFillColor(Character character, uint currentHp, uint maxHp)
|
|
{
|
|
return ColorUtils.ColorForCharacter(
|
|
character,
|
|
currentHp,
|
|
maxHp,
|
|
false,
|
|
false,
|
|
BarConfig.ColorByHealth
|
|
) ?? BarConfig.FillColor;
|
|
}
|
|
|
|
protected virtual PluginConfigColor GetBackgroundColor(Character character)
|
|
{
|
|
return BarConfig.BackgroundColor;
|
|
}
|
|
}
|
|
|
|
public class NameplateWithBarAndExtras : NameplateWithBar
|
|
{
|
|
public NameplateWithBarAndExtras(NameplateConfig config) : base(config)
|
|
{
|
|
}
|
|
|
|
public override List<(StrataLevel, Action)> GetElementsDrawActions(NameplateData data)
|
|
{
|
|
List<(StrataLevel, Action)> drawActions = new List<(StrataLevel, Action)>();
|
|
if (!IsVisible(data.GameObject)) { return drawActions; }
|
|
|
|
NameplateAnchor? barAnchor = GetBarAnchor(data);
|
|
Vector2 origin = _config.Position + (barAnchor?.Position ?? data.ScreenPosition);
|
|
|
|
Vector2 swapOffset = Vector2.Zero;
|
|
if (_config.SwapLabelsWhenNeeded && (data.IsTitlePrefix || data.Title.Length == 0))
|
|
{
|
|
swapOffset = _config.TitleLabelConfig.Position - _config.NameLabelConfig.Position;
|
|
}
|
|
|
|
// name
|
|
float nameAlpha = _config.RangeConfig.AlphaForDistance(data.Distance, _config.NameLabelConfig.Color.Vector.W);
|
|
var (nameText, namePos, nameSize, nameColor) = _nameLabelHud.PreCalculate(origin + swapOffset, barAnchor?.Size, data.GameObject, data.Name, isPlayerName: data.Kind == ObjectKind.Player);
|
|
drawActions.Add((_config.NameLabelConfig.StrataLevel, () =>
|
|
{
|
|
_nameLabelHud.DrawLabel(nameText, namePos, nameSize, nameColor, nameAlpha);
|
|
}
|
|
));
|
|
|
|
// title
|
|
float titleAlpha = _config.RangeConfig.AlphaForDistance(data.Distance, _config.TitleLabelConfig.Color.Vector.W);
|
|
var (titleText, titlePos, titleSize, titleColor) = _titleLabelHud.PreCalculate(origin - swapOffset, barAnchor?.Size, data.GameObject, title: data.Title);
|
|
if (data.Title.Length > 0)
|
|
{
|
|
drawActions.Add((_config.TitleLabelConfig.StrataLevel, () =>
|
|
{
|
|
_titleLabelHud.DrawLabel(titleText, titlePos, titleSize, titleColor, titleAlpha);
|
|
}
|
|
));
|
|
}
|
|
|
|
// extras anchor
|
|
NameplateExtrasAnchors extrasAnchors = new NameplateExtrasAnchors(
|
|
barAnchor,
|
|
_config.NameLabelConfig.Enabled ? new NameplateAnchor(namePos, nameSize) : null,
|
|
_config.TitleLabelConfig.Enabled && data.Title.Length > 0 ? new NameplateAnchor(titlePos, titleSize) : null
|
|
);
|
|
|
|
drawActions.AddRange(GetExtrasDrawActions(data, extrasAnchors));
|
|
|
|
return drawActions;
|
|
}
|
|
|
|
protected virtual List<(StrataLevel, Action)> GetExtrasDrawActions(NameplateData data, NameplateExtrasAnchors anchors)
|
|
{
|
|
// override
|
|
return new List<(StrataLevel, Action)>();
|
|
}
|
|
}
|
|
|
|
public class NameplateWithPlayerBar : NameplateWithBarAndExtras
|
|
{
|
|
private NameplateWithPlayerBarConfig Config => (NameplateWithPlayerBarConfig)_config;
|
|
|
|
public NameplateWithPlayerBar(NameplateWithPlayerBarConfig config) : base(config)
|
|
{
|
|
}
|
|
|
|
protected override List<(StrataLevel, Action)> GetExtrasDrawActions(NameplateData data, NameplateExtrasAnchors anchors)
|
|
{
|
|
List<(StrataLevel, Action)> drawActions = new List<(StrataLevel, Action)>();
|
|
if (data.GameObject is not IPlayerCharacter character) { return drawActions; }
|
|
|
|
float alpha = _config.RangeConfig.AlphaForDistance(data.Distance);
|
|
|
|
// role/job icon
|
|
if (Config.RoleIconConfig.Enabled)
|
|
{
|
|
NameplateAnchor? anchor = anchors.GetAnchor(Config.RoleIconConfig.NameplateLabelAnchor, Config.RoleIconConfig.PrioritizeHealthBarAnchor);
|
|
anchor = anchor ?? new NameplateAnchor(data.ScreenPosition, Vector2.Zero);
|
|
|
|
uint jobId = character.ClassJob.RowId;
|
|
uint iconId = Config.RoleIconConfig.UseRoleIcons ?
|
|
JobsHelper.RoleIconIDForJob(jobId, Config.RoleIconConfig.UseSpecificDPSRoleIcons) :
|
|
JobsHelper.IconIDForJob(jobId, (uint)Config.RoleIconConfig.Style);
|
|
|
|
if (iconId > 0)
|
|
{
|
|
var pos = Utils.GetAnchoredPosition(anchor.Value.Position, -anchor.Value.Size, Config.RoleIconConfig.FrameAnchor);
|
|
var iconPos = Utils.GetAnchoredPosition(pos + Config.RoleIconConfig.Position, Config.RoleIconConfig.Size, Config.RoleIconConfig.Anchor);
|
|
|
|
drawActions.Add((Config.RoleIconConfig.StrataLevel, () =>
|
|
{
|
|
DrawHelper.DrawInWindow(_config.ID + "_jobIcon", iconPos, Config.RoleIconConfig.Size, false, (drawList) =>
|
|
{
|
|
DrawHelper.DrawIcon(iconId, iconPos, Config.RoleIconConfig.Size, false, alpha, drawList);
|
|
});
|
|
}
|
|
));
|
|
}
|
|
}
|
|
|
|
// state icon
|
|
if (Config.StateIconConfig.Enabled &&
|
|
data.NamePlateIconId > 0 &&
|
|
Config.StateIconConfig.ShouldDrawIcon(data.NamePlateIconId))
|
|
{
|
|
NameplateAnchor? anchor = anchors.GetAnchor(Config.StateIconConfig.NameplateLabelAnchor, Config.StateIconConfig.PrioritizeHealthBarAnchor);
|
|
anchor = anchor ?? new NameplateAnchor(data.ScreenPosition, Vector2.Zero);
|
|
|
|
var pos = Utils.GetAnchoredPosition(anchor.Value.Position, -anchor.Value.Size, Config.StateIconConfig.FrameAnchor);
|
|
var iconPos = Utils.GetAnchoredPosition(pos + Config.StateIconConfig.Position, Config.StateIconConfig.Size, Config.StateIconConfig.Anchor);
|
|
|
|
drawActions.Add((Config.StateIconConfig.StrataLevel, () =>
|
|
{
|
|
DrawHelper.DrawInWindow(_config.ID + "_stateIcon", iconPos, Config.StateIconConfig.Size, false, (drawList) =>
|
|
{
|
|
DrawHelper.DrawIcon((uint)data.NamePlateIconId, iconPos, Config.StateIconConfig.Size, false, alpha, drawList);
|
|
});
|
|
}
|
|
));
|
|
}
|
|
|
|
return drawActions;
|
|
}
|
|
|
|
protected override PluginConfigColor GetFillColor(Character character, uint currentHp, uint maxHp)
|
|
{
|
|
NameplatePlayerBarConfig config = (NameplatePlayerBarConfig)BarConfig;
|
|
|
|
return ColorUtils.ColorForCharacter(
|
|
character,
|
|
currentHp,
|
|
maxHp,
|
|
config.UseJobColor,
|
|
config.UseRoleColor,
|
|
config.ColorByHealth
|
|
) ?? config.FillColor;
|
|
}
|
|
|
|
protected override PluginConfigColor GetBackgroundColor(Character character)
|
|
{
|
|
NameplatePlayerBarConfig config = (NameplatePlayerBarConfig)BarConfig;
|
|
|
|
if (config.UseJobColorAsBackgroundColor)
|
|
{
|
|
return GlobalColors.Instance.SafeColorForJobId(character.ClassJob.RowId);
|
|
}
|
|
else if (config.UseRoleColorAsBackgroundColor)
|
|
{
|
|
return GlobalColors.Instance.SafeRoleColorForJobId(character.ClassJob.RowId);
|
|
}
|
|
|
|
return config.BackgroundColor;
|
|
}
|
|
}
|
|
|
|
public class NameplateWithEnemyBar : NameplateWithBarAndExtras
|
|
{
|
|
private NameplateWithEnemyBarConfig Config => (NameplateWithEnemyBarConfig)_config;
|
|
|
|
private LabelHud _orderLabelHud;
|
|
private StatusEffectsListHud _debuffsHud;
|
|
private NameplateCastbarHud _castbarHud;
|
|
|
|
public NameplateWithEnemyBar(NameplateWithEnemyBarConfig config) : base(config)
|
|
{
|
|
_orderLabelHud = new LabelHud(config.BarConfig.OrderLabelConfig);
|
|
_debuffsHud = new StatusEffectsListHud(config.DebuffsConfig);
|
|
_castbarHud = new NameplateCastbarHud(config.CastbarConfig);
|
|
}
|
|
|
|
public void StopPreview()
|
|
{
|
|
_debuffsHud.StopPreview();
|
|
_castbarHud.StopPreview();
|
|
}
|
|
|
|
protected override List<(StrataLevel, Action)> GetExtrasDrawActions(NameplateData data, NameplateExtrasAnchors anchors)
|
|
{
|
|
List<(StrataLevel, Action)> drawActions = new List<(StrataLevel, Action)>();
|
|
if (data.GameObject is not Character character) { return drawActions; }
|
|
|
|
NameplateEnemyBarConfig barConfig = Config.BarConfig;
|
|
NameplateAnchor? anchor = barConfig.IsVisible(character.CurrentHp, character.MaxHp) ? anchors.BarAnchor : anchors.NameLabelAnchor;
|
|
anchor = anchor ?? new NameplateAnchor(_config.Position + data.ScreenPosition, Vector2.Zero);
|
|
|
|
// order label
|
|
float alpha = _config.RangeConfig.AlphaForDistance(data.Distance, barConfig.OrderLabelConfig.Color.Vector.W);
|
|
|
|
barConfig.OrderLabelConfig.SetText(data.Order);
|
|
var (labelText, labelPos, labelSize, labelColor) = _orderLabelHud.PreCalculate(anchor.Value.Position, anchor.Value.Size, data.GameObject);
|
|
drawActions.Add((barConfig.OrderLabelConfig.StrataLevel, () =>
|
|
{
|
|
_orderLabelHud.DrawLabel(labelText, labelPos, labelSize, labelColor, alpha);
|
|
}
|
|
));
|
|
|
|
// debuffs
|
|
Vector2 buffsPos = Utils.GetAnchoredPosition(anchor.Value.Position, -anchor.Value.Size, Config.DebuffsConfig.HealthBarAnchor);
|
|
drawActions.Add((Config.DebuffsConfig.StrataLevel, () =>
|
|
{
|
|
_debuffsHud.Actor = character;
|
|
_debuffsHud.PrepareForDraw(buffsPos);
|
|
_debuffsHud.Draw(buffsPos);
|
|
}
|
|
));
|
|
|
|
// castbar
|
|
Vector2 castbarPos = Utils.GetAnchoredPosition(anchor.Value.Position, -anchor.Value.Size, Config.CastbarConfig.HealthBarAnchor);
|
|
drawActions.Add((Config.CastbarConfig.StrataLevel, () =>
|
|
{
|
|
_castbarHud.ParentSize = anchor.Value.Size;
|
|
_castbarHud.Actor = character;
|
|
_castbarHud.PrepareForDraw(castbarPos);
|
|
_castbarHud.Draw(castbarPos);
|
|
}
|
|
));
|
|
|
|
// icon
|
|
if (Config.IconConfig.Enabled && data.NamePlateIconId > 0)
|
|
{
|
|
anchor = anchors.GetAnchor(Config.IconConfig.NameplateLabelAnchor, Config.IconConfig.PrioritizeHealthBarAnchor);
|
|
anchor = anchor ?? new NameplateAnchor(data.ScreenPosition, Vector2.Zero);
|
|
|
|
var pos = Utils.GetAnchoredPosition(_config.Position + anchor.Value.Position, -anchor.Value.Size, Config.IconConfig.FrameAnchor);
|
|
var iconPos = Utils.GetAnchoredPosition(pos + Config.IconConfig.Position, Config.IconConfig.Size, Config.IconConfig.Anchor);
|
|
|
|
drawActions.Add((Config.IconConfig.StrataLevel, () =>
|
|
{
|
|
DrawHelper.DrawInWindow(_config.ID + "_enemyIcon", iconPos, Config.IconConfig.Size, false, (drawList) =>
|
|
{
|
|
DrawHelper.DrawIcon((uint)data.NamePlateIconId, iconPos, Config.IconConfig.Size, false, alpha, drawList);
|
|
});
|
|
}
|
|
));
|
|
|
|
}
|
|
|
|
// company icon (PvP Frontline: Maelstrom, Flames, Adders)
|
|
var gcIconOverrides = (Config.CompanyIconConfig.IconIdTeam1, Config.CompanyIconConfig.IconIdTeam2, Config.CompanyIconConfig.IconIdTeam3);
|
|
if (Config.CompanyIconConfig.Enabled && Utils.GrandCompanyIconIdForPvPEnemy(data.GameObject, gcIconOverrides) is uint gcIconId)
|
|
{
|
|
anchor = anchors.GetAnchor(Config.CompanyIconConfig.NameplateLabelAnchor, Config.CompanyIconConfig.PrioritizeHealthBarAnchor);
|
|
anchor = anchor ?? new NameplateAnchor(data.ScreenPosition, Vector2.Zero);
|
|
|
|
var pos = Utils.GetAnchoredPosition(_config.Position + anchor.Value.Position, -anchor.Value.Size, Config.CompanyIconConfig.FrameAnchor);
|
|
var iconPos = Utils.GetAnchoredPosition(pos + Config.CompanyIconConfig.Position, Config.CompanyIconConfig.Size, Config.CompanyIconConfig.Anchor);
|
|
|
|
drawActions.Add((Config.CompanyIconConfig.StrataLevel, () =>
|
|
{
|
|
DrawHelper.DrawInWindow(_config.ID + "_enemyCompanyIcon", iconPos, Config.CompanyIconConfig.Size, false, (drawList) =>
|
|
{
|
|
DrawHelper.DrawIcon(gcIconId, iconPos, Config.CompanyIconConfig.Size, false, alpha, drawList);
|
|
});
|
|
}
|
|
));
|
|
}
|
|
|
|
// role/job icon (enemy players only; has ClassJob)
|
|
if (Config.RoleIconConfig.Enabled && data.GameObject is IPlayerCharacter playerCharacter)
|
|
{
|
|
uint jobId = playerCharacter.ClassJob.RowId;
|
|
uint iconId = Config.RoleIconConfig.UseRoleIcons
|
|
? JobsHelper.RoleIconIDForJob(jobId, Config.RoleIconConfig.UseSpecificDPSRoleIcons)
|
|
: JobsHelper.IconIDForJob(jobId, (uint)Config.RoleIconConfig.Style);
|
|
|
|
if (iconId > 0)
|
|
{
|
|
anchor = anchors.GetAnchor(Config.RoleIconConfig.NameplateLabelAnchor, Config.RoleIconConfig.PrioritizeHealthBarAnchor);
|
|
anchor = anchor ?? new NameplateAnchor(data.ScreenPosition, Vector2.Zero);
|
|
|
|
var pos = Utils.GetAnchoredPosition(_config.Position + anchor.Value.Position, -anchor.Value.Size, Config.RoleIconConfig.FrameAnchor);
|
|
var iconPos = Utils.GetAnchoredPosition(pos + Config.RoleIconConfig.Position, Config.RoleIconConfig.Size, Config.RoleIconConfig.Anchor);
|
|
|
|
drawActions.Add((Config.RoleIconConfig.StrataLevel, () =>
|
|
{
|
|
DrawHelper.DrawInWindow(_config.ID + "_enemyRoleJobIcon", iconPos, Config.RoleIconConfig.Size, false, (drawList) =>
|
|
{
|
|
DrawHelper.DrawIcon(iconId, iconPos, Config.RoleIconConfig.Size, false, alpha, drawList);
|
|
});
|
|
}
|
|
));
|
|
}
|
|
}
|
|
|
|
return drawActions;
|
|
}
|
|
|
|
protected override unsafe PluginConfigColor GetFillColor(Character character, uint currentHp, uint maxHp)
|
|
{
|
|
NameplateEnemyBarConfig config = (NameplateEnemyBarConfig)BarConfig;
|
|
|
|
bool targetingPlayer = character.TargetObjectId == Plugin.ObjectTable.LocalPlayer?.GameObjectId;
|
|
if (targetingPlayer && config.UseCustomColorWhenBeingTargeted)
|
|
{
|
|
return config.CustomColorWhenBeingTargeted;
|
|
}
|
|
|
|
if (config.UseStateColor)
|
|
{
|
|
StructsCharacter* chara = (StructsCharacter*)character.Address;
|
|
byte nameplateColorId = chara->GetNamePlateColorType();
|
|
|
|
switch (nameplateColorId) {
|
|
case 7: return (character.StatusFlags & StatusFlags.Hostile) != 0 ? config.UnengagedHostileColor : config.UnengagedColor;
|
|
case 9: return config.EngagedColor;
|
|
case 10: return config.ClaimedColor;
|
|
case 11: return config.UnclaimedColor;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
return base.GetFillColor(character, currentHp, maxHp);
|
|
}
|
|
}
|
|
|
|
#region utils
|
|
public struct NameplateAnchor
|
|
{
|
|
public Vector2 Position;
|
|
public Vector2 Size;
|
|
|
|
internal NameplateAnchor(Vector2 position, Vector2 size)
|
|
{
|
|
Position = position;
|
|
Size = size;
|
|
}
|
|
}
|
|
|
|
public struct NameplateExtrasAnchors
|
|
{
|
|
public NameplateAnchor? BarAnchor;
|
|
public NameplateAnchor? NameLabelAnchor;
|
|
public NameplateAnchor? TitleLabelAnchor;
|
|
public NameplateAnchor? HighestLabelAnchor;
|
|
public NameplateAnchor? LowestLabelAnchor;
|
|
private NameplateAnchor? DefaultLabelAnchor;
|
|
|
|
internal NameplateExtrasAnchors(NameplateAnchor? barAnchor, NameplateAnchor? nameLabelAnchor, NameplateAnchor? titleLabelAnchor)
|
|
{
|
|
BarAnchor = barAnchor;
|
|
NameLabelAnchor = nameLabelAnchor;
|
|
TitleLabelAnchor = titleLabelAnchor;
|
|
DefaultLabelAnchor = nameLabelAnchor;
|
|
|
|
float nameY = -1;
|
|
if (nameLabelAnchor.HasValue)
|
|
{
|
|
nameY = nameLabelAnchor.Value.Position.Y;
|
|
}
|
|
|
|
float titleY = -1;
|
|
if (titleLabelAnchor.HasValue)
|
|
{
|
|
titleY = titleLabelAnchor.Value.Position.Y;
|
|
}
|
|
|
|
if (nameY == -1)
|
|
{
|
|
DefaultLabelAnchor = titleLabelAnchor;
|
|
}
|
|
else if (nameY < titleY)
|
|
{
|
|
HighestLabelAnchor = nameLabelAnchor;
|
|
LowestLabelAnchor = titleLabelAnchor;
|
|
}
|
|
else if (nameY > titleY)
|
|
{
|
|
HighestLabelAnchor = titleLabelAnchor;
|
|
LowestLabelAnchor = nameLabelAnchor;
|
|
}
|
|
}
|
|
|
|
internal NameplateAnchor? GetAnchor(NameplateLabelAnchor label, bool prioritizeHealthBar)
|
|
{
|
|
if (prioritizeHealthBar && BarAnchor != null) { return BarAnchor; }
|
|
|
|
NameplateAnchor? labelAnchor = null;
|
|
|
|
switch (label)
|
|
{
|
|
case NameplateLabelAnchor.Name: labelAnchor = NameLabelAnchor; break;
|
|
case NameplateLabelAnchor.Title: labelAnchor = TitleLabelAnchor; break;
|
|
case NameplateLabelAnchor.Highest: labelAnchor = HighestLabelAnchor; break;
|
|
case NameplateLabelAnchor.Lowest: labelAnchor = LowestLabelAnchor; break;
|
|
}
|
|
|
|
return labelAnchor ?? DefaultLabelAnchor;
|
|
}
|
|
#endregion
|
|
}
|
|
}
|