c5b8e48072
Co-authored-by: Cursor <cursoragent@cursor.com>
141 lines
5.3 KiB
C#
141 lines
5.3 KiB
C#
using System;
|
|
using HSUI.Helpers;
|
|
using Dalamud.Bindings.ImGui;
|
|
using System.Collections.Generic;
|
|
using System.Numerics;
|
|
using HSUI.Config;
|
|
using Dalamud.Game.ClientState.Objects.SubKinds;
|
|
using Dalamud.Game.ClientState.Objects.Types;
|
|
|
|
namespace HSUI.Interface.GeneralElements
|
|
{
|
|
public class MouseGCDIndicatorHud : DraggableHudElement, IHudElementWithActor, IHudElementWithVisibilityConfig
|
|
{
|
|
private MouseGCDIndicatorConfig Config => (MouseGCDIndicatorConfig)_config;
|
|
public VisibilityConfig VisibilityConfig => Config.VisibilityConfig;
|
|
|
|
public IGameObject? Actor { get; set; } = null;
|
|
|
|
private float _lastTotalCastTime = 0;
|
|
|
|
public MouseGCDIndicatorHud(MouseGCDIndicatorConfig config, string displayName) : base(config, displayName) { }
|
|
|
|
protected override (List<Vector2>, List<Vector2>) ChildrenPositionsAndSizes()
|
|
{
|
|
return (new List<Vector2>(), new List<Vector2>());
|
|
}
|
|
|
|
protected override void DrawDraggableArea(Vector2 origin)
|
|
{
|
|
return;
|
|
}
|
|
|
|
public override void DrawChildren(Vector2 origin)
|
|
{
|
|
if (!Config.Enabled || Actor == null || Actor is not IPlayerCharacter)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GCDHelper.GetGCDInfo((IPlayerCharacter)Actor, out var elapsed, out var total);
|
|
|
|
if (!Config.AlwaysShow && total == 0)
|
|
{
|
|
_lastTotalCastTime = 0;
|
|
return;
|
|
}
|
|
|
|
if (_lastTotalCastTime == 0 && Utils.IsActorCasting(Actor))
|
|
{
|
|
_lastTotalCastTime = ((IBattleChara)Actor).TotalCastTime;
|
|
}
|
|
|
|
var scale = elapsed / total;
|
|
if (scale <= 0)
|
|
{
|
|
_lastTotalCastTime = 0;
|
|
return;
|
|
}
|
|
|
|
bool instantGCDsOnly = Config.InstantGCDsOnly && _lastTotalCastTime != 0;
|
|
bool thresholdGCDs = Config.LimitGCDThreshold && _lastTotalCastTime > Config.GCDThreshold;
|
|
|
|
if (instantGCDsOnly || thresholdGCDs)
|
|
{
|
|
if (Config.AlwaysShow)
|
|
{
|
|
elapsed = 0;
|
|
total = 0;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
Vector2 center = ImGui.GetMousePos() + Config.CursorCenterOffset;
|
|
AddDrawAction(_config.StrataLevel, () =>
|
|
{
|
|
DrawCircularIndicator(center, Config.CircleRadius, elapsed, total);
|
|
});
|
|
}
|
|
|
|
private void DrawCircularIndicator(Vector2 position, float radius, float current, float total)
|
|
{
|
|
total = Config.AlwaysShow && total == 0 ? 1 : total;
|
|
current = Config.AlwaysShow && current == 0 ? total : current;
|
|
|
|
var size = new Vector2(radius * 2);
|
|
DrawHelper.DrawInWindow(ID, position - size / 2, size, false, (drawList) =>
|
|
{
|
|
current = Math.Min(current, total);
|
|
|
|
const int segments = 100;
|
|
const float queueTime = 0.5f;
|
|
float startAngle = 0f;
|
|
float endAngle = 2f * (float)Math.PI;
|
|
float offset = (float)(-Math.PI / 2f + (Config.CircleStartAngle * (Math.PI / 180f)));
|
|
|
|
if (Config.RotateCCW)
|
|
{
|
|
startAngle *= -1;
|
|
endAngle *= -1;
|
|
}
|
|
|
|
if (Config.AlwaysShow && current == total)
|
|
{
|
|
drawList.PathArcTo(position, radius, startAngle + offset, endAngle + offset, segments);
|
|
drawList.PathStroke(Config.FillColor.Base, ImDrawFlags.None, Config.CircleThickness);
|
|
}
|
|
else
|
|
{
|
|
float progressAngle = Math.Min(current, total - (Config.ShowGCDQueueIndicator ? queueTime : 0f)) / total * endAngle;
|
|
|
|
drawList.PathArcTo(position, radius, startAngle + offset, progressAngle + offset, segments);
|
|
drawList.PathStroke(Config.FillColor.Base, ImDrawFlags.None, Config.CircleThickness);
|
|
|
|
if (Config.ShowGCDQueueIndicator && current > total - queueTime)
|
|
{
|
|
float oldAngle = progressAngle - 0.0003f * total * endAngle;
|
|
progressAngle = current / total * endAngle;
|
|
drawList.PathArcTo(position, radius, oldAngle + offset, progressAngle + offset, segments);
|
|
drawList.PathStroke(Config.QueueColor.Base, ImDrawFlags.None, Config.CircleThickness);
|
|
}
|
|
|
|
drawList.PathArcTo(position, radius, progressAngle + offset, endAngle + offset, segments);
|
|
drawList.PathStroke(Config.BackgroundColor.Base, ImDrawFlags.None, Config.CircleThickness);
|
|
}
|
|
|
|
if (Config.ShowBorder)
|
|
{
|
|
drawList.PathArcTo(position, radius - Config.CircleThickness / 2f, 0, endAngle, segments);
|
|
drawList.PathStroke(0xFF000000, ImDrawFlags.None, 1);
|
|
|
|
drawList.PathArcTo(position, radius + Config.CircleThickness / 2f, 0, endAngle, segments);
|
|
drawList.PathStroke(0xFF000000, ImDrawFlags.None, 1);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|