feat: add clearing settings

This commit is contained in:
Anna 2024-07-25 18:21:46 -04:00
parent 867203a86c
commit e471548e81
Signed by: anna
GPG Key ID: D0943384CD9F87D1
3 changed files with 121 additions and 12 deletions

View File

@ -24,6 +24,8 @@ public class Configuration : IPluginConfiguration {
public int TextMulRed = 100;
public int TextMulGreen = 100;
public int TextMulBlue = 100;
public bool ClearResultsOnInactive = true;
public float ClearDelaySeconds = 10;
}
public enum MeterMode {

124
Plugin.cs
View File

@ -3,11 +3,14 @@ using System.Globalization;
using System.Text;
using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
using Dalamud.Game.Gui.ContextMenu;
using Dalamud.Game.Text;
using Dalamud.IoC;
using Dalamud.Memory;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Group;
using FFXIVClientStructs.FFXIV.Client.Graphics;
using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
@ -37,14 +40,21 @@ public class Plugin : IDalamudPlugin {
[PluginService]
internal ICommandManager CommandManager { get; init; }
[PluginService]
internal IContextMenu ContextMenu { get; init; }
internal Configuration Config { get; }
private Client Client { get; }
internal PluginUi Ui { get; }
private Commands Commands { get; }
private Stopwatch Watch { get; } = Stopwatch.StartNew();
private Stopwatch AlternateWatch { get; } = Stopwatch.StartNew();
private Stopwatch DelayWatch { get; } = new();
private bool _ranLastTick;
private bool _showDps = true;
private bool _reset;
private bool _wasActive;
private bool _manuallyReset = true;
private readonly byte[] _manaUsers = [
6, // cnj
@ -70,9 +80,11 @@ public class Plugin : IDalamudPlugin {
this.Commands = new Commands(this);
this.AddonLifecycle!.RegisterListener(AddonEvent.PostUpdate, "_PartyList", this.UpdateList);
this.ContextMenu!.OnMenuOpened += this.MenuOpened;
}
public void Dispose() {
this.ContextMenu.OnMenuOpened -= this.MenuOpened;
this.AddonLifecycle.UnregisterListener(AddonEvent.PostUpdate, "_PartyList", this.UpdateList);
this.Commands.Dispose();
this.Ui.Dispose();
@ -83,24 +95,114 @@ public class Plugin : IDalamudPlugin {
this.Interface.SavePluginConfig(this.Config);
}
private unsafe void MenuOpened(IMenuOpenedArgs args) {
var add = args.AddonName == "_PartyList";
if (!add) {
var ctx = AgentContext.Instance();
if (args.AgentPtr != (nint) ctx) {
return;
}
var targetId = ctx->TargetObjectId.ObjectId;
if (targetId == 0xE000_0000) {
return;
}
if (this.ClientState.LocalPlayer is { } player && player.GameObjectId == targetId) {
add = true;
} else {
var group = GroupManager.Instance()->GetGroup();
if (group != null && group->GetPartyMemberByEntityId(targetId) != null) {
add = true;
}
}
}
if (!add) {
return;
}
args.AddMenuItem(new MenuItem {
Name = "Clear parse results",
Prefix = SeIconChar.BoxedLetterP,
PrefixColor = 37,
IsEnabled = this.Client.Data?.IsActive == false,
OnClicked = _ => {
this._reset = true;
this._manuallyReset = true;
},
});
}
private unsafe void UpdateList(AddonEvent type, AddonArgs args) {
var ranLast = this._ranLastTick;
this._ranLastTick = false;
var list = (AddonPartyList*) AtkStage.Instance()->RaptureAtkUnitManager->GetAddonByName("_PartyList");
if (!this.UpdateListInner(list) && ranLast) {
if (list == null) {
return;
}
var shouldUpdate = false;
var wasActive = this._wasActive;
var becameInactive = false;
if (this.Client.Data is { } data) {
if (wasActive && !data.IsActive) {
becameInactive = true;
}
this._wasActive = data.IsActive;
}
if (this.Client.Data is { IsActive: true }) {
shouldUpdate = true;
this._manuallyReset = false;
} else if (becameInactive) {
if (this.Config.ClearResultsOnInactive) {
this.DelayWatch.Restart();
}
}
if (this.Config.ClearResultsOnInactive && this.DelayWatch.IsRunning && this.DelayWatch.Elapsed >= TimeSpan.FromSeconds(this.Config.ClearDelaySeconds)) {
this.DelayWatch.Reset();
this._reset = true;
}
if (!this._reset && !this._manuallyReset) {
// only do these checks if we shouldn't reset and if we're waiting for active data
// keep running if we're in the delay period
if (this.DelayWatch.IsRunning) {
shouldUpdate = true;
}
// keep running if the user wants to manually clear results
if (!this.Config.ClearResultsOnInactive) {
shouldUpdate = true;
}
}
if (this._reset) {
this.DelayWatch.Reset();
this._reset = false;
this._manuallyReset = true;
this.ResetMembers(list);
}
if (shouldUpdate && this.UpdateListInner(list) && ranLast) {
this.ResetMembers(list);
}
}
/// <summary>
/// Update the party list.
/// </summary>
/// <returns>true if the list should be reset immediately</returns>
private unsafe bool UpdateListInner(AddonPartyList* list) {
if (this.Client.Data is not { } data) {
return false;
}
if (!data.IsActive) {
return false;
}
if (this.ClientState.LocalPlayer is not { } player) {
return false;
}
@ -109,7 +211,7 @@ public class Plugin : IDalamudPlugin {
var playerName = player.Name.TextValue;
if (list->HoveredIndex >= 0 || list->TargetedIndex >= 0) {
return false;
return true;
}
var names = new List<(string, int)>();
@ -122,7 +224,7 @@ public class Plugin : IDalamudPlugin {
// controller soft target not handled by hoveredindex above
if (chara->GetSoftTargetId() == member.EntityId) {
return false;
return true;
}
var name = MemoryHelper.ReadStringNullTerminated((nint) member.Name);
@ -131,8 +233,8 @@ public class Plugin : IDalamudPlugin {
this._ranLastTick = true;
if (this.Watch.Elapsed.TotalMilliseconds > this.Config.AlternateSeconds * 1_000) {
this.Watch.Restart();
if (this.AlternateWatch.Elapsed.TotalMilliseconds > this.Config.AlternateSeconds * 1_000) {
this.AlternateWatch.Restart();
this._showDps ^= true;
}
@ -150,7 +252,7 @@ public class Plugin : IDalamudPlugin {
this.UpdateMember(list->PartyMembers[i], member.Object, data.Encounter, combatant);
}
return true;
return false;
}
private unsafe void ResetMembers(AddonPartyList* list) {

View File

@ -75,7 +75,7 @@ public class PluginUi : IDisposable {
this.Plugin.Config.TextColour = ConvertRgba(textColour);
}
if (ImGui.TreeNodeEx("Advanced colour options")) {
if (ImGui.TreeNodeEx("Advanced colour options##text")) {
using var treePop = new OnDispose(ImGui.TreePop);
anyChanged |= ImGui.SliderInt("Add red", ref this.Plugin.Config.TextAddRed, 0, 255);
@ -86,6 +86,11 @@ public class PluginUi : IDisposable {
anyChanged |= ImGui.SliderInt("Multiply blue", ref this.Plugin.Config.TextMulBlue, 0, 100);
}
anyChanged |= ImGui.Checkbox("Clear results after encounter ends", ref this.Plugin.Config.ClearResultsOnInactive);
using (ImGuiHelper.DisabledUnless(this.Plugin.Config.ClearResultsOnInactive)) {
anyChanged |= ImGui.SliderFloat("Seconds to delay before clearing", ref this.Plugin.Config.ClearDelaySeconds, 0, 300);
}
if (anyChanged) {
this.Plugin.SaveConfig();
}