diff --git a/HighRollerClassic/DataStructures/Misc.cs b/HighRollerClassic/DataStructures/Misc.cs new file mode 100644 index 0000000..2821fcb --- /dev/null +++ b/HighRollerClassic/DataStructures/Misc.cs @@ -0,0 +1,16 @@ +namespace HighRollerClassic.DataStructures; + +public class Misc +{ + /// + /// Appends message if error par is true + /// + /// it will write the message if it's true + /// the message we wish to write + /// reference to the message + public static void AppendMessage(bool error, string errorMessage, ref string? message) + { + if (!error) return; + message = message == null ? errorMessage : $"\n{errorMessage}"; + } +} diff --git a/HighRollerClassic/DataStructures/Settings.cs b/HighRollerClassic/DataStructures/Settings.cs index 30d93c0..9aa051d 100644 --- a/HighRollerClassic/DataStructures/Settings.cs +++ b/HighRollerClassic/DataStructures/Settings.cs @@ -2,30 +2,66 @@ using System.Collections.Generic; namespace HighRollerClassic.DataStructures; -public struct Settings() +public class Settings { - /// - /// Contains data about each multiplier, roll, etc. - /// - public readonly List rolls = new(); - - /// - /// Contains messages such as announcements etc. - /// - public readonly List macros = new(); - - /// - /// Maximum bet that will be allowed to set - /// - public uint? maxBet = null; - - /// - /// How much the bet will change when user adjusts their bet via +/- keys - /// - public uint? step = null; - /// /// Whether developer options should be visible in the settings /// public bool devOptions = false; + + /// + /// Maximum bet that will be allowed to set + /// + public uint? MaxBet { get; set; } = null; + + /// + /// How much the bet will change when user adjusts their bet via +/- keys + /// + public uint? Step { get; set; } = null; + + /// + /// Contains messages such as announcements etc. + /// + public List Macros { get; private set; } = new(); + + /// + /// Contains data about each multiplier, roll, etc. + /// + public List Rolls { get; private set; } = new(); + + /// + /// Adds roll + /// + /// The roll 'collection' we wish to add + /// returns error message if validations fails, null if it's successfully added + public string? AddRoll(SettingsRoll newRoll) + { + var individualValidation = ValidateIndividual(newRoll); + if (individualValidation != null) return individualValidation; + + var fullValidation = ValidateRoll(newRoll); + if (fullValidation != null) return fullValidation; + + Rolls.Add(newRoll); + return null; + } + + /// + /// Validates new roll + /// + /// The roll we wish to add + /// Returns error message if validation fails, otherwise null string + private string? ValidateRoll(SettingsRoll newRoll) + { + string? message = null; + + var rollExists = Rolls.Exists(p => p.Roll == newRoll.Roll); + Misc.AppendMessage(rollExists, "The roll already exists", ref message); + var multiplierExists = Rolls.Exists(p => p.Multiplier == newRoll.Multiplier); + Misc.AppendMessage(multiplierExists, "This multiplier already exists", ref message); + var colourExists = Rolls.Exists(p => p.Colour == newRoll.Colour); + Misc.AppendMessage(colourExists, "This colour already exists", ref message); + + return message; + } } diff --git a/HighRollerClassic/DataStructures/SettingsRoll.cs b/HighRollerClassic/DataStructures/SettingsRoll.cs index f616e90..819eff0 100644 --- a/HighRollerClassic/DataStructures/SettingsRoll.cs +++ b/HighRollerClassic/DataStructures/SettingsRoll.cs @@ -2,9 +2,44 @@ using System.Numerics; namespace HighRollerClassic.DataStructures; -public struct SettingsRoll +/// +/// Stores individual 'Roll' setting (multiplier, roll, colour) +/// +/// the amount gil will get multiplied if roll interval is reached +/// the amount that will manipulate multiplier, usually acquired by a player running /random +/// each roll can be colour coded for better visibility +public record SettingsRoll(uint? Multiplier, uint? Roll, Vector4? Colour) { - private uint multiplier; - private uint roll; - private Vector4 color; + private const uint MinRollInterval = 1; + private const uint MaxRollInterval = 999; + + /// + /// Roll multiplier + /// + public uint? Multiplier { get; set; } = Multiplier; + + /// + /// Roll itself + /// + public uint? Roll + { + get; + set + { + if (value is < MinRollInterval or > MaxRollInterval) + { + field = null; + return; + } + + field = value; + } + } = Roll; + + /// + /// Colour that will be used to highlight roll in history + /// + public Vector4? Colour { get; set; } = Colour; + + public bool ValidInput => Multiplier.HasValue && Roll.HasValue; } diff --git a/HighRollerClassic/Windows/GambaWindow.cs b/HighRollerClassic/Windows/GambaWindow.cs index 7385554..10a0b24 100644 --- a/HighRollerClassic/Windows/GambaWindow.cs +++ b/HighRollerClassic/Windows/GambaWindow.cs @@ -9,13 +9,11 @@ namespace HighRollerClassic.Windows; public class GambaWindow : Window, IDisposable { private readonly Configuration configuration; + private readonly string name; // todo remove state as the window will only be opened by us calling it with parameters window id private readonly Player? player; private readonly Plugin plugin; - private readonly string name; - - private bool SettingsSet => configuration.Settings is { maxBet: not null, step: not null, rolls.Count: > 0, macros.Count: > 0 }; public GambaWindow(Plugin plugin, MenuTargetDefault target) : base($"High Roller Classic - {target.TargetName}##HRC{target.TargetContentId}", @@ -34,6 +32,9 @@ public class GambaWindow : Window, IDisposable name = target.TargetName; } + private bool SettingsSet => configuration.Settings is + { MaxBet: not null, Step: not null, Rolls.Count: > 0, Macros.Count: > 0 }; + public void Dispose() { } public override void Draw() diff --git a/HighRollerClassic/Windows/SettingsWindow.cs b/HighRollerClassic/Windows/SettingsWindow.cs index 2a94570..19f0d1e 100644 --- a/HighRollerClassic/Windows/SettingsWindow.cs +++ b/HighRollerClassic/Windows/SettingsWindow.cs @@ -1,6 +1,5 @@ using System; using System.Numerics; -using System.Runtime.CompilerServices; using Dalamud.Bindings.ImGui; using Dalamud.Interface.Components; using Dalamud.Interface.Windowing; @@ -19,34 +18,27 @@ public class SettingsWindow : Window, IDisposable private const uint MaxAllowedGil = 999_999_999; private readonly Configuration configuration; - - private bool maxBetFormatValid = true; - private SettingsRoll? newRoll; - - private (uint min, uint max) rollInterval = (1, 999); - private Settings settings; - private bool stepFormatValid = true; - - // colours - private readonly Vector4 yellow = new(249/255f, 180/255f, 45/255f, 1); private readonly Vector4 red = new(1, 0, 0, 1f); - public SettingsWindow(Plugin plugin) : base("Settings##HRC Settings") + // colours + private readonly Vector4 yellow = new(249 / 255f, 180 / 255f, 45 / 255f, 1); + + private SettingsRoll? newRoll; + + private Settings settings; + private bool stepFormatValid = true; + + public SettingsWindow(Plugin plugin) : base("Settings##HRC") { - Flags = ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoScrollbar | - ImGuiWindowFlags.NoScrollWithMouse; + Flags = ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse; Size = new Vector2(500, 300); SizeCondition = ImGuiCond.Always; configuration = plugin.Configuration; - // this creates a copy, not a reference - settings = configuration.Settings; + settings = new Settings(); } - // todo proper implementation it's just a placeholder - private bool TempRoll => newRoll.HasValue; - public void Dispose() { } public override void PreDraw() { } @@ -72,23 +64,22 @@ public class SettingsWindow : Window, IDisposable radius - (textSize.X * 0.5f), radius - (textSize.Y * 0.5f) ); - - + drawList.AddText(textPos, textColor, text); - + ImGui.Dummy(new Vector2(radius * 2f, radius * 2f)); // todo set up multiplier, roll, color, etc // todo add button for rolls - if (ImGui.Button("Add roll") && TempRoll) - { - // TODO no new rolls must be there - newRoll = new SettingsRoll(); - } if (ImGui.CollapsingHeader("Rolls##settings")) { + if (ImGui.Button("Add roll") && TempRoll) + { + // TODO no new rolls must be there + newRoll = new SettingsRoll(); + } // todo here we put new rolls // foreach (var roll in settings.rolls) // { @@ -98,11 +89,11 @@ public class SettingsWindow : Window, IDisposable if (ImGui.CollapsingHeader("General##settings")) { - var maxbetValid = LabelTextInput("max_bet_label", "Max bet", "max_bet_text", ref settings.maxBet); + var maxbetValid = LabelTextInput("max_bet_label", "Max bet", "max_bet_text", ref settings.MaxBet); if (maxbetValid.HasValue) maxBetFormatValid = maxbetValid.Value; ImGui.Spacing(); - var stepValid = LabelTextInput("step_label", "Step", "step_input", ref settings.step); + var stepValid = LabelTextInput("step_label", "Step", "step_input", ref settings.Step); if (stepValid.HasValue) stepFormatValid = stepValid.Value; ImGui.Spacing(); @@ -125,8 +116,8 @@ public class SettingsWindow : Window, IDisposable configuration.Settings = settings; configuration.Save(); Plugin.Log.Debug($"Configuration data: \n\n " + - $"Max bet: {configuration.Settings.maxBet}\n" + - $"Step change: {configuration.Settings.step}"); + $"Max bet: {configuration.Settings.MaxBet}\n" + + $"Step change: {configuration.Settings.Step}"); } ImGui.EndDisabled(); @@ -141,12 +132,11 @@ public class SettingsWindow : Window, IDisposable /// Returns false if the roll is to be removed /// /// gil multiplication in case of a roll - /// if roll is checked on less/less or equal comparison /// how much user rolls /// colours the rolls in main window, depending on their value /// tracks which roll we're setting so input fields don't have the same ids - private bool? DisplayRollSetting( - ref uint multiplier, ref bool exact, ref uint roll, ref Vector4 colour, ref uint id) + private (bool? valid, bool change) DisplayRollSetting( + ref uint multiplier, ref uint roll, ref Vector4 colour, ref uint id, ref) { ImGui.SetNextItemWidth(RollSettingInputWidth); ImGui.InputUInt($"##multiplier{id}", ref multiplier); @@ -173,7 +163,8 @@ public class SettingsWindow : Window, IDisposable // TODO verify input // we need to verify if data inputted is "good" - return ValidateRollSetting(); + var valid = ValidateRollSetting(); + var change = } private bool ValidateRollSetting() @@ -184,6 +175,8 @@ public class SettingsWindow : Window, IDisposable // roll must not already exist + // colour must not exist already + return true; } @@ -194,8 +187,10 @@ public class SettingsWindow : Window, IDisposable /// text for the label input field /// id of the input field /// new value if parsing was successful + /// the original value in configuration to compare it to /// - private bool? LabelTextInput(string labelId, string labelText, string inputId, ref uint? result) + private (bool? valid, bool change) LabelTextInput( + string labelId, string labelText, string inputId, ref uint? result, ref uint? original) { bool? valid = null; @@ -213,21 +208,19 @@ public class SettingsWindow : Window, IDisposable result = parsedValue; valid = true; } - else - valid = false; + else valid = false; } - + // todo alert that appears when field doesn't match the configuration ImGui.SameLine(); ImGui.Text("*"); - - // todo place the alert if field validation fails - return valid; + // todo place the alert if field validation fails + return (valid, result == original); } /// - /// Validates inputs for Max bet and Step + /// Validates input values for Max bet and Step /// /// private (bool valid, string message) ValidateInput() @@ -237,10 +230,10 @@ public class SettingsWindow : Window, IDisposable if (!maxBetFormatValid || !stepFormatValid) SetError("Input fields have invalid data", ref message, ref valid); - if (settings.maxBet > MaxAllowedGil) + if (settings.MaxBet > MaxAllowedGil) SetError("Entered bet amount exceeds maximum possible bet", ref message, ref valid); - if (settings.step > configuration.Settings.maxBet || settings.maxBet < configuration.Settings.maxBet) + if (settings.Step > configuration.Settings.MaxBet || settings.MaxBet < configuration.Settings.MaxBet) SetError("Step change must not exceed current maximum bet", ref message, ref valid); return (valid, message);