Files

373 lines
14 KiB
C#

using Dalamud.Game.ClientState.JobGauge.Types;
using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.ClientState.Objects.Types;
using HSUI.Config;
using HSUI.Config.Attributes;
using HSUI.Helpers;
using HSUI.Interface.Bars;
using HSUI.Interface.GeneralElements;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
namespace HSUI.Interface.Jobs
{
public class ViperHud : JobHud
{
private new ViperConfig Config => (ViperConfig)_config;
public ViperHud(ViperConfig 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.RattlingCoilGauge.Enabled)
{
positions.Add(Config.Position + Config.RattlingCoilGauge.Position);
sizes.Add(Config.RattlingCoilGauge.Size);
}
if (Config.Vipersight.Enabled)
{
positions.Add(Config.Position + Config.Vipersight.Position);
sizes.Add(Config.Vipersight.Size);
}
if (Config.AnguineTribute.Enabled)
{
positions.Add(Config.Position + Config.AnguineTribute.Position);
sizes.Add(Config.AnguineTribute.Size);
}
if (Config.SerpentOfferings.Enabled)
{
positions.Add(Config.Position + Config.SerpentOfferings.Position);
sizes.Add(Config.SerpentOfferings.Size);
}
return (positions, sizes);
}
public override void DrawJobHud(Vector2 origin, IPlayerCharacter player)
{
if (Config.RattlingCoilGauge.Enabled)
{
DrawRattlingCoilGauge(origin + Config.Position, player);
}
if (Config.Vipersight.Enabled)
{
DrawVipersightBar(origin + Config.Position, player);
}
if (Config.SerpentOfferings.Enabled)
{
DrawSerpentOfferingsBar(origin + Config.Position, player);
}
if (Config.AnguineTribute.Enabled)
{
DrawAnguineTributeGauge(origin + Config.Position, player);
}
}
private unsafe void DrawVipersightBar(Vector2 origin, IPlayerCharacter player)
{
ViperCombo lastUsedActionId = (ViperCombo)SpellHelper.Instance.GetLastUsedActionId();
ViperComboState comboState;
bool isAoE = false;
switch (lastUsedActionId)
{
case ViperCombo.SteelMaw:
case ViperCombo.DreadMaw:
isAoE = true;
comboState = ViperComboState.Started;
break;
case ViperCombo.SteelFangs:
case ViperCombo.DreadFangs:
comboState = ViperComboState.Started;
break;
case ViperCombo.HuntersBite:
case ViperCombo.SwiftskinsBite:
isAoE = true;
comboState = ViperComboState.Finisher;
break;
case ViperCombo.HuntersSting:
case ViperCombo.SwiftskinsSting:
comboState = ViperComboState.Finisher;
break;
default:
comboState = ViperComboState.None;
break;
}
if (Config.Vipersight.HideWhenInactive && comboState == ViperComboState.None)
{
return;
}
uint leftId = SpellHelper.Instance.GetSpellActionId(isAoE ? (uint)ViperCombo.SteelMaw : (uint)ViperCombo.SteelFangs);
bool isLeftGlowing = SpellHelper.Instance.IsActionHighlighted(leftId);
uint rightId = SpellHelper.Instance.GetSpellActionId(isAoE ? (uint)ViperCombo.DreadMaw : (uint)ViperCombo.DreadFangs);
bool isRightGlowing = SpellHelper.Instance.IsActionHighlighted(rightId);
List<Tuple<PluginConfigColor, float, LabelConfig?>> chunks = new();
List<bool> glows = new();
Tuple<PluginConfigColor, float, LabelConfig?> empty = new(PluginConfigColor.Empty, 1, null);
Tuple<PluginConfigColor, float, LabelConfig?> start = new(Config.Vipersight.ComboStartColor, 1, null);
Tuple<PluginConfigColor, float, LabelConfig?> endFlank = new(Config.Vipersight.ComboEndFlankColor, 1, null);
Tuple<PluginConfigColor, float, LabelConfig?> endHind = new(Config.Vipersight.ComboEndHindColor, 1, null);
Tuple<PluginConfigColor, float, LabelConfig?> endAoE = new(Config.Vipersight.ComboEndAOEColor, 1, null);
bool isFlankEnder = Utils.StatusListForBattleChara(player).Any(o => o.StatusId is 3645 or 3646);
bool isHindEnder = Utils.StatusListForBattleChara(player).Any(o => o.StatusId is 3647 or 3648);
bool noEnder = !isFlankEnder && !isHindEnder;
switch (comboState)
{
case ViperComboState.None:
{
chunks = [empty, empty, empty, empty];
glows = [false, isLeftGlowing, isRightGlowing, false];
break;
}
case ViperComboState.Started:
{
chunks = [empty, start, start, empty];
glows = [false, isLeftGlowing || isAoE, isRightGlowing || isAoE, false];
break;
}
case ViperComboState.Finisher:
{
bool isFlankChain = lastUsedActionId == ViperCombo.HuntersSting;
bool isHindChain = lastUsedActionId == ViperCombo.SwiftskinsSting;
Tuple<PluginConfigColor, float, LabelConfig?> end;
if (isFlankEnder)
{
end = isHindChain ? endHind : endFlank;
}
else if (isHindEnder)
{
end = isFlankChain ? endFlank : endHind;
}
else
{
end = isFlankChain ? endFlank : isHindChain ? endHind : endAoE;
}
chunks = [end, start, start, end];
glows = [isLeftGlowing, isLeftGlowing, isRightGlowing, isRightGlowing];
break;
}
}
if (Config.Vipersight.Invert)
{
chunks.Reverse();
glows.Reverse();
}
BarHud[] bars = BarUtilities.GetChunkedBars(
Config.Vipersight,
chunks.ToArray(),
player,
Config.Vipersight.GlowConfig,
glows.ToArray()
);
foreach (BarHud bar in bars)
{
AddDrawActions(bar.GetDrawActions(origin, Config.Vipersight.StrataLevel));
}
}
private unsafe void DrawRattlingCoilGauge(Vector2 origin, IPlayerCharacter player)
{
VPRGauge gauge = Plugin.JobGauges.Get<VPRGauge>();
if (Config.RattlingCoilGauge.HideWhenInactive && gauge.RattlingCoilStacks <= 0)
{
return;
}
int maxStacks = player.Level >= 88 ? 3 : 2;
BarHud[] bars = BarUtilities.GetChunkedBars(Config.RattlingCoilGauge, maxStacks, gauge.RattlingCoilStacks, maxStacks, 0, player);
foreach (BarHud bar in bars)
{
AddDrawActions(bar.GetDrawActions(origin, Config.RattlingCoilGauge.StrataLevel));
}
}
private unsafe void DrawAnguineTributeGauge(Vector2 origin, IPlayerCharacter player)
{
VPRGauge gauge = Plugin.JobGauges.Get<VPRGauge>();
if (Config.AnguineTribute.HideWhenInactive && gauge.AnguineTribute <= 0)
{
return;
}
int maxStacks = player.Level >= 96 ? 5 : 4;
BarHud[] bars = BarUtilities.GetChunkedBars(Config.AnguineTribute, maxStacks, gauge.AnguineTribute, maxStacks, 0, player);
foreach (BarHud bar in bars)
{
AddDrawActions(bar.GetDrawActions(origin, Config.AnguineTribute.StrataLevel));
}
}
private unsafe void DrawSerpentOfferingsBar(Vector2 origin, IPlayerCharacter player)
{
ViperConfig.SerpentOfferingsBarConfig config = Config.SerpentOfferings;
VPRGauge gauge = Plugin.JobGauges.Get<VPRGauge>();
float reawakenedDuration = Utils.StatusListForBattleChara(player).FirstOrDefault(o => o.StatusId is 3670 or 4094 && o.RemainingTime > 0f)?.RemainingTime ?? 0f;
bool reAwakenedReady = Utils.StatusListForBattleChara(player).Any(o => o.StatusId is 3671) || gauge.SerpentOffering >= 50;
bool isReawakened = reawakenedDuration > 0;
bool showReawakened = isReawakened && config.EnableAwakenedTimer;
float serpentOffering = showReawakened && isReawakened ? reawakenedDuration : gauge.SerpentOffering;
if (Config.SerpentOfferings.HideWhenInactive && gauge.SerpentOffering <= 0)
{
return;
}
Config.SerpentOfferings.Label.SetValue(serpentOffering);
BarHud[] bars = BarUtilities.GetChunkedProgressBars(
config,
showReawakened ? 1 : 2,
showReawakened ? reawakenedDuration : serpentOffering,
showReawakened ? 30f : 100f,
fillColor: reAwakenedReady ? config.AwakenedColor : config.FillColor
); ;
foreach (BarHud bar in bars)
{
AddDrawActions(bar.GetDrawActions(origin, Config.SerpentOfferings.StrataLevel));
}
}
}
public enum ViperCombo
{
SteelFangs = 34606,
DreadFangs = 34607,
HuntersSting = 34608,
SwiftskinsSting = 34609,
SteelMaw = 34614,
DreadMaw = 34615,
HuntersBite = 34616,
SwiftskinsBite = 34617
}
public enum ViperComboState
{
None,
Started,
Finisher
}
[Section("Job Specific Bars")]
[SubSection("Melee", 0)]
[SubSection("Viper", 1)]
public class ViperConfig : JobConfig
{
[JsonIgnore] public override uint JobId => JobIDs.VPR;
public new static ViperConfig DefaultConfig()
{
var config = new ViperConfig();
config.SerpentOfferings.UseChunks = false;
return config;
}
[NestedConfig("Vipersight Bar", 30)]
public VipersightBarConfig Vipersight = new VipersightBarConfig(
new(0, -10),
new(254, 10),
new(new Vector4(237f / 255f, 141f / 255f, 7f / 255f, 100f / 100f))
);
[NestedConfig("Rattling Coil Bar", 40)]
public ChunkedBarConfig RattlingCoilGauge = new ChunkedBarConfig(
new(0, -34),
new(254, 10),
new(new Vector4(204f / 255f, 40f / 255f, 40f / 255f, 1f))
);
[NestedConfig("Serpent Offerings Bar", 45)]
public SerpentOfferingsBarConfig SerpentOfferings = new SerpentOfferingsBarConfig(
new(0, -46),
new(254, 10),
new(new Vector4(69f / 255f, 115f / 255f, 202f / 255f, 1f))
);
[NestedConfig("Anguine Tribute Bar", 50)]
public ChunkedBarConfig AnguineTribute = new ChunkedBarConfig(
new(0, -58),
new(254, 10),
new(new Vector4(69f / 255f, 115f / 255f, 202f / 255f, 1f))
);
[Exportable(false)]
public class VipersightBarConfig : ChunkedBarConfig
{
[NestedConfig("Show Glow", 39, separator = false, spacing = true)]
public BarGlowConfig GlowConfig = new BarGlowConfig();
[ColorEdit4("Combo Start", spacing = true)]
[Order(41)]
public PluginConfigColor ComboStartColor = new(new Vector4(230f / 255f, 33f / 255f, 33f / 255f, 100f / 100f));
[ColorEdit4("Flank Ender")]
[Order(42)]
public PluginConfigColor ComboEndFlankColor = new(new Vector4(46f / 255f, 228f / 255f, 42f / 255f, 1f));
[ColorEdit4("Hind Ender")]
[Order(43)]
public PluginConfigColor ComboEndHindColor = new(new Vector4(230f / 255f, 33f / 255f, 33f / 255f, 1f));
[ColorEdit4("Grim/Default Ender")]
[Order(44)]
public PluginConfigColor ComboEndAOEColor = new(new Vector4(69f / 255f, 115f / 255f, 202f / 255f, 1f));
[Checkbox("Invert", spacing = true)]
[Order(45)]
public bool Invert = false;
public VipersightBarConfig(Vector2 position, Vector2 size, PluginConfigColor fillColor)
: base(position, size, fillColor)
{
}
}
[Exportable(false)]
public class SerpentOfferingsBarConfig : ChunkedProgressBarConfig
{
[Checkbox("Enable Awakened Timer", spacing = true)]
[Order(46)]
public bool EnableAwakenedTimer = true;
[ColorEdit4("Ready to Reawaken Color")]
[Order(47)]
public PluginConfigColor AwakenedColor = new(new Vector4(69f / 255f, 115f / 255f, 202f / 255f, 1f));
public SerpentOfferingsBarConfig(Vector2 position, Vector2 size, PluginConfigColor fillColor)
: base(position, size, fillColor)
{
}
}
}
}