PartyDamage/PluginUi.cs

328 lines
15 KiB
C#

using System.Numerics;
using System.Text;
using Dalamud.Interface.Utility;
using FFXIVClientStructs.FFXIV.Client.UI;
using ImGuiNET;
using Lumina.Excel.GeneratedSheets;
namespace PartyDamage;
public class PluginUi : IDisposable {
private Plugin Plugin { get; }
internal bool Visible;
private List<ClassJob> Jobs { get; }
public PluginUi(Plugin plugin) {
this.Plugin = plugin;
this.Jobs = [.. this.Plugin.DataManager.GetExcelSheet<ClassJob>()!
.Where(cj => cj.RowId != 0 && !string.IsNullOrWhiteSpace(cj.Name))
.OrderBy(cj => cj.Role)
.ThenBy(cj => cj.RowId)];
this.Plugin.Interface.UiBuilder.Draw += this.Draw;
}
public void Dispose() {
this.Plugin.Interface.UiBuilder.Draw -= this.Draw;
}
private void Draw() {
if (!this.Visible) {
return;
}
ImGui.SetNextWindowSize(new Vector2(700, 300), ImGuiCond.FirstUseEver);
using var end = new OnDispose(ImGui.End);
if (!ImGui.Begin("Party Damage", ref this.Visible)) {
return;
}
var anyChanged = false;
if (!ImGui.BeginTabBar("##main-tab-bar")) {
return;
}
using var endTabBar = new OnDispose(ImGui.EndTabBar);
if (ImGui.BeginTabItem("Meter")) {
using var endTabItem = new OnDispose(ImGui.EndTabItem);
// 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);
using (ImGuiHelper.DisabledUnless(this.Plugin.Config.UseDpsBar)) {
if (ImGui.BeginCombo("Bar mode", Enum.GetName(this.Plugin.Config.DpsBarMode))) {
using var endCombo = new OnDispose(ImGui.EndCombo);
foreach (var mode in Enum.GetValues<DpsBarMode>()) {
if (ImGui.Selectable(Enum.GetName(mode), this.Plugin.Config.DpsBarMode == mode)) {
anyChanged = true;
this.Plugin.Config.DpsBarMode = mode;
}
}
}
var scalePreview = this.Plugin.Config.DpsBarScaleToMax
? "Max DPS"
: "Total DPS";
if (ImGui.BeginCombo("Bar scale", scalePreview)) {
using var endCombo = new OnDispose(ImGui.EndCombo);
if (ImGui.Selectable("Max DPS", this.Plugin.Config.DpsBarScaleToMax)) {
anyChanged = true;
this.Plugin.Config.DpsBarScaleToMax = true;
}
if (ImGui.Selectable("Total DPS", !this.Plugin.Config.DpsBarScaleToMax)) {
anyChanged = true;
this.Plugin.Config.DpsBarScaleToMax = false;
}
}
var barAlpha = this.Plugin.Config.BarAlpha * 100;
if (ImGui.SliderFloat("Bar opacity", ref barAlpha, 0, 100, "%.2f%%")) {
anyChanged = true;
this.Plugin.Config.BarAlpha = Math.Clamp(barAlpha / 100, 0, 1);
}
if (ImGui.TreeNodeEx("Advanced colour options")) {
using var treePop = new OnDispose(ImGui.TreePop);
anyChanged |= ImGui.SliderInt("Add red", ref this.Plugin.Config.BarAddRed, 0, 255);
anyChanged |= ImGui.SliderInt("Add green", ref this.Plugin.Config.BarAddGreen, 0, 255);
anyChanged |= ImGui.SliderInt("Add blue", ref this.Plugin.Config.BarAddBlue, 0, 255);
anyChanged |= ImGui.SliderInt("Multiply red", ref this.Plugin.Config.BarMulRed, 0, 100);
anyChanged |= ImGui.SliderInt("Multiply green", ref this.Plugin.Config.BarMulGreen, 0, 100);
anyChanged |= ImGui.SliderInt("Multiply blue", ref this.Plugin.Config.BarMulBlue, 0, 100);
}
}
ImGui.Spacing();
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.1f, 60f);
}
using (ImGuiHelper.DisabledUnless(this.Plugin.Config is { Alternate: true, Mode: MeterMode.Mana })) {
anyChanged |= ImGui.Checkbox("Only alternate when in combat", ref this.Plugin.Config.OnlyAlternateInCombat);
anyChanged |= ImGui.Checkbox("Alternate chocobo timer", ref this.Plugin.Config.AlternateChocobo);
if (ImGui.TreeNodeEx("Jobs to alternate")) {
using var treePop = new OnDispose(ImGui.TreePop);
if (ImGui.Button("All")) {
anyChanged = true;
this.Plugin.Config.AlternateJobs.Clear();
this.Plugin.Config.AlternateChocobo = true;
this.Plugin.Config.AlternateJobs.AddRange(this.Jobs.Select(cj => cj.RowId));
}
ImGui.SameLine();
if (ImGui.Button("None")) {
this.Plugin.Config.AlternateJobs.Clear();
this.Plugin.Config.AlternateChocobo = false;
anyChanged = true;
}
ImGui.SameLine();
if (ImGui.Button("Mana users")) {
this.Plugin.Config.AlternateJobs.Clear();
this.Plugin.Config.AlternateChocobo = false;
this.Plugin.Config.AlternateJobs.AddRange(this.Plugin.ManaUsers.Select(cj => (uint) cj));
anyChanged = true;
}
foreach (var job in this.Jobs) {
var alternate = this.Plugin.Config.AlternateJobs.Contains(job.RowId);
if (ImGui.Checkbox(job.Name, ref alternate)) {
anyChanged = true;
if (alternate && !this.Plugin.Config.AlternateJobs.Contains(job.RowId)) {
this.Plugin.Config.AlternateJobs.Add(job.RowId);
} else {
this.Plugin.Config.AlternateJobs.Remove(job.RowId);
}
}
}
}
}
ImGui.Spacing();
var textColour = ConvertRgba(this.Plugin.Config.TextColour);
if (ImGui.ColorEdit3("DPS text colour", ref textColour)) {
anyChanged = true;
this.Plugin.Config.TextColour = ConvertRgba(textColour);
}
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);
anyChanged |= ImGui.SliderInt("Add green", ref this.Plugin.Config.TextAddGreen, 0, 255);
anyChanged |= ImGui.SliderInt("Add blue", ref this.Plugin.Config.TextAddBlue, 0, 255);
anyChanged |= ImGui.SliderInt("Multiply red", ref this.Plugin.Config.TextMulRed, 0, 100);
anyChanged |= ImGui.SliderInt("Multiply green", ref this.Plugin.Config.TextMulGreen, 0, 100);
anyChanged |= ImGui.SliderInt("Multiply blue", ref this.Plugin.Config.TextMulBlue, 0, 100);
}
ImGui.Spacing();
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 (ImGui.BeginTabItem("Evaluations")) {
using var endTabItem = new OnDispose(ImGui.EndTabItem);
ImGui.PushTextWrapPos();
using var popTextWrapPos = new OnDispose(ImGui.PopTextWrapPos);
ImGui.TextUnformatted("These evaluations are based on your relative rank compared to other players playing the same role (tank, healer, melee, magical ranged, physical ranged). This means that you will always receive the highest evaluation if you are the only member of your role. These evaluations should not be taken too seriously.");
ImGui.Separator();
anyChanged |= ImGui.Checkbox("Show an NPC text bubble rating your performance after an encounter", ref this.Plugin.Config.UseEvaluatorNpc);
using (ImGuiHelper.DisabledUnless(this.Plugin.Config.UseEvaluatorNpc)) {
const string previewLabel = "Preview";
var previewButtonSize = ImGuiHelpers.GetButtonSize(previewLabel);
var comboSize = ImGui.GetContentRegionAvail().X
- ImGui.GetStyle().ItemSpacing.X
- previewButtonSize.X;
var current = Evaluator.Evaluators.FirstOrDefault(e => e.Id == this.Plugin.Config.EvaluatorId);
var preview = current == null
? this.Plugin.Config.EvaluatorId == Evaluator.RandomId
? "Random"
: "None"
: current.ConfigName ?? current.Name;
if (ImGuiHelper.BeginComboVertical("Evaluator", "evaluator", preview, comboSize)) {
using var endCombo = new OnDispose(ImGui.EndCombo);
if (ImGui.Selectable("None", this.Plugin.Config.EvaluatorId == Guid.Empty)) {
anyChanged = true;
this.Plugin.Config.EvaluatorId = Guid.Empty;
}
if (ImGui.Selectable("Random", this.Plugin.Config.EvaluatorId == Evaluator.RandomId)) {
anyChanged = true;
this.Plugin.Config.EvaluatorId = Evaluator.RandomId;
}
foreach (var evaluator in Evaluator.Evaluators) {
if (ImGui.Selectable(evaluator.ConfigName ?? evaluator.Name, this.Plugin.Config.EvaluatorId == evaluator.Id)) {
anyChanged = true;
this.Plugin.Config.EvaluatorId = evaluator.Id;
}
}
}
ImGui.SameLine();
if (ImGui.Button(previewLabel)) {
if (this.Plugin.GetEvaluator() is { } evaluator) {
var evaluation = Random.Shared.GetItems(Enum.GetValues<Evaluation>(), 1)[0];
var msg = evaluator.GetLineFor(evaluation, this.Plugin.Config.BlendEvaluations, Random.Shared.Next(1, 8));
if (msg != null) {
unsafe {
UIModule.Instance()->ShowBattleTalkImage(
Encoding.UTF8.GetBytes(evaluator.Name),
msg.EncodeWithNullTerminator(),
this.Plugin.Config.EvaluationLength,
evaluator.BattleTalkImage,
6
);
}
}
}
}
if (ImGui.TreeNodeEx("Evaluation thresholds")) {
using var treePop = new OnDispose(ImGui.TreePop);
ImGui.TextUnformatted("If your rank is equal to or above the thresholds defined below, you will get the ranking specified. For example, if best is set to 85% and good is set to 65% and you were 3/4 (75%), you would be evaluated as good.");
ImGui.Spacing();
foreach (var evaluation in Enum.GetValues<Evaluation>()) {
if (!this.Plugin.Config.EvaluationThresholds.TryGetValue(evaluation, out var threshold)) {
threshold = 0f;
}
threshold *= 100f;
if (ImGui.SliderFloat(Enum.GetName(evaluation), ref threshold, 0, 100, "%.2f%%")) {
anyChanged = true;
this.Plugin.Config.EvaluationThresholds[evaluation] = Math.Clamp(threshold / 100, 0, 1);
}
}
}
if (ImGui.TreeNodeEx("Random evaluator pool")) {
using var treePop = new OnDispose(ImGui.TreePop);
foreach (var evaluator in Evaluator.Evaluators) {
var enabled = this.Plugin.Config.EvaluatorsRandomEnabled.GetValueOrDefault(evaluator.Id, false);
if (ImGui.Checkbox(evaluator.ConfigName ?? evaluator.Name, ref enabled)) {
anyChanged = true;
this.Plugin.Config.EvaluatorsRandomEnabled[evaluator.Id] = enabled;
}
}
}
anyChanged |= ImGui.Checkbox("Mix in lines from the next and previous evaluation levels", ref this.Plugin.Config.BlendEvaluations);
anyChanged |= ImGui.SliderFloat("Seconds to display evaluation", ref this.Plugin.Config.EvaluationLength, 0.5f, 30);
anyChanged |= ImGui.SliderInt("Minimum players to show evaluation", ref this.Plugin.Config.EvaluationMinCombatants, 0, 24);
anyChanged |= ImGui.SliderInt("Minimum players on the same role to show evaluation", ref this.Plugin.Config.EvaluationMinSameRole, 0, 8);
}
}
if (anyChanged) {
this.Plugin.SaveConfig();
}
// ImGui.InputInt("image id", ref this._imageId);
// if (this.Plugin.TextureProvider.TryGetFromGameIcon(new GameIconLookup((uint) this._imageId), out var tex)) {
// if (tex.TryGetWrap(out var wrap, out _)) {
// ImGui.Image(wrap.ImGuiHandle, new Vector2(wrap.Width, wrap.Height));
// }
// }
}
// private int _imageId = 73000;
private static Vector3 ConvertRgba(uint colour) {
var red = colour >> 24;
var green = (colour >> 16) & 0xFF;
var blue = (colour >> 8) & 0xFF;
// var alpha = colour & 0xFF;
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;
}
}