feat: add configuration and modes
This commit is contained in:
parent
09266c4e5f
commit
05e2d87142
21
Commands.cs
Normal file
21
Commands.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using Dalamud.Game.Command;
|
||||||
|
|
||||||
|
namespace PartyDamage;
|
||||||
|
|
||||||
|
public class Commands : IDisposable {
|
||||||
|
private Plugin Plugin { get; }
|
||||||
|
|
||||||
|
public Commands(Plugin plugin) {
|
||||||
|
this.Plugin = plugin;
|
||||||
|
|
||||||
|
this.Plugin.CommandManager.AddHandler("/partydamage", new CommandInfo(this.OnCommand));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
this.Plugin.CommandManager.RemoveHandler("/partydamage");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCommand(string command, string args) {
|
||||||
|
this.Plugin.Ui.Visible ^= true;
|
||||||
|
}
|
||||||
|
}
|
20
Configuration.cs
Normal file
20
Configuration.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using Dalamud.Configuration;
|
||||||
|
|
||||||
|
namespace PartyDamage;
|
||||||
|
|
||||||
|
public class Configuration : IPluginConfiguration {
|
||||||
|
public int Version { get; set; } = 1;
|
||||||
|
|
||||||
|
public bool UseDpsBar = true;
|
||||||
|
public float BarAlpha = 0.5f;
|
||||||
|
public MeterMode Mode = MeterMode.Mana;
|
||||||
|
public bool Alternate = true;
|
||||||
|
public bool ManaModeAlternateOnlyManaUsers = true;
|
||||||
|
public float AlternateSeconds = 3.0f;
|
||||||
|
public uint DpsColour = 0xEDFFEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MeterMode {
|
||||||
|
Name,
|
||||||
|
Mana,
|
||||||
|
}
|
18
ImGuiHelper.cs
Normal file
18
ImGuiHelper.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using ImGuiNET;
|
||||||
|
|
||||||
|
namespace PartyDamage;
|
||||||
|
|
||||||
|
public static class ImGuiHelper {
|
||||||
|
public static OnDispose? DisabledIf(bool disabled) {
|
||||||
|
if (disabled) {
|
||||||
|
ImGui.BeginDisabled();
|
||||||
|
return new OnDispose(ImGui.EndDisabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OnDispose? DisabledUnless(bool unless) {
|
||||||
|
return DisabledIf(!unless);
|
||||||
|
}
|
||||||
|
}
|
19
OnDispose.cs
Normal file
19
OnDispose.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
namespace PartyDamage;
|
||||||
|
|
||||||
|
public class OnDispose : IDisposable {
|
||||||
|
private readonly Action _action;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
public OnDispose(Action action) {
|
||||||
|
this._action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
if (this._disposed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._disposed = true;
|
||||||
|
this._action();
|
||||||
|
}
|
||||||
|
}
|
159
Plugin.cs
159
Plugin.cs
@ -31,23 +31,56 @@ public class Plugin : IDalamudPlugin {
|
|||||||
private IPartyList PartyList { get; init; }
|
private IPartyList PartyList { get; init; }
|
||||||
|
|
||||||
[PluginService]
|
[PluginService]
|
||||||
private IDalamudPluginInterface Interface { get; init; }
|
internal IDalamudPluginInterface Interface { get; init; }
|
||||||
|
|
||||||
|
[PluginService]
|
||||||
|
internal ICommandManager CommandManager { get; init; }
|
||||||
|
|
||||||
|
internal Configuration Config { get; }
|
||||||
private Client Client { get; }
|
private Client Client { get; }
|
||||||
|
internal PluginUi Ui { get; }
|
||||||
|
private Commands Commands { get; }
|
||||||
|
|
||||||
private Stopwatch Watch { get; } = Stopwatch.StartNew();
|
private Stopwatch Watch { get; } = Stopwatch.StartNew();
|
||||||
private bool _ranLastTick;
|
private bool _ranLastTick;
|
||||||
|
|
||||||
|
private readonly byte[] ManaUsers = [
|
||||||
|
6, // cnj
|
||||||
|
7, // thm
|
||||||
|
19, // pld
|
||||||
|
24, // whm
|
||||||
|
25, // blm
|
||||||
|
26, // acn
|
||||||
|
27, // smn
|
||||||
|
28, // sch
|
||||||
|
32, // drk
|
||||||
|
33, // ast
|
||||||
|
35, // rdm
|
||||||
|
36, // blu
|
||||||
|
40, // sge
|
||||||
|
42, // pct
|
||||||
|
];
|
||||||
|
|
||||||
public Plugin() {
|
public Plugin() {
|
||||||
|
this.Config = this.Interface!.GetPluginConfig() as Configuration ?? new Configuration();
|
||||||
this.Client = new Client();
|
this.Client = new Client();
|
||||||
|
this.Ui = new PluginUi(this);
|
||||||
|
this.Commands = new Commands(this);
|
||||||
|
|
||||||
this.AddonLifecycle!.RegisterListener(AddonEvent.PostUpdate, "_PartyList", this.UpdateList);
|
this.AddonLifecycle!.RegisterListener(AddonEvent.PostUpdate, "_PartyList", this.UpdateList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
this.AddonLifecycle.UnregisterListener(AddonEvent.PostUpdate, "_PartyList", this.UpdateList);
|
this.AddonLifecycle.UnregisterListener(AddonEvent.PostUpdate, "_PartyList", this.UpdateList);
|
||||||
|
this.Commands.Dispose();
|
||||||
|
this.Ui.Dispose();
|
||||||
this.Client.Dispose();
|
this.Client.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void SaveConfig() {
|
||||||
|
this.Interface.SavePluginConfig(this.Config);
|
||||||
|
}
|
||||||
|
|
||||||
private unsafe void UpdateList(AddonEvent type, AddonArgs args) {
|
private unsafe void UpdateList(AddonEvent type, AddonArgs args) {
|
||||||
var ranLast = this._ranLastTick;
|
var ranLast = this._ranLastTick;
|
||||||
this._ranLastTick = false;
|
this._ranLastTick = false;
|
||||||
@ -140,6 +173,11 @@ public class Plugin : IDalamudPlugin {
|
|||||||
var manaString = member.Object->Mana.ToString(CultureInfo.InvariantCulture);
|
var manaString = member.Object->Mana.ToString(CultureInfo.InvariantCulture);
|
||||||
left->SetText(manaString[..^2]);
|
left->SetText(manaString[..^2]);
|
||||||
right->SetText(manaString[^2..]);
|
right->SetText(manaString[^2..]);
|
||||||
|
|
||||||
|
unit.Name->SetText(member.Object->Name);
|
||||||
|
unit.Name->TextColor = new ByteColor {
|
||||||
|
RGBA = 0xFFFFFFFF,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,46 +187,103 @@ public class Plugin : IDalamudPlugin {
|
|||||||
Encounter encounter,
|
Encounter encounter,
|
||||||
Combatant combatant
|
Combatant combatant
|
||||||
) {
|
) {
|
||||||
member.TargetGlow->ToggleVisibility(true);
|
if (this.Config.UseDpsBar) {
|
||||||
member.TargetGlow->SetAlpha(128);
|
member.TargetGlow->ToggleVisibility(true);
|
||||||
member.TargetGlow->SetScaleX(
|
member.TargetGlow->SetAlpha((byte) Math.Round(this.Config.BarAlpha * 255));
|
||||||
encounter.EncDps == 0
|
member.TargetGlow->SetScaleX(
|
||||||
? 0
|
encounter.EncDps == 0
|
||||||
: combatant.EncDps / encounter.EncDps
|
? 0
|
||||||
);
|
: combatant.EncDps / encounter.EncDps
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
var left = (AtkTextNode*) member.MPGaugeBar->GetTextNodeById(2);
|
if (this.Config.Mode == MeterMode.Mana) {
|
||||||
var right = (AtkTextNode*) member.MPGaugeBar->GetTextNodeById(3);
|
var left = (AtkTextNode*) member.MPGaugeBar->GetTextNodeById(2);
|
||||||
|
var right = (AtkTextNode*) member.MPGaugeBar->GetTextNodeById(3);
|
||||||
|
|
||||||
|
if (this.Config.Alternate) {
|
||||||
|
var isCaster = Array.IndexOf(this.ManaUsers, chara->ClassJob) != -1;
|
||||||
|
if (!this.Config.ManaModeAlternateOnlyManaUsers || isCaster) {
|
||||||
|
var elapsedSeconds = this.Watch.Elapsed.Seconds;
|
||||||
|
if (elapsedSeconds >= this.Config.AlternateSeconds * 2) {
|
||||||
|
this.Watch.Restart();
|
||||||
|
} else if (elapsedSeconds >= this.Config.AlternateSeconds) {
|
||||||
|
left->TextColor = new ByteColor {
|
||||||
|
RGBA = 0xFFFFFFFF,
|
||||||
|
};
|
||||||
|
right->TextColor = left->TextColor;
|
||||||
|
|
||||||
|
var manaString = chara->Mana.ToString(CultureInfo.InvariantCulture);
|
||||||
|
left->SetText(manaString[..^2]);
|
||||||
|
right->SetText(manaString[^2..]);
|
||||||
|
|
||||||
|
if (this.Watch.Elapsed.Seconds >= this.Config.AlternateSeconds * 2) {
|
||||||
|
this.Watch.Restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.Watch.Elapsed.Seconds % 6 < 3) {
|
|
||||||
left->TextColor = new ByteColor {
|
left->TextColor = new ByteColor {
|
||||||
RGBA = 0xFFFFFFFF,
|
RGBA = this.Config.DpsColour,
|
||||||
};
|
};
|
||||||
right->TextColor = left->TextColor;
|
right->TextColor = left->TextColor;
|
||||||
|
|
||||||
var manaString = chara->Mana.ToString(CultureInfo.InvariantCulture);
|
if (combatant.EncDps == 0 || float.IsInfinity(combatant.EncDps) || float.IsNaN(combatant.EncDps)) {
|
||||||
left->SetText(manaString[..^2]);
|
left->SetText("0.");
|
||||||
right->SetText(manaString[^2..]);
|
right->SetText("00");
|
||||||
|
} else if (combatant.EncDps < 1_000) {
|
||||||
|
var dps = Math.Round(combatant.EncDps * 100).ToString(CultureInfo.InvariantCulture);
|
||||||
|
left->SetText($"{dps[..^2]}.");
|
||||||
|
right->SetText(dps[^2..]);
|
||||||
|
} else if (combatant.EncDps < 1_000_000) {
|
||||||
|
var dps = Math.Round(combatant.EncDps / 100).ToString(CultureInfo.InvariantCulture);
|
||||||
|
left->SetText($"{dps[..^1]}.");
|
||||||
|
right->SetText($"{dps[^1..]}K");
|
||||||
|
} else if (combatant.EncDps < 1_000_000_000) {
|
||||||
|
var dps = Math.Round(combatant.EncDps / 100_000).ToString(CultureInfo.InvariantCulture);
|
||||||
|
left->SetText($"{dps[..^1]}.");
|
||||||
|
right->SetText($"{dps[^1..]}M");
|
||||||
|
} else {
|
||||||
|
var dps = Math.Round(combatant.EncDps / 100_000_000).ToString(CultureInfo.InvariantCulture);
|
||||||
|
left->SetText($"{dps[..^1]}.");
|
||||||
|
right->SetText($"{dps[^1..]}B");
|
||||||
|
}
|
||||||
|
} else if (this.Config.Mode == MeterMode.Name) {
|
||||||
|
var dpsText = combatant.EncDps switch {
|
||||||
|
float.NaN => "0",
|
||||||
|
float.PositiveInfinity => "0",
|
||||||
|
float.NegativeInfinity => "0",
|
||||||
|
< 1_000 => $"{combatant.EncDps:N2}",
|
||||||
|
< 1_000_000 => $"{combatant.EncDps / 1_000:N2}K",
|
||||||
|
< 1_000_000_000 => $"{combatant.EncDps / 1_000_000:N2}M",
|
||||||
|
_ => $"{combatant.EncDps / 1_000_000_000:N2}B",
|
||||||
|
};
|
||||||
|
|
||||||
return;
|
if (this.Config.Alternate) {
|
||||||
}
|
var elapsedSeconds = this.Watch.Elapsed.Seconds;
|
||||||
|
if (elapsedSeconds >= this.Config.AlternateSeconds * 2) {
|
||||||
|
this.Watch.Restart();
|
||||||
|
} else if (elapsedSeconds >= this.Config.AlternateSeconds) {
|
||||||
|
member.Name->TextColor = new ByteColor {
|
||||||
|
RGBA = 0xFFFFFFFF,
|
||||||
|
};
|
||||||
|
member.Name->SetText(chara->Name);
|
||||||
|
|
||||||
left->TextColor = new ByteColor {
|
if (this.Watch.Elapsed.Seconds >= this.Config.AlternateSeconds * 2) {
|
||||||
RGBA = 0xedffecff,
|
this.Watch.Restart();
|
||||||
};
|
}
|
||||||
right->TextColor = left->TextColor;
|
|
||||||
|
|
||||||
if (combatant.EncDps == 0 || float.IsInfinity(combatant.EncDps) || float.IsNaN(combatant.EncDps)) {
|
return;
|
||||||
left->SetText("0.");
|
}
|
||||||
right->SetText("00");
|
}
|
||||||
} else if (combatant.EncDps < 1_000) {
|
|
||||||
var dps = Math.Round(combatant.EncDps * 100).ToString(CultureInfo.InvariantCulture);
|
member.Name->SetText(dpsText);
|
||||||
left->SetText($"{dps[..^2]}.");
|
member.Name->TextColor = new ByteColor {
|
||||||
right->SetText(dps[^2..]);
|
RGBA = this.Config.DpsColour,
|
||||||
} else if (combatant.EncDps < 1_000_000) {
|
};
|
||||||
var dps = Math.Round(combatant.EncDps / 100).ToString(CultureInfo.InvariantCulture);
|
|
||||||
left->SetText($"{dps[..^1]}.");
|
|
||||||
right->SetText($"{dps[^1..]}K");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
76
PluginUi.cs
Normal file
76
PluginUi.cs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using ImGuiNET;
|
||||||
|
|
||||||
|
namespace PartyDamage;
|
||||||
|
|
||||||
|
public class PluginUi : IDisposable {
|
||||||
|
private Plugin Plugin { get; }
|
||||||
|
internal bool Visible;
|
||||||
|
|
||||||
|
public PluginUi(Plugin plugin) {
|
||||||
|
this.Plugin = plugin;
|
||||||
|
|
||||||
|
this.Plugin.Interface.UiBuilder.Draw += this.Draw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
this.Plugin.Interface.UiBuilder.Draw -= this.Draw;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Draw() {
|
||||||
|
var anyChanged = false;
|
||||||
|
|
||||||
|
ImGui.TextUnformatted("Meter mode");
|
||||||
|
if (ImGui.BeginCombo("##mode", Enum.GetName(this.Plugin.Config.Mode))) {
|
||||||
|
using var endCombo = new OnDispose(ImGui.EndCombo);
|
||||||
|
|
||||||
|
foreach (var mode in Enum.GetValues<MeterMode>()) {
|
||||||
|
if (ImGui.Selectable(Enum.GetName(mode), mode == this.Plugin.Config.Mode)) {
|
||||||
|
anyChanged = true;
|
||||||
|
this.Plugin.Config.Mode = mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
anyChanged |= ImGui.Checkbox("Use DPS bars behind party list", ref this.Plugin.Config.UseDpsBar);
|
||||||
|
var barAlpha = this.Plugin.Config.BarAlpha * 100;
|
||||||
|
if (ImGui.SliderFloat("Bar opacity", ref barAlpha, 0, 100, "%.2f%%")) {
|
||||||
|
this.Plugin.Config.BarAlpha = Math.Clamp(barAlpha / 100, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
anyChanged |= ImGui.Checkbox("Alternate between values", ref this.Plugin.Config.Alternate);
|
||||||
|
using (ImGuiHelper.DisabledUnless(this.Plugin.Config.Alternate)) {
|
||||||
|
anyChanged |= ImGui.SliderFloat("Seconds before alternating", ref this.Plugin.Config.AlternateSeconds, 0.5f, 60f);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (ImGuiHelper.DisabledUnless(this.Plugin.Config.Alternate && this.Plugin.Config.Mode == MeterMode.Name)) {
|
||||||
|
anyChanged |= ImGui.Checkbox("Only alternate on jobs that use mana", ref this.Plugin.Config.ManaModeAlternateOnlyManaUsers);
|
||||||
|
}
|
||||||
|
|
||||||
|
var textColour = ConvertRgba(this.Plugin.Config.DpsColour);
|
||||||
|
if (ImGui.ColorPicker3("DPS text colour", ref textColour)) {
|
||||||
|
anyChanged = true;
|
||||||
|
this.Plugin.Config.DpsColour = ConvertRgba(textColour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector3 ConvertRgba(uint colour) {
|
||||||
|
var red = colour & 0xFF;
|
||||||
|
var green = (colour >> 8) & 0xFF;
|
||||||
|
var blue = (colour >> 16) & 0xFF;
|
||||||
|
// var alpha = colour >> 24;
|
||||||
|
|
||||||
|
return new Vector3(red / 255f, green / 255f, blue / 255f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static uint ConvertRgba(Vector3 parts) {
|
||||||
|
var red = (uint) Math.Round(parts.X * 255);
|
||||||
|
var green = (uint) Math.Round(parts.Y * 255);
|
||||||
|
var blue = (uint) Math.Round(parts.Z * 255);
|
||||||
|
|
||||||
|
return (red << 24)
|
||||||
|
| (green << 16)
|
||||||
|
| (blue << 8)
|
||||||
|
| 0xFF;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user