Initial release: HSUI v1.0.0.0 - HUD replacement with configurable hotbars
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,429 @@
|
||||
using Dalamud.Game.ClientState.JobGauge.Types;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using HSUI.Config;
|
||||
using HSUI.Config.Attributes;
|
||||
using HSUI.Helpers;
|
||||
using HSUI.Interface.Bars;
|
||||
using HSUI.Interface.GeneralElements;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Gauge;
|
||||
using FFXIVClientStructs.FFXIV.Common.Lua;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace HSUI.Interface.Jobs
|
||||
{
|
||||
public class SummonerHud : JobHud
|
||||
{
|
||||
private new SummonerConfig Config => (SummonerConfig)_config;
|
||||
|
||||
public SummonerHud(SummonerConfig config, string? displayName = null) : base(config, displayName)
|
||||
{
|
||||
}
|
||||
|
||||
protected override (List<Vector2>, List<Vector2>) ChildrenPositionsAndSizes()
|
||||
{
|
||||
List<Vector2> positions = new();
|
||||
List<Vector2> sizes = new();
|
||||
|
||||
if (Config.AetherflowBar.Enabled)
|
||||
{
|
||||
positions.Add(Config.Position + Config.AetherflowBar.Position);
|
||||
sizes.Add(Config.AetherflowBar.Size);
|
||||
}
|
||||
|
||||
if (Config.TranceBar.Enabled)
|
||||
{
|
||||
positions.Add(Config.Position + Config.TranceBar.Position);
|
||||
sizes.Add(Config.TranceBar.Size);
|
||||
}
|
||||
|
||||
if (Config.IfritBar.Enabled)
|
||||
{
|
||||
positions.Add(Config.Position + Config.IfritBar.Position);
|
||||
sizes.Add(Config.IfritBar.Size);
|
||||
}
|
||||
|
||||
if (Config.TitanBar.Enabled)
|
||||
{
|
||||
positions.Add(Config.Position + Config.TitanBar.Position);
|
||||
sizes.Add(Config.TitanBar.Size);
|
||||
}
|
||||
|
||||
if (Config.GarudaBar.Enabled)
|
||||
{
|
||||
positions.Add(Config.Position + Config.GarudaBar.Position);
|
||||
sizes.Add(Config.GarudaBar.Size);
|
||||
}
|
||||
|
||||
if (Config.StacksBar.Enabled)
|
||||
{
|
||||
positions.Add(Config.Position + Config.StacksBar.Position);
|
||||
sizes.Add(Config.StacksBar.Size);
|
||||
}
|
||||
|
||||
return (positions, sizes);
|
||||
}
|
||||
|
||||
public override void DrawJobHud(Vector2 origin, IPlayerCharacter player)
|
||||
{
|
||||
Vector2 pos = origin + Config.Position;
|
||||
|
||||
if (Config.AetherflowBar.Enabled)
|
||||
{
|
||||
DrawAetherBar(pos, player);
|
||||
}
|
||||
|
||||
if (Config.TranceBar.Enabled)
|
||||
{
|
||||
DrawTranceBar(pos, player);
|
||||
}
|
||||
|
||||
if (Config.IfritBar.Enabled)
|
||||
{
|
||||
DrawIfritBar(pos, player);
|
||||
}
|
||||
|
||||
if (Config.TitanBar.Enabled)
|
||||
{
|
||||
DrawTitanBar(pos, player);
|
||||
}
|
||||
|
||||
if (Config.GarudaBar.Enabled)
|
||||
{
|
||||
DrawGarudaBar(pos, player);
|
||||
}
|
||||
|
||||
if (Config.StacksBar.Enabled)
|
||||
{
|
||||
HandleAttunementStacks(pos, player);
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void DrawIfritBar(Vector2 origin, IPlayerCharacter player)
|
||||
{
|
||||
SMNGauge gauge = Plugin.JobGauges.Get<SMNGauge>();
|
||||
int stackCount = gauge.IsIfritReady ? 1 : 0;
|
||||
|
||||
if (!Config.IfritBar.HideWhenInactive || stackCount > 1)
|
||||
{
|
||||
BarHud[] bars = BarUtilities.GetChunkedBars(Config.IfritBar, 1, stackCount, 1, 0, player);
|
||||
foreach (BarHud bar in bars)
|
||||
{
|
||||
AddDrawActions(bar.GetDrawActions(origin, Config.IfritBar.StrataLevel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTitanBar(Vector2 origin, IPlayerCharacter player)
|
||||
{
|
||||
SMNGauge gauge = Plugin.JobGauges.Get<SMNGauge>();
|
||||
int stackCount = gauge.IsTitanReady ? 1 : 0;
|
||||
|
||||
if (!Config.TitanBar.HideWhenInactive || stackCount > 1)
|
||||
{
|
||||
BarHud[] bars = BarUtilities.GetChunkedBars(Config.TitanBar, 1, stackCount, 1, 0, player);
|
||||
foreach (BarHud bar in bars)
|
||||
{
|
||||
AddDrawActions(bar.GetDrawActions(origin, Config.TitanBar.StrataLevel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawGarudaBar(Vector2 origin, IPlayerCharacter player)
|
||||
{
|
||||
SMNGauge gauge = Plugin.JobGauges.Get<SMNGauge>();
|
||||
int stackCount = gauge.IsGarudaReady ? 1 : 0;
|
||||
|
||||
if (!Config.GarudaBar.HideWhenInactive || stackCount > 1)
|
||||
{
|
||||
BarHud[] bars = BarUtilities.GetChunkedBars(Config.GarudaBar, 1, stackCount, 1, 0, player);
|
||||
foreach (BarHud bar in bars)
|
||||
{
|
||||
AddDrawActions(bar.GetDrawActions(origin, Config.GarudaBar.StrataLevel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum Primal
|
||||
{
|
||||
None = 0,
|
||||
Ifrit = 1,
|
||||
Titan = 2,
|
||||
Garuda = 3
|
||||
}
|
||||
|
||||
private unsafe void HandleAttunementStacks(Vector2 origin, IPlayerCharacter player)
|
||||
{
|
||||
SMNGauge gauge = Plugin.JobGauges.Get<SMNGauge>();
|
||||
|
||||
byte value = *((byte*)(new IntPtr(gauge.Address) + 0xE));
|
||||
Primal primal = (Primal)(value & 3);
|
||||
int stacks = ((value >> 2) & 7);
|
||||
|
||||
if (primal == Primal.Ifrit && Config.StacksBar.ShowIfritStacks)
|
||||
{
|
||||
DrawStacksBar(origin, player, stacks, 2, Config.StacksBar.IfritStackColor);
|
||||
}
|
||||
else if (primal == Primal.Titan && Config.StacksBar.ShowTitanStacks)
|
||||
{
|
||||
DrawStacksBar(origin, player, stacks, 4, Config.StacksBar.TitanStackColor);
|
||||
}
|
||||
else if (primal == Primal.Garuda && Config.StacksBar.ShowGarudaStacks)
|
||||
{
|
||||
DrawStacksBar(origin, player, stacks, 4, Config.StacksBar.GarudaStackColor);
|
||||
}
|
||||
else if (!Config.StacksBar.HideWhenInactive)
|
||||
{
|
||||
DrawStacksBar(origin, player, 0, 1, Config.StacksBar.FillColor);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawAetherBar(Vector2 origin, IPlayerCharacter player)
|
||||
{
|
||||
ushort stackCount = Utils.StatusListForBattleChara(player).FirstOrDefault(o => o.StatusId == 304)?.Param ?? 0;
|
||||
|
||||
if (Config.AetherflowBar.HideWhenInactive && stackCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BarHud[] bars = BarUtilities.GetChunkedBars(Config.AetherflowBar, 2, stackCount, 2, 0, player);
|
||||
foreach (BarHud bar in bars)
|
||||
{
|
||||
AddDrawActions(bar.GetDrawActions(origin, Config.AetherflowBar.StrataLevel));
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void DrawTranceBar(Vector2 origin, IPlayerCharacter player)
|
||||
{
|
||||
SMNGauge gauge = Plugin.JobGauges.Get<SMNGauge>();
|
||||
PluginConfigColor tranceColor;
|
||||
uint spellID = 0;
|
||||
float maxDuration = 0f;
|
||||
float currentCooldown = 0f;
|
||||
float tranceDuration = 0f;
|
||||
tranceColor = Config.TranceBar.FillColor;
|
||||
|
||||
// Dawntrail Fixes
|
||||
bool isSolarBahamutReady = gauge.AetherFlags.HasFlag(AetherFlags.None + 0x8) || // 0x8 Formerly Titan Attuned
|
||||
gauge.AetherFlags.HasFlag(AetherFlags.None + 0xC); // 0xC Formerly Garuda Attuned
|
||||
bool isPhoenixReady = gauge.AetherFlags.HasFlag(AetherFlags.None + 0x4); // 0x4 Formerly Ifrit Attuned
|
||||
bool isNormalBahamutReady = !isSolarBahamutReady && !isPhoenixReady; // You'd think it would be 0x10, but thats unused now
|
||||
|
||||
byte summonedPrimal = *((byte*)(new IntPtr(gauge.Address) + 0xE)); // Formally Attunement, now...?
|
||||
Primal primal = (Primal)(summonedPrimal & 3);
|
||||
|
||||
if (primal != Primal.None)
|
||||
{
|
||||
tranceColor = primal == Primal.Ifrit ? Config.TranceBar.IfritColor : primal == Primal.Titan ? Config.TranceBar.TitanColor : primal == Primal.Garuda ? Config.TranceBar.GarudaColor : Config.TranceBar.FillColor;
|
||||
tranceDuration = gauge.AttunementTimerRemaining;
|
||||
maxDuration = 30f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isSolarBahamutReady)
|
||||
{
|
||||
tranceColor = Config.TranceBar.SolarBahamutColor;
|
||||
tranceDuration = gauge.SummonTimerRemaining;
|
||||
spellID = 36992;
|
||||
maxDuration = 15f;
|
||||
}
|
||||
else if (isNormalBahamutReady)
|
||||
{
|
||||
tranceColor = Config.TranceBar.BahamutColor;
|
||||
tranceDuration = gauge.SummonTimerRemaining;
|
||||
spellID = 7427;
|
||||
maxDuration = 15f;
|
||||
}
|
||||
else if (isPhoenixReady)
|
||||
{
|
||||
tranceColor = Config.TranceBar.PhoenixColor;
|
||||
tranceDuration = gauge.SummonTimerRemaining;
|
||||
spellID = 25831;
|
||||
maxDuration = 15f;
|
||||
}
|
||||
}
|
||||
|
||||
if (tranceDuration != 0)
|
||||
{
|
||||
if (gauge.AttunementTimerRemaining > 0 && Config.TranceBar.HidePrimals)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Config.TranceBar.Label.SetValue(tranceDuration / 1000f);
|
||||
|
||||
BarHud bar = BarUtilities.GetProgressBar(Config.TranceBar, tranceDuration / 1000f, maxDuration, 0, player, tranceColor);
|
||||
AddDrawActions(bar.GetDrawActions(origin, Config.TranceBar.StrataLevel));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Config.TranceBar.HideWhenInactive)
|
||||
{
|
||||
if (gauge.AttunementTimerRemaining == 0)
|
||||
{
|
||||
maxDuration = SpellHelper.Instance.GetRecastTime(spellID);
|
||||
float tranceCooldown = SpellHelper.Instance.GetSpellCooldown(spellID);
|
||||
currentCooldown = maxDuration - tranceCooldown;
|
||||
|
||||
Config.TranceBar.Label.SetValue(maxDuration - currentCooldown);
|
||||
if (currentCooldown == maxDuration)
|
||||
{
|
||||
Config.TranceBar.Label.SetText("READY");
|
||||
}
|
||||
|
||||
BarHud bar = BarUtilities.GetProgressBar(Config.TranceBar, currentCooldown, maxDuration, 0, player, tranceColor);
|
||||
AddDrawActions(bar.GetDrawActions(origin, Config.TranceBar.StrataLevel));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawStacksBar(Vector2 origin, IPlayerCharacter player, int amount, int max, PluginConfigColor stackColor, BarGlowConfig? glowConfig = null)
|
||||
{
|
||||
SummonerStacksBarConfig config = Config.StacksBar;
|
||||
|
||||
config.FillColor = stackColor;
|
||||
|
||||
BarHud[] bars = BarUtilities.GetChunkedBars(Config.StacksBar, max, amount, max, 0f, player, glowConfig: glowConfig);
|
||||
foreach (BarHud bar in bars)
|
||||
{
|
||||
AddDrawActions(bar.GetDrawActions(origin, Config.StacksBar.StrataLevel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Section("Job Specific Bars")]
|
||||
[SubSection("Caster", 0)]
|
||||
[SubSection("Summoner", 1)]
|
||||
public class SummonerConfig : JobConfig
|
||||
{
|
||||
[JsonIgnore] public override uint JobId => JobIDs.SMN;
|
||||
public new static SummonerConfig DefaultConfig()
|
||||
{
|
||||
var config = new SummonerConfig();
|
||||
|
||||
config.TranceBar.Label.FontID = FontsConfig.DefaultMediumFontKey;
|
||||
config.UseDefaultPrimaryResourceBar = true;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
[NestedConfig("Aetherflow Bar", 40)]
|
||||
public ChunkedBarConfig AetherflowBar = new ChunkedBarConfig(
|
||||
new(-0, -7),
|
||||
new(254, 14),
|
||||
new(new Vector4(255f / 255f, 177f / 255f, 255f / 255f, 100f / 100f))
|
||||
);
|
||||
|
||||
[NestedConfig("Trance Bar", 45)]
|
||||
public SummonerTranceBarConfig TranceBar = new SummonerTranceBarConfig(
|
||||
new(0, -23),
|
||||
new(254, 14),
|
||||
new(new Vector4(128f / 255f, 255f / 255f, 255f / 255f, 100f / 100f))
|
||||
);
|
||||
|
||||
[NestedConfig("Ifrit Bar", 50)]
|
||||
public ChunkedBarConfig IfritBar = new ChunkedBarConfig(
|
||||
new(-85, -39),
|
||||
new(84, 14),
|
||||
new(new Vector4(200f / 255f, 40f / 255f, 0f / 255f, 100f / 100f))
|
||||
);
|
||||
|
||||
[NestedConfig("Titan Bar", 55)]
|
||||
public ChunkedBarConfig TitanBar = new ChunkedBarConfig(
|
||||
new(0, -39),
|
||||
new(84, 14),
|
||||
new(new Vector4(210f / 255f, 150f / 255f, 26f / 255f, 100f / 100f))
|
||||
);
|
||||
|
||||
[NestedConfig("Garuda Bar", 60)]
|
||||
public ChunkedBarConfig GarudaBar = new ChunkedBarConfig(
|
||||
new(85, -39),
|
||||
new(84, 14),
|
||||
new(new Vector4(60f / 255f, 160f / 255f, 100f / 255f, 100f / 100f))
|
||||
);
|
||||
|
||||
[NestedConfig("Attunement Stacks Bar", 65)]
|
||||
public SummonerStacksBarConfig StacksBar = new SummonerStacksBarConfig(
|
||||
new(0, -55),
|
||||
new(254, 14),
|
||||
new PluginConfigColor(new Vector4(255f / 255f, 255f / 255f, 255f / 255f, 0f / 100f))
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
[Exportable(false)]
|
||||
public class SummonerTranceBarConfig : ProgressBarConfig
|
||||
{
|
||||
[ColorEdit4("Bahamut Color")]
|
||||
[Order(26)]
|
||||
public PluginConfigColor BahamutColor = new(new Vector4(128f / 255f, 255f / 255f, 255f / 255f, 100f / 100f));
|
||||
|
||||
[ColorEdit4("Phoenix Color")]
|
||||
[Order(27)]
|
||||
public PluginConfigColor PhoenixColor = new(new Vector4(240f / 255f, 100f / 255f, 10f / 255f, 100f / 100f));
|
||||
|
||||
[ColorEdit4("Solar Bahamut Color")]
|
||||
[Order(28)]
|
||||
public PluginConfigColor SolarBahamutColor = new(new Vector4(235f / 255f, 241f / 255f, 252f / 255f, 100f / 100f));
|
||||
|
||||
[ColorEdit4("Ifrit Color")]
|
||||
[Order(29)]
|
||||
public PluginConfigColor IfritColor = new(new Vector4(200f / 255f, 40f / 255f, 0f / 255f, 100f / 100f));
|
||||
|
||||
[ColorEdit4("Titan Color")]
|
||||
[Order(30)]
|
||||
public PluginConfigColor TitanColor = new(new Vector4(210f / 255f, 150f / 255f, 26f / 255f, 100f / 100f));
|
||||
|
||||
[ColorEdit4("Garuda Color")]
|
||||
[Order(31)]
|
||||
public PluginConfigColor GarudaColor = new(new Vector4(60f / 255f, 160f / 255f, 100f / 255f, 100f / 100f));
|
||||
|
||||
[Checkbox("Hide Primals")]
|
||||
[Order(45)]
|
||||
public bool HidePrimals = false;
|
||||
|
||||
public SummonerTranceBarConfig(Vector2 position, Vector2 size, PluginConfigColor fillColor)
|
||||
: base(position, size, fillColor)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Exportable(false)]
|
||||
public class SummonerStacksBarConfig : ChunkedBarConfig
|
||||
{
|
||||
[Checkbox("Ifrit Stacks", separator = false, spacing = false)]
|
||||
[Order(51)]
|
||||
public bool ShowIfritStacks = true;
|
||||
|
||||
[Checkbox("Titan Stacks", separator = false, spacing = false)]
|
||||
[Order(53)]
|
||||
public bool ShowTitanStacks = true;
|
||||
|
||||
[Checkbox("Garuda Stacks", separator = false, spacing = false)]
|
||||
[Order(55)]
|
||||
public bool ShowGarudaStacks = true;
|
||||
|
||||
[ColorEdit4("Ifrit Stacks Color")]
|
||||
[Order(56)]
|
||||
public PluginConfigColor IfritStackColor = new(new Vector4(200f / 255f, 40f / 255f, 0f / 255f, 100f / 100f));
|
||||
|
||||
[ColorEdit4("Titan Stacks Color")]
|
||||
[Order(57)]
|
||||
public PluginConfigColor TitanStackColor = new(new Vector4(210f / 255f, 150f / 255f, 26f / 255f, 100f / 100f));
|
||||
|
||||
[ColorEdit4("Garuda Stacks Color")]
|
||||
[Order(58)]
|
||||
public PluginConfigColor GarudaStackColor = new(new Vector4(60f / 255f, 160f / 255f, 100f / 255f, 100f / 100f));
|
||||
|
||||
public SummonerStacksBarConfig(Vector2 position, Vector2 size, PluginConfigColor fillColor)
|
||||
: base(position, size, fillColor)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user