From d3eb675e499702736c2ca6bf987487138b596b2a Mon Sep 17 00:00:00 2001 From: Anna Date: Sun, 28 Jul 2024 01:16:47 -0400 Subject: [PATCH] feat: start adding more evaluators --- Configuration.cs | 4 +- Evaluator.cs | 154 ++++++++++++++++++++++++++++++++++++++++------- ImGuiHelper.cs | 13 +++- Plugin.cs | 28 ++++----- PluginUi.cs | 35 ++++++++++- 5 files changed, 192 insertions(+), 42 deletions(-) diff --git a/Configuration.cs b/Configuration.cs index 7a08900..32cf810 100644 --- a/Configuration.cs +++ b/Configuration.cs @@ -39,8 +39,10 @@ public class Configuration : IPluginConfiguration { public int EvaluationMinSameRole; public Dictionary EvaluatorsRandomEnabled = Evaluator.Evaluators.ToDictionary( e => e.Id, - _ => true + e => e.Default ); + public float EvaluationLength = 5f; + public bool BlendEvaluations; } public enum MeterMode { diff --git a/Evaluator.cs b/Evaluator.cs index e544329..8d851f6 100644 --- a/Evaluator.cs +++ b/Evaluator.cs @@ -7,41 +7,68 @@ namespace PartyDamage; public class Evaluator { public required Guid Id { get; init; } public required string Name { get; init; } + public string? ConfigName { get; init; } public required uint BattleTalkImage { get; init; } + public required bool Default { get; init; } public required Dictionary Lines { get; init; } public bool IsMammet { get; init; } - public SeString? GetLineFor(Evaluation evaluation) { - if (!this.Lines.TryGetValue(evaluation, out var lines)) { + public SeString? GetLineFor(Evaluation evaluation, bool blend, int rank) { + var lines = new List(); + if (blend) { + if (evaluation.Next() is { } next && this.Lines.TryGetValue(next, out var nextLines)) { + lines.AddRange(nextLines); + } + + if (evaluation.Previous() is { } prev && this.Lines.TryGetValue(prev, out var prevLines)) { + lines.AddRange(prevLines); + } + } + + if (!this.Lines.TryGetValue(evaluation, out var currentLines)) { return null; } - var line = Random.Shared.GetItems(lines, 1)[0]; - if (!this.IsMammet) { - return line; - } + lines.AddRange(currentLines); - foreach (var payload in line.Payloads) { + var template = Random.Shared.GetItems(lines.ToArray(), 1)[0]; + var line = new SeStringBuilder(); + + foreach (var payload in template.Payloads) { if (payload is not TextPayload text) { + line.Add(payload); continue; } - var newText = new StringBuilder(); - var upper = true; - foreach (var ch in text.Text!) { - if (!char.IsLetter(ch)) { - newText.Append(ch); - continue; - } + var newText = this.IsMammet + ? Mammetise(text.Text!) + : text.Text!; + newText = string.Format( + newText, + rank + ); - newText.Append(upper ? char.ToUpperInvariant(ch) : char.ToLowerInvariant(ch)); - upper = !upper; - } - text.Text = newText.ToString(); + line.AddText(newText.ToString()); } - return line; + return line.Build(); + } + + private static string Mammetise(string input) { + var newText = new StringBuilder(); + var upper = true; + foreach (var ch in input) { + if (!char.IsLetter(ch)) { + newText.Append(ch); + continue; + } + + newText.Append(upper ? char.ToUpperInvariant(ch) : char.ToLowerInvariant(ch)); + upper = !upper; + } + + return newText.ToString(); } public static readonly Guid RandomId = new("00000000-0000-0000-0000-000000000001"); @@ -51,6 +78,7 @@ public class Evaluator { Id = new Guid("ebbccc44-13b5-4843-a635-3b693fe47840"), Name = "Parser Mammet", BattleTalkImage = 73160, + Default = true, Lines = new Dictionary { [Evaluation.Best] = [ "Parse result: greatly exceeds expectations!", @@ -85,10 +113,35 @@ public class Evaluator { }, IsMammet = true, }, + new Evaluator { + Id = new("3e833290-bc1f-4318-9461-391dcc66c739"), + Name = "Ranking Mammet", + ConfigName = "Ranking Mammet (displays rank explicitly)", + BattleTalkImage = 73160, + Default = false, + Lines = new Dictionary { + [Evaluation.Best] = [ + "You ranked #{0}.", + ], + [Evaluation.Good] = [ + "You ranked #{0}.", + ], + [Evaluation.Fair] = [ + "You ranked #{0}.", + ], + [Evaluation.Poor] = [ + "You ranked #{0}.", + ], + [Evaluation.Awful] = [ + "You ranked #{0}.", + ], + } + }, new Evaluator { Id = new Guid("5053c386-192a-416f-b025-223af8d592bf"), Name = "G'raha Tia", BattleTalkImage = 73012, + Default = true, Lines = new Dictionary { [Evaluation.Best] = [ "Impressive! No surprise coming from someone as skilled as you.", @@ -116,11 +169,12 @@ public class Evaluator { Id = new Guid("1dd9addb-f0d3-4a8d-b087-62ae10cb5423"), Name = "Wuk Lamat", BattleTalkImage = 73265, + Default = true, Lines = new Dictionary { [Evaluation.Best] = [ new SeStringBuilder() - .AddText("Incredible! You have ") - .AddItalics("got") + .AddText("Incredible! You ") + .AddItalics("have") .AddText(" to show me how to do that sometime!") .Build(), "Amazing! You truly are the best there is!", @@ -135,7 +189,7 @@ public class Evaluator { ], [Evaluation.Poor] = [ new SeStringBuilder() - .AddText("Whoa! Is Eorzea's champion ") + .AddText("Hey... Is Eorzea's champion ") .AddItalics("slacking") .AddText("? Huh. What will everyone say when I tell them?") .Build(), @@ -154,7 +208,43 @@ public class Evaluator { "It's okay. I won't tell anyone about that.", ], }, - } + }, + new Evaluator { + Id = new("3f862fca-cb18-4f48-b067-71b116070fa8"), + Name = "Estinien", + BattleTalkImage = 73007, + Default = true, + Lines = new Dictionary { + [Evaluation.Best] = [ + "Ha! Well fought, friend! If only I had been there to join you. It looked like fun.", + "Now there's a fight that will make a good story. Expertly fought.", + ], + } + }, + new Evaluator { + Id = new("37ac5883-c008-4dc2-8c6b-a605a4698c04"), + Name = "Thancred", + ConfigName = "Thancred (\"This is Thancred\" meme)", + BattleTalkImage = 73013, + Default = false, + Lines = new Dictionary { + [Evaluation.Best] = [ + "This is Thancred.", + ], + [Evaluation.Good] = [ + "This is Thancred.", + ], + [Evaluation.Fair] = [ + "This is Thancred.", + ], + [Evaluation.Poor] = [ + "This is Thancred.", + ], + [Evaluation.Awful] = [ + "This is Thancred.", + ], + }, + }, ]; } @@ -166,6 +256,24 @@ public enum Evaluation { Awful, } +public static class EvaluationExt { + public static Evaluation? Next(this Evaluation evaluation) { + if (evaluation == 0) { + return null; + } + + return evaluation - 1; + } + + public static Evaluation? Previous(this Evaluation evaluation) { + if (evaluation == Evaluation.Awful) { + return null; + } + + return evaluation + 1; + } +} + // 001 Venat // 002 Zenos // 003 Evil? Zenos diff --git a/ImGuiHelper.cs b/ImGuiHelper.cs index b911473..7a6606b 100644 --- a/ImGuiHelper.cs +++ b/ImGuiHelper.cs @@ -15,4 +15,15 @@ public static class ImGuiHelper { public static OnDispose? DisabledUnless(bool unless) { return DisabledIf(!unless); } -} \ No newline at end of file + + public static bool BeginComboVertical( + string label, + string id, + string preview, + float width = -1 + ) { + ImGui.TextUnformatted(label); + ImGui.SetNextItemWidth(width); + return ImGui.BeginCombo($"##{id}", preview); + } +} diff --git a/Plugin.cs b/Plugin.cs index c9da64b..5c2f69a 100644 --- a/Plugin.cs +++ b/Plugin.cs @@ -212,7 +212,7 @@ public class Plugin : IDalamudPlugin { return; } - var evaluator = GetEvaluator(); + var evaluator = this.GetEvaluator(); if (evaluator == null) { return; } @@ -247,13 +247,13 @@ public class Plugin : IDalamudPlugin { continue; } - var msg = evaluator.GetLineFor(threshold.Key); + var msg = evaluator.GetLineFor(threshold.Key, this.Config.BlendEvaluations, youIndex + 1); if (msg != null) { var bytes = msg.EncodeWithNullTerminator(); UIModule.Instance()->ShowBattleTalkImage( Encoding.UTF8.GetBytes(evaluator.Name), bytes, - 5f, + this.Config.EvaluationLength, evaluator.BattleTalkImage, 6 ); @@ -263,19 +263,19 @@ public class Plugin : IDalamudPlugin { } return; + } - Evaluator? GetEvaluator() { - if (this.Config.EvaluatorId != Evaluator.RandomId) { - return Evaluator.Evaluators.FirstOrDefault(e => e.Id == this.Config.EvaluatorId); - } - - var pool = Evaluator.Evaluators - .Where(e => this.Config.EvaluatorsRandomEnabled.GetValueOrDefault(e.Id)) - .ToArray(); - return pool.Length == 0 - ? null - : Random.Shared.GetItems(pool, 1).GetIndexOrDefault(0); + internal Evaluator? GetEvaluator() { + if (this.Config.EvaluatorId != Evaluator.RandomId) { + return Evaluator.Evaluators.FirstOrDefault(e => e.Id == this.Config.EvaluatorId); } + + var pool = Evaluator.Evaluators + .Where(e => this.Config.EvaluatorsRandomEnabled.GetValueOrDefault(e.Id)) + .ToArray(); + return pool.Length == 0 + ? null + : Random.Shared.GetItems(pool, 1).GetIndexOrDefault(0); } /// diff --git a/PluginUi.cs b/PluginUi.cs index f53ad1a..147383a 100644 --- a/PluginUi.cs +++ b/PluginUi.cs @@ -1,4 +1,7 @@ using System.Numerics; +using System.Text; +using Dalamud.Interface.Utility; +using FFXIVClientStructs.FFXIV.Client.UI; using ImGuiNET; namespace PartyDamage; @@ -118,13 +121,19 @@ public class PluginUi : IDisposable { 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.Name; - if (ImGui.BeginCombo("Evaluator", preview)) { + if (ImGuiHelper.BeginComboVertical("Evaluator", "evaluator", preview, comboSize)) { using var endCombo = new OnDispose(ImGui.EndCombo); if (ImGui.Selectable("None", this.Plugin.Config.EvaluatorId == Guid.Empty)) { @@ -138,13 +147,31 @@ public class PluginUi : IDisposable { } foreach (var evaluator in Evaluator.Evaluators) { - if (ImGui.Selectable(evaluator.Name, this.Plugin.Config.EvaluatorId == evaluator.Id)) { + 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(), 1)[0]; + var msg = evaluator.GetLineFor(evaluation, this.Plugin.Config.BlendEvaluations, Random.Shared.Next(1, 8)); + if (msg != null) { + unsafe { + UIModule.Instance()->ShowBattleTalk( + Encoding.UTF8.GetBytes(evaluator.Name), + msg.EncodeWithNullTerminator(), + this.Plugin.Config.EvaluationLength, + 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."); @@ -168,13 +195,15 @@ public class PluginUi : IDisposable { foreach (var evaluator in Evaluator.Evaluators) { var enabled = this.Plugin.Config.EvaluatorsRandomEnabled.GetValueOrDefault(evaluator.Id, false); - if (ImGui.Checkbox(evaluator.Name, ref enabled)) { + 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); }