f37369cdda
Co-authored-by: Cursor <cursoragent@cursor.com>
465 lines
17 KiB
C#
465 lines
17 KiB
C#
using Dalamud.Game.ClientState.JobGauge.Enums;
|
|
using Dalamud.Game.ClientState.JobGauge.Types;
|
|
using Dalamud.Game.ClientState.Objects.SubKinds;
|
|
using Dalamud.Game.ClientState.Statuses;
|
|
using HSUI.Config;
|
|
using HSUI.Config.Attributes;
|
|
using HSUI.Enums;
|
|
using HSUI.Helpers;
|
|
using HSUI.Interface.Bars;
|
|
using HSUI.Interface.GeneralElements;
|
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
|
|
namespace HSUI.Interface.Jobs
|
|
{
|
|
public class MonkHud : JobHud
|
|
{
|
|
private new MonkConfig Config => (MonkConfig)_config;
|
|
|
|
private string[] _chunkTexts = new string[] { "I", "II", "III" };
|
|
|
|
public MonkHud(MonkConfig config, string? displayName = null) : base(config, displayName)
|
|
{
|
|
}
|
|
|
|
protected override (List<Vector2>, List<Vector2>) ChildrenPositionsAndSizes()
|
|
{
|
|
List<Vector2> positions = new List<Vector2>();
|
|
List<Vector2> sizes = new List<Vector2>();
|
|
|
|
if (Config.ChakraBar.Enabled)
|
|
{
|
|
positions.Add(Config.Position + Config.ChakraBar.Position);
|
|
sizes.Add(Config.ChakraBar.Size);
|
|
}
|
|
|
|
if (Config.BeastChakraStacksBar.Enabled)
|
|
{
|
|
positions.Add(Config.Position + Config.BeastChakraStacksBar.Position);
|
|
sizes.Add(Config.BeastChakraStacksBar.Size);
|
|
}
|
|
|
|
if (Config.MastersGauge.Enabled)
|
|
{
|
|
positions.Add(Config.Position + Config.MastersGauge.Position);
|
|
sizes.Add(Config.MastersGauge.Size);
|
|
}
|
|
|
|
if (Config.StancesBar.Enabled)
|
|
{
|
|
positions.Add((Config.Position + Config.StancesBar.Position));
|
|
sizes.Add(Config.StancesBar.Size);
|
|
}
|
|
|
|
if (Config.PerfectBalanceBar.Enabled)
|
|
{
|
|
positions.Add(Config.Position + Config.PerfectBalanceBar.Position);
|
|
sizes.Add(Config.PerfectBalanceBar.Size);
|
|
}
|
|
|
|
return (positions, sizes);
|
|
}
|
|
|
|
public override void DrawJobHud(Vector2 origin, IPlayerCharacter player)
|
|
{
|
|
var position = origin + Config.Position;
|
|
|
|
if (Config.ChakraBar.Enabled)
|
|
{
|
|
DrawChakraGauge(position, player);
|
|
}
|
|
|
|
if (Config.BeastChakraStacksBar.Enabled)
|
|
{
|
|
DrawBeastChakraStacksBar(position, player);
|
|
}
|
|
|
|
if (Config.MastersGauge.Enabled)
|
|
{
|
|
DrawMastersGauge(position, player);
|
|
}
|
|
|
|
if (Config.StancesBar.Enabled)
|
|
{
|
|
DrawFormsBar(position, player);
|
|
}
|
|
|
|
if (Config.PerfectBalanceBar.Enabled)
|
|
{
|
|
DrawPerfectBalanceBar(position, player);
|
|
}
|
|
}
|
|
|
|
private void DrawChakraGauge(Vector2 origin, IPlayerCharacter player)
|
|
{
|
|
MNKGauge gauge = Plugin.JobGauges.Get<MNKGauge>();
|
|
if (Config.ChakraBar.HideWhenInactive && gauge.Chakra == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
PluginConfigColor mainColor = Config.ChakraBar.FillColor;
|
|
PluginConfigColor extraColor = Config.ChakraBar.BrotherhoodExtraCharkaColor;
|
|
|
|
List<Tuple<PluginConfigColor, float, LabelConfig?>> chunks = new();
|
|
for (int i = 1; i < 6; i++)
|
|
{
|
|
PluginConfigColor color = (gauge.Chakra < i || gauge.Chakra - 5 < i) ? mainColor : extraColor;
|
|
chunks.Add(new(color, i <= gauge.Chakra ? 1 : 0, null));
|
|
}
|
|
|
|
BarHud[] bars = BarUtilities.GetChunkedBars(Config.ChakraBar, chunks.ToArray(), player);
|
|
foreach (BarHud bar in bars)
|
|
{
|
|
AddDrawActions(bar.GetDrawActions(origin, Config.ChakraBar.StrataLevel));
|
|
}
|
|
}
|
|
|
|
private unsafe void DrawBeastChakraStacksBar(Vector2 origin, IPlayerCharacter player)
|
|
{
|
|
MonkBeastChakraStacksBar config = Config.BeastChakraStacksBar;
|
|
MNKGauge gauge = Plugin.JobGauges.Get<MNKGauge>();
|
|
int stacks = gauge.OpoOpoFury + gauge.RaptorFury + gauge.CoeurlFury;
|
|
|
|
if (config.HideWhenInactive && stacks == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
PluginConfigColor empty = PluginConfigColor.Empty;
|
|
Tuple<PluginConfigColor, float, LabelConfig?>[] chunks =
|
|
[
|
|
new(gauge.OpoOpoFury > 0 ? config.OpoopoColor : empty, 1, null),
|
|
new(gauge.RaptorFury > 0 ? config.RaptorColor : empty, 1, null),
|
|
new(gauge.CoeurlFury > 0 ? config.CoeurlColor : empty, 1, null),
|
|
new(gauge.CoeurlFury > 1 ? config.CoeurlColor : empty, 1, null),
|
|
];
|
|
|
|
BarHud[] bars = BarUtilities.GetChunkedBars(config, chunks, player);
|
|
foreach (BarHud bar in bars)
|
|
{
|
|
AddDrawActions(bar.GetDrawActions(origin, config.StrataLevel));
|
|
}
|
|
}
|
|
|
|
private unsafe void DrawMastersGauge(Vector2 origin, IPlayerCharacter player)
|
|
{
|
|
MNKGauge gauge = Plugin.JobGauges.Get<MNKGauge>();
|
|
|
|
if (Config.MastersGauge.HideWhenInactive &&
|
|
gauge.Nadi == Nadi.None &&
|
|
gauge.BeastChakra[0] == BeastChakra.None &&
|
|
gauge.BeastChakra[1] == BeastChakra.None &&
|
|
gauge.BeastChakra[2] == BeastChakra.None)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int[] order = Config.MastersGauge.ChakraOrder;
|
|
int[] hasChakra =
|
|
[
|
|
gauge.Nadi.HasFlag(Nadi.Lunar) ? 1 : 0,
|
|
gauge.BeastChakra[0] != BeastChakra.None ? 1 : 0,
|
|
gauge.BeastChakra[0] != BeastChakra.None ? 1 : 0,
|
|
gauge.BeastChakra[0] != BeastChakra.None ? 1 : 0,
|
|
gauge.Nadi.HasFlag(Nadi.Solar) ? 1 : 0,
|
|
];
|
|
|
|
PluginConfigColor[] colors = new[]
|
|
{
|
|
Config.MastersGauge.LunarNadiColor,
|
|
GetChakraColor(gauge.BeastChakra[0]),
|
|
GetChakraColor(gauge.BeastChakra[1]),
|
|
GetChakraColor(gauge.BeastChakra[2]),
|
|
Config.MastersGauge.SolarNadiColor
|
|
};
|
|
|
|
var chunks = new Tuple<PluginConfigColor, float, LabelConfig?>[5];
|
|
for (int i = 0; i < chunks.Length; i++)
|
|
{
|
|
chunks[i] = new(colors[order[i]], hasChakra[order[i]], i == 2 ? Config.MastersGauge.BlitzTimerLabel : null);
|
|
}
|
|
|
|
Config.MastersGauge.BlitzTimerLabel.SetValue(gauge.BlitzTimeRemaining / 1000);
|
|
|
|
BarHud[] bars = BarUtilities.GetChunkedBars(Config.MastersGauge, chunks, player);
|
|
foreach (BarHud bar in bars)
|
|
{
|
|
AddDrawActions(bar.GetDrawActions(origin, Config.MastersGauge.StrataLevel));
|
|
}
|
|
}
|
|
|
|
private void DrawFormsBar(Vector2 origin, IPlayerCharacter player)
|
|
{
|
|
// formless fist
|
|
IStatus? formlessFist = Utils.StatusListForBattleChara(player).FirstOrDefault(o => o.StatusId == 2513);
|
|
if (formlessFist != null)
|
|
{
|
|
float remaining = Math.Abs(formlessFist.RemainingTime);
|
|
|
|
BarHud bar = BarUtilities.GetProgressBar(
|
|
Config.StancesBar,
|
|
null,
|
|
new LabelConfig[] { Config.StancesBar.FormlessFistLabel },
|
|
remaining,
|
|
30f,
|
|
0,
|
|
player,
|
|
Config.StancesBar.FormlessFistColor
|
|
);
|
|
|
|
Config.StancesBar.FormlessFistLabel.SetValue(remaining);
|
|
|
|
AddDrawActions(bar.GetDrawActions(origin, Config.StancesBar.StrataLevel));
|
|
return;
|
|
}
|
|
|
|
// forms
|
|
IStatus? form = Utils.StatusListForBattleChara(player).FirstOrDefault(o => o.StatusId is 107 or 108 or 109);
|
|
if (Config.StancesBar.HideWhenInactive && form is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int activeFormIndex = form != null ? (int)form.StatusId - 107 : -1;
|
|
PluginConfigColor[] chunkColors = new PluginConfigColor[]
|
|
{
|
|
Config.StancesBar.OpoOpoColor,
|
|
Config.StancesBar.RaptorColor,
|
|
Config.StancesBar.CoeurlColor
|
|
};
|
|
|
|
LabelConfig[] chunkLabels = new LabelConfig[]
|
|
{
|
|
Config.StancesBar.FormLabel.Clone(0),
|
|
Config.StancesBar.FormLabel.Clone(1),
|
|
Config.StancesBar.FormLabel.Clone(2)
|
|
};
|
|
|
|
var chunks = new Tuple<PluginConfigColor, float, LabelConfig?>[3];
|
|
for (int i = 0; i < chunks.Length; i++)
|
|
{
|
|
LabelConfig label = chunkLabels[i];
|
|
label.SetText(_chunkTexts[i]);
|
|
|
|
chunks[i] = new(chunkColors[i], activeFormIndex == i ? 1 : 0, label);
|
|
}
|
|
|
|
BarHud[] bars = BarUtilities.GetChunkedBars(Config.StancesBar, chunks, player);
|
|
foreach (BarHud bar in bars)
|
|
{
|
|
AddDrawActions(bar.GetDrawActions(origin, Config.StancesBar.StrataLevel));
|
|
}
|
|
}
|
|
|
|
private void DrawPerfectBalanceBar(Vector2 origin, IPlayerCharacter player)
|
|
{
|
|
IStatus? perfectBalance = Utils.StatusListForBattleChara(player).Where(o => o.StatusId is 110 && o.RemainingTime > 0f).FirstOrDefault();
|
|
float duration = perfectBalance?.RemainingTime ?? 0f;
|
|
float stacks = perfectBalance?.Param ?? 0f;
|
|
|
|
if (Config.PerfectBalanceBar.HideWhenInactive && duration <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Tuple<PluginConfigColor, float, LabelConfig?>[] chunks = new Tuple<PluginConfigColor, float, LabelConfig?>[3];
|
|
for (int i = 0; i < chunks.Length; i++)
|
|
{
|
|
chunks[i] = new(
|
|
Config.PerfectBalanceBar.FillColor,
|
|
i < stacks ? 1f : 0,
|
|
i == 1 ? Config.PerfectBalanceBar.PerfectBalanceLabel : null
|
|
);
|
|
}
|
|
|
|
Config.PerfectBalanceBar.PerfectBalanceLabel.SetValue(duration);
|
|
|
|
BarHud[] bars = BarUtilities.GetChunkedBars(Config.PerfectBalanceBar, chunks, player);
|
|
foreach (BarHud bar in bars)
|
|
{
|
|
AddDrawActions(bar.GetDrawActions(origin, Config.PerfectBalanceBar.StrataLevel));
|
|
}
|
|
}
|
|
|
|
private PluginConfigColor GetChakraColor(BeastChakra chakra) => chakra switch
|
|
{
|
|
BeastChakra.OpoOpo => Config.MastersGauge.OpoopoChakraColor,
|
|
BeastChakra.Raptor => Config.MastersGauge.RaptorChakraColor,
|
|
BeastChakra.Coeurl => Config.MastersGauge.CoeurlChakraColor,
|
|
_ => new PluginConfigColor(new(0, 0, 0, 0))
|
|
};
|
|
}
|
|
|
|
[Section("Job Specific Bars")]
|
|
[SubSection("Melee", 0)]
|
|
[SubSection("Monk", 1)]
|
|
public class MonkConfig : JobConfig
|
|
{
|
|
[JsonIgnore] public override uint JobId => JobIDs.MNK;
|
|
|
|
public new static MonkConfig DefaultConfig()
|
|
{
|
|
var config = new MonkConfig();
|
|
|
|
config.StancesBar.Enabled = false;
|
|
config.MastersGauge.BlitzTimerLabel.HideIfZero = true;
|
|
config.PerfectBalanceBar.PerfectBalanceLabel.HideIfZero = true;
|
|
|
|
return config;
|
|
}
|
|
|
|
[NestedConfig("Chakra Bar", 35)]
|
|
public ChakraBar ChakraBar = new ChakraBar(
|
|
new(0, -32),
|
|
new(254, 20),
|
|
new(new Vector4(204f / 255f, 115f / 255f, 0f, 100f / 100f))
|
|
);
|
|
|
|
[NestedConfig("Fury Stacks Bar", 40)]
|
|
public MonkBeastChakraStacksBar BeastChakraStacksBar = new MonkBeastChakraStacksBar(
|
|
new(0, -32),
|
|
new(254, 20)
|
|
);
|
|
|
|
[NestedConfig("Masterful Blitz Bar", 45)]
|
|
public MastersGauge MastersGauge = new MastersGauge(
|
|
new(0, -54),
|
|
new(254, 20)
|
|
);
|
|
|
|
[NestedConfig("Forms Bar", 50)]
|
|
public MonkStancesBarConfig StancesBar = new MonkStancesBarConfig(
|
|
new(0, -98),
|
|
new(254, 20)
|
|
);
|
|
|
|
[NestedConfig("Perfect Balance Bar", 55)]
|
|
public PerfectBalanceBar PerfectBalanceBar = new PerfectBalanceBar(
|
|
new(0, -76),
|
|
new(254, 20),
|
|
new(new Vector4(150f / 255f, 255f / 255f, 255f / 255f, 100f / 100f))
|
|
);
|
|
}
|
|
|
|
public class ChakraBar: ChunkedBarConfig
|
|
{
|
|
[ColorEdit4("Brotherhood Extra Chakra Color")]
|
|
[Order(26)]
|
|
public PluginConfigColor BrotherhoodExtraCharkaColor = new(new Vector4(204f / 255f, 0, 0, 1));
|
|
|
|
public ChakraBar(Vector2 position, Vector2 size, PluginConfigColor fillColor, int padding = 2) : base(position, size, fillColor, padding)
|
|
{
|
|
}
|
|
}
|
|
|
|
public class PerfectBalanceBar : ChunkedBarConfig
|
|
{
|
|
[NestedConfig("Perfect Balance Duration Text", 50, spacing = true)]
|
|
public NumericLabelConfig PerfectBalanceLabel;
|
|
|
|
public PerfectBalanceBar(Vector2 position, Vector2 size, PluginConfigColor fillColor, int padding = 2) : base(position, size, fillColor, padding)
|
|
{
|
|
PerfectBalanceLabel = new NumericLabelConfig(Vector2.Zero, "", DrawAnchor.Center, DrawAnchor.Center);
|
|
}
|
|
}
|
|
|
|
[DisableParentSettings("FillColor", "FillDirection")]
|
|
public class MonkBeastChakraStacksBar : ChunkedBarConfig
|
|
{
|
|
[ColorEdit4("Opo-opo Color")]
|
|
[Order(19)]
|
|
public PluginConfigColor OpoopoColor = PluginConfigColor.FromHex(0xFFFFB3D3);
|
|
|
|
[ColorEdit4("Raptor Color")]
|
|
[Order(20)]
|
|
public PluginConfigColor RaptorColor = PluginConfigColor.FromHex(0xFFBF89E5);
|
|
|
|
[ColorEdit4("Coeurl Color")]
|
|
[Order(21)]
|
|
public PluginConfigColor CoeurlColor = PluginConfigColor.FromHex(0xFF9AE7C0);
|
|
|
|
public MonkBeastChakraStacksBar(Vector2 position, Vector2 size)
|
|
: base(position, size, PluginConfigColor.Empty)
|
|
{
|
|
}
|
|
}
|
|
|
|
[DisableParentSettings("FillColor", "FillDirection")]
|
|
public class MastersGauge : ChunkedBarConfig
|
|
{
|
|
[ColorEdit4("Lunar Nadi Color")]
|
|
[Order(19)]
|
|
public PluginConfigColor LunarNadiColor = PluginConfigColor.FromHex(0xFFDA87FF);
|
|
|
|
[ColorEdit4("Solar Nadi Color")]
|
|
[Order(20)]
|
|
public PluginConfigColor SolarNadiColor = PluginConfigColor.FromHex(0xFFFFFFCA);
|
|
|
|
[ColorEdit4("Opo-opo Color")]
|
|
[Order(21)]
|
|
public PluginConfigColor OpoopoChakraColor = PluginConfigColor.FromHex(0xFFC1527E);
|
|
|
|
[ColorEdit4("Raptor Color")]
|
|
[Order(22)]
|
|
public PluginConfigColor RaptorChakraColor = PluginConfigColor.FromHex(0xFF8C67BA);
|
|
|
|
[ColorEdit4("Coeurl Color")]
|
|
[Order(23)]
|
|
public PluginConfigColor CoeurlChakraColor = PluginConfigColor.FromHex(0xFF326D5A);
|
|
|
|
[DragDropHorizontal("Chakra Order", "Lunar Nadi", "Chakra 1", "Chakra 2", "Chakra 3", "Solar Nadi")]
|
|
[Order(24)]
|
|
public int[] ChakraOrder = new int[] { 0, 1, 2, 3, 4 };
|
|
|
|
[NestedConfig("Blitz Timer Text", 50, spacing = true)]
|
|
public NumericLabelConfig BlitzTimerLabel;
|
|
|
|
public MastersGauge(Vector2 position, Vector2 size)
|
|
: base(position, size, PluginConfigColor.Empty)
|
|
{
|
|
BlitzTimerLabel = new NumericLabelConfig(Vector2.Zero, "", DrawAnchor.Center, DrawAnchor.Center);
|
|
}
|
|
}
|
|
|
|
[DisableParentSettings("FillColor")]
|
|
public class MonkStancesBarConfig : ChunkedBarConfig
|
|
{
|
|
[ColorEdit4("Opo-opo Color")]
|
|
[Order(19)]
|
|
public PluginConfigColor OpoOpoColor = PluginConfigColor.FromHex(0xFFFFB3D3);
|
|
|
|
[ColorEdit4("Raptor Color")]
|
|
[Order(20)]
|
|
public PluginConfigColor RaptorColor = PluginConfigColor.FromHex(0xFFBF89E5);
|
|
|
|
[ColorEdit4("Coeurl Color")]
|
|
[Order(21)]
|
|
public PluginConfigColor CoeurlColor = PluginConfigColor.FromHex(0xFF9AE7C0);
|
|
|
|
[ColorEdit4("Formless Fist Color")]
|
|
[Order(22)]
|
|
public PluginConfigColor FormlessFistColor = PluginConfigColor.FromHex(0xFF514793);
|
|
|
|
[NestedConfig("Form Number Text", 500, spacing = true)]
|
|
public LabelConfig FormLabel;
|
|
|
|
[NestedConfig("Formless Fist Duration Text", 1000, separator = false, spacing = true)]
|
|
public NumericLabelConfig FormlessFistLabel;
|
|
|
|
public MonkStancesBarConfig(Vector2 position, Vector2 size)
|
|
: base(position, size, PluginConfigColor.Empty)
|
|
{
|
|
FormLabel = new LabelConfig(Vector2.Zero, "", DrawAnchor.Center, DrawAnchor.Center);
|
|
|
|
FormlessFistLabel = new NumericLabelConfig(Vector2.Zero, "", DrawAnchor.Center, DrawAnchor.Center);
|
|
FormlessFistLabel.Enabled = false;
|
|
}
|
|
}
|
|
}
|