Compare commits
14 Commits
483b411125
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| f2545cab05 | |||
| 6fffedaa9d | |||
| 8c9c3b3d94 | |||
| f42732dbc4 | |||
| 82262cc7d6 | |||
| 8e381cf916 | |||
| d1dddb59bd | |||
| 21b9e84fec | |||
| aa7553d9f9 | |||
| d00e82a96f | |||
| 08162ecccb | |||
| f5a35344d0 | |||
| 81a4bb4bc4 | |||
| e186db6fb0 |
@@ -7,8 +7,9 @@ namespace HighRollerClassic;
|
|||||||
[Serializable]
|
[Serializable]
|
||||||
public class Configuration : IPluginConfiguration
|
public class Configuration : IPluginConfiguration
|
||||||
{
|
{
|
||||||
public PlayerManager players = new();
|
public PlayerManager Players { get; set; } = new();
|
||||||
public Settings settings;
|
public SettingsStructure.Settings? Settings { get; set; } // is nullable if settings are not yet created
|
||||||
|
|
||||||
public int Version { get; set; } = 0;
|
public int Version { get; set; } = 0;
|
||||||
|
|
||||||
// The below exists just to make saving less cumbersome
|
// The below exists just to make saving less cumbersome
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace HighRollerClassic.DataStructures;
|
|
||||||
|
|
||||||
public struct Settings
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Contains data about each multiplier, roll, etc.
|
|
||||||
/// </summary>
|
|
||||||
private List<SettingsRolls> rolls;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Maximum bet that will be allowed to set
|
|
||||||
/// </summary>
|
|
||||||
private uint max_bet;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// How much the bet will change when user adjusts their bet via +/- keys
|
|
||||||
/// </summary>
|
|
||||||
private uint step;
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using System.Numerics;
|
|
||||||
|
|
||||||
namespace HighRollerClassic.DataStructures;
|
|
||||||
|
|
||||||
public struct SettingsRolls
|
|
||||||
{
|
|
||||||
private uint multiplier;
|
|
||||||
private uint roll;
|
|
||||||
private bool exact;
|
|
||||||
private Vector4 color;
|
|
||||||
}
|
|
||||||
9
HighRollerClassic/Macro/MacroType.cs
Normal file
9
HighRollerClassic/Macro/MacroType.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace HighRollerClassic.DataStructures;
|
||||||
|
|
||||||
|
public enum MacroType
|
||||||
|
{
|
||||||
|
Announce,
|
||||||
|
TargetBets,
|
||||||
|
WinsRoll,
|
||||||
|
LosesRoll
|
||||||
|
}
|
||||||
21
HighRollerClassic/Macro/MessageMacro.cs
Normal file
21
HighRollerClassic/Macro/MessageMacro.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
namespace HighRollerClassic.DataStructures;
|
||||||
|
|
||||||
|
public struct MessageMacro
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// which type of message we're storing here
|
||||||
|
/// </summary>
|
||||||
|
private MacroType type;
|
||||||
|
/// <summary>
|
||||||
|
/// only for messages that talk about rolls
|
||||||
|
/// </summary>
|
||||||
|
private uint? rollNum;
|
||||||
|
/// <summary>
|
||||||
|
/// message itself
|
||||||
|
/// </summary>
|
||||||
|
private string message;
|
||||||
|
/// <summary>
|
||||||
|
/// additional emotes that character will play out after/before outputting the message
|
||||||
|
/// </summary>
|
||||||
|
private string emotes;
|
||||||
|
}
|
||||||
@@ -5,10 +5,10 @@ namespace HighRollerClassic;
|
|||||||
|
|
||||||
public class Player(MenuTargetDefault target)
|
public class Player(MenuTargetDefault target)
|
||||||
{
|
{
|
||||||
private Roll rolls = new();
|
private RollHistory rollsHistory = new();
|
||||||
public int Bank { get; private set; } = 0;
|
public int Bank { get; private set; } = 0;
|
||||||
public string Name { get; private set; } = target.TargetName;
|
|
||||||
// todo maybe remove it and tie it to dalamud's api to get accurate character name once per session
|
|
||||||
|
|
||||||
public ulong ContentId { get; private set; } = target.TargetContentId;
|
public ulong ContentId { get; private set; } = target.TargetContentId;
|
||||||
|
|
||||||
|
// TODO implement roll history FULL
|
||||||
}
|
}
|
||||||
21
HighRollerClassic/Player/PlayerManager.cs
Normal file
21
HighRollerClassic/Player/PlayerManager.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Dalamud.Game.Gui.ContextMenu;
|
||||||
|
|
||||||
|
namespace HighRollerClassic;
|
||||||
|
|
||||||
|
public class PlayerManager
|
||||||
|
{
|
||||||
|
private List<Player> Players { get; set; } = [];
|
||||||
|
|
||||||
|
public Player? GetOrCreatePlayer(MenuTargetDefault? target)
|
||||||
|
{
|
||||||
|
if (target is null) return null;
|
||||||
|
|
||||||
|
var player = Players.Find(p => p.ContentId == target.TargetContentId);
|
||||||
|
if (player is not null) return player;
|
||||||
|
|
||||||
|
player = new Player(target);
|
||||||
|
Players.Add(player);
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace HighRollerClassic.DataStructures;
|
namespace HighRollerClassic.DataStructures;
|
||||||
|
|
||||||
public struct Roll
|
public struct RollHistory
|
||||||
{
|
{
|
||||||
private uint value;
|
private uint value;
|
||||||
private uint multiplier;
|
private uint multiplier;
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Dalamud.Game.Gui.ContextMenu;
|
|
||||||
|
|
||||||
namespace HighRollerClassic;
|
|
||||||
|
|
||||||
public class PlayerManager
|
|
||||||
{
|
|
||||||
private List<Player> Players { get; set; } = [];
|
|
||||||
|
|
||||||
public Player GetPlayer(MenuTargetDefault target)
|
|
||||||
{
|
|
||||||
foreach (var player in Players)
|
|
||||||
if (player.ContentId == target.TargetContentId)
|
|
||||||
return player;
|
|
||||||
|
|
||||||
Players.Add(new Player(target));
|
|
||||||
return Players.Last();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||||
using Dalamud.Game.Command;
|
using Dalamud.Game.Command;
|
||||||
using Dalamud.Game.Gui.ContextMenu;
|
using Dalamud.Game.Gui.ContextMenu;
|
||||||
@@ -7,40 +8,37 @@ using Dalamud.IoC;
|
|||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using HighRollerClassic.Windows;
|
using HighRollerClassic.Windows;
|
||||||
|
using Lumina.Data.Parsing.Layer;
|
||||||
|
|
||||||
namespace HighRollerClassic;
|
namespace HighRollerClassic;
|
||||||
|
|
||||||
public sealed class Plugin : IDalamudPlugin
|
public sealed class Plugin : IDalamudPlugin
|
||||||
{
|
{
|
||||||
private const string CommandName = "/hrc";
|
private const string CommandName = "/hrc";
|
||||||
private readonly PluginState state = new();
|
private readonly WindowSystem windowSystem = new("HighRollerClassic");
|
||||||
|
private readonly List<GambaWindow> gambaWindows = [];
|
||||||
public readonly WindowSystem WindowSystem = new("HighRollerClassic");
|
|
||||||
|
|
||||||
public Plugin()
|
public Plugin()
|
||||||
{
|
{
|
||||||
Configuration = PluginInterface.GetPluginConfig() as Configuration ?? new Configuration();
|
Configuration = PluginInterface.GetPluginConfig() as Configuration ?? new Configuration();
|
||||||
|
|
||||||
SettingsWindow = new SettingsWindow(this);
|
SettingsWindow = new SettingsWindow(this);
|
||||||
MainWindow = new MainWindow(this, state);
|
windowSystem.AddWindow(SettingsWindow);
|
||||||
|
|
||||||
WindowSystem.AddWindow(SettingsWindow);
|
|
||||||
WindowSystem.AddWindow(MainWindow);
|
|
||||||
|
|
||||||
CommandManager.AddHandler(CommandName, new CommandInfo(OnCommand)
|
CommandManager.AddHandler(CommandName, new CommandInfo(OnCommand)
|
||||||
{
|
{
|
||||||
HelpMessage = "Opens the High Roller Classic window"
|
HelpMessage = "Opens the HRC Settings"
|
||||||
});
|
});
|
||||||
|
|
||||||
// Tell the UI system that we want our windows to be drawn through the window system
|
// Tell the UI system that we want our windows to be drawn through the window system
|
||||||
PluginInterface.UiBuilder.Draw += WindowSystem.Draw;
|
PluginInterface.UiBuilder.Draw += windowSystem.Draw;
|
||||||
|
|
||||||
// This adds a button to the plugin installer entry of this plugin which allows
|
// This adds a button to the plugin installer entry of this plugin which allows
|
||||||
// toggling the display status of the configuration ui
|
// toggling the display status of the configuration ui
|
||||||
PluginInterface.UiBuilder.OpenConfigUi += ToggleConfigUi;
|
PluginInterface.UiBuilder.OpenConfigUi += ToggleSettingsUi;
|
||||||
|
|
||||||
// Adds another button doing the same but for the main ui of the plugin
|
// Adds another button doing the same but for the main ui of the plugin
|
||||||
PluginInterface.UiBuilder.OpenMainUi += ToggleMainUi;
|
// PluginInterface.UiBuilder.OpenMainUi += ToggleMainUi;
|
||||||
|
|
||||||
// Add a simple message to the log with level set to information
|
// Add a simple message to the log with level set to information
|
||||||
// Use /xllog to open the log window in-game
|
// Use /xllog to open the log window in-game
|
||||||
@@ -77,19 +75,21 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
|
|
||||||
public Configuration Configuration { get; init; }
|
public Configuration Configuration { get; init; }
|
||||||
private SettingsWindow SettingsWindow { get; init; }
|
private SettingsWindow SettingsWindow { get; init; }
|
||||||
private MainWindow MainWindow { get; init; }
|
private List<GambaWindow> Windows { get; init; }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
// Unregister all actions to not leak anything during disposal of plugin
|
// Unregister all actions to not leak anything during disposal of plugin
|
||||||
PluginInterface.UiBuilder.Draw -= WindowSystem.Draw;
|
PluginInterface.UiBuilder.Draw -= windowSystem.Draw;
|
||||||
PluginInterface.UiBuilder.OpenConfigUi -= ToggleConfigUi;
|
PluginInterface.UiBuilder.OpenConfigUi -= ToggleSettingsUi;
|
||||||
PluginInterface.UiBuilder.OpenMainUi -= ToggleMainUi;
|
|
||||||
|
|
||||||
WindowSystem.RemoveAllWindows();
|
windowSystem.RemoveAllWindows();
|
||||||
|
|
||||||
SettingsWindow.Dispose();
|
SettingsWindow.Dispose();
|
||||||
MainWindow.Dispose();
|
foreach (var window in gambaWindows)
|
||||||
|
{
|
||||||
|
window.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
CommandManager.RemoveHandler(CommandName);
|
CommandManager.RemoveHandler(CommandName);
|
||||||
|
|
||||||
@@ -99,17 +99,12 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
private void OnCommand(string command, string args)
|
private void OnCommand(string command, string args)
|
||||||
{
|
{
|
||||||
// In response to the slash command, toggle the display status of our main ui
|
// In response to the slash command, toggle the display status of our main ui
|
||||||
MainWindow.Toggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ToggleConfigUi()
|
|
||||||
{
|
|
||||||
SettingsWindow.Toggle();
|
SettingsWindow.Toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ToggleMainUi()
|
public void ToggleSettingsUi()
|
||||||
{
|
{
|
||||||
MainWindow.Toggle();
|
SettingsWindow.Toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PlayerIsLoaded()
|
public bool PlayerIsLoaded()
|
||||||
@@ -121,12 +116,12 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
{
|
{
|
||||||
if (args.MenuType == ContextMenuType.Inventory) return;
|
if (args.MenuType == ContextMenuType.Inventory) return;
|
||||||
|
|
||||||
// get character's (persistent) id
|
|
||||||
var target = (MenuTargetDefault)args.Target;
|
var target = (MenuTargetDefault)args.Target;
|
||||||
|
|
||||||
if (target.TargetObject is not IPlayerCharacter)
|
// target must be a player that is not self
|
||||||
|
if (target.TargetObject is not IPlayerCharacter || target.TargetContentId == PlayerState.ContentId)
|
||||||
{
|
{
|
||||||
Log.Debug("Not a player, returning");
|
Log.Debug("Not a foreign player");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,11 +136,28 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
|
|
||||||
private Action<IMenuItemClickedArgs> ContextMenuPlayerGameStart(MenuTargetDefault target)
|
private Action<IMenuItemClickedArgs> ContextMenuPlayerGameStart(MenuTargetDefault target)
|
||||||
{
|
{
|
||||||
return args =>
|
return _ =>
|
||||||
{
|
{
|
||||||
Log.Debug($"Starting match with {target.TargetName}");
|
Log.Debug($"Starting gamba with {target.TargetName}");
|
||||||
state.Target = target;
|
CreateGambaWindow(target);
|
||||||
MainWindow.Toggle();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CreateGambaWindow(MenuTargetDefault target)
|
||||||
|
{
|
||||||
|
var existingWindow = gambaWindows.Find(p => p.WindowName.Contains(target.TargetContentId.ToString()));
|
||||||
|
if (existingWindow is { IsOpen: false })
|
||||||
|
{
|
||||||
|
existingWindow.Toggle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var window = new GambaWindow(this, target)
|
||||||
|
{
|
||||||
|
IsOpen = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
gambaWindows.Add(window);
|
||||||
|
windowSystem.AddWindow(window);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
using Dalamud.Game.Gui.ContextMenu;
|
|
||||||
|
|
||||||
namespace HighRollerClassic;
|
|
||||||
|
|
||||||
public sealed class PluginState
|
|
||||||
{
|
|
||||||
/// tracks selected target as we pass it to the window
|
|
||||||
public MenuTargetDefault? Target { get; set; }
|
|
||||||
}
|
|
||||||
48
HighRollerClassic/SettingsStructure/RollsCollection.cs
Normal file
48
HighRollerClassic/SettingsStructure/RollsCollection.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace HighRollerClassic.SettingsStructure;
|
||||||
|
|
||||||
|
public class RollsCollection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains data about each multiplier, roll, etc.
|
||||||
|
/// </summary>
|
||||||
|
public List<SettingsRoll> Rolls { get; private set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates given roll
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newRoll">The roll we wish to validate</param>
|
||||||
|
/// <returns>Returns message TODO</returns>
|
||||||
|
private string? ValidateRoll(SettingsRoll newRoll)
|
||||||
|
{
|
||||||
|
if (!newRoll.IsValid) return "Invalid roll configuration input";
|
||||||
|
|
||||||
|
// existing values must not exist anywhere else
|
||||||
|
var mpExists = Rolls.Exists(p => p != newRoll && p.Roll.Value == newRoll.Roll.Value);
|
||||||
|
var rollExists = Rolls.Exists(p => p != newRoll && p.Roll.Value == newRoll.Roll.Value);
|
||||||
|
var colourExists = false;
|
||||||
|
if (newRoll.Colour.Value.HasValue)
|
||||||
|
{
|
||||||
|
colourExists = Rolls.Exists(p => p != newRoll && p.Colour.Value == newRoll.Colour.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasDuplicate = mpExists && rollExists && colourExists;
|
||||||
|
return hasDuplicate ? "The roll configuration is not unique!" : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Does quick iteration to see if rolls are valid
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>string if there is an error</returns>
|
||||||
|
public (bool valid, string? message) ValidateAll()
|
||||||
|
{
|
||||||
|
foreach (var roll in Rolls)
|
||||||
|
{
|
||||||
|
var val = ValidateRoll(roll);
|
||||||
|
if (ValidateRoll(roll) != null) return (false, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (true, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
10
HighRollerClassic/SettingsStructure/SettingValueType.cs
Normal file
10
HighRollerClassic/SettingsStructure/SettingValueType.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace HighRollerClassic.DataStructures;
|
||||||
|
|
||||||
|
public enum SettingValueType
|
||||||
|
{
|
||||||
|
Multiplier,
|
||||||
|
Roll,
|
||||||
|
Colour,
|
||||||
|
MaxBet,
|
||||||
|
Step,
|
||||||
|
}
|
||||||
34
HighRollerClassic/SettingsStructure/Settings.cs
Normal file
34
HighRollerClassic/SettingsStructure/Settings.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using HighRollerClassic.DataStructures;
|
||||||
|
|
||||||
|
namespace HighRollerClassic.SettingsStructure;
|
||||||
|
|
||||||
|
public class Settings(Configuration? configuration)
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Whether developer options should be visible in the settings
|
||||||
|
/// </summary>
|
||||||
|
public bool devOptions = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum bet that will be allowed to set
|
||||||
|
/// </summary>
|
||||||
|
public TrackedValue MaxBet { get; set; } = new(SettingValueType.MaxBet, null, null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How much the bet will change when user adjusts their bet via +/- keys
|
||||||
|
/// </summary>
|
||||||
|
public TrackedValue Step { get; set; } = new(SettingValueType.Step, configuration, null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains messages such as announcements etc.
|
||||||
|
/// </summary>
|
||||||
|
// TODO IMPLEMENT
|
||||||
|
public List<MessageMacro> Macros { get; private set; } = new();
|
||||||
|
|
||||||
|
public readonly RollsCollection Rolls = new();
|
||||||
|
|
||||||
|
// todo might get fucky wucky if maxbet is not yet defined
|
||||||
|
public bool IsValid => MaxBet.IsValid && Step.IsValid && Rolls.ValidateAll().valid;
|
||||||
|
public bool Set => IsValid && Rolls.Rolls.Count > 0 && Macros.Count > 0;
|
||||||
|
}
|
||||||
35
HighRollerClassic/SettingsStructure/SettingsRoll.cs
Normal file
35
HighRollerClassic/SettingsStructure/SettingsRoll.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Dalamud.Interface;
|
||||||
|
using HighRollerClassic.DataStructures;
|
||||||
|
|
||||||
|
namespace HighRollerClassic.SettingsStructure;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stores individual 'Roll' setting (multiplier, roll, colour)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="multiplier">Roll multiplier</param>
|
||||||
|
/// <param name="roll">Actual roll value</param>
|
||||||
|
/// <param name="colour">Actual colour (can be null)</param>
|
||||||
|
public class SettingsRoll(uint? multiplier, uint? roll, Vector4? colour)
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Roll multiplier
|
||||||
|
/// </summary>
|
||||||
|
public TrackedValue Multiplier { get; set; } = new(SettingValueType.Multiplier, null, multiplier);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Roll itself
|
||||||
|
/// </summary>
|
||||||
|
public TrackedValue Roll { get; set; } = new(SettingValueType.Roll, null, roll);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Colour that will be used to highlight roll in history
|
||||||
|
/// </summary>
|
||||||
|
public TrackedValue Colour { get; set; } =
|
||||||
|
new(SettingValueType.Colour, null, colour.HasValue ? ColorHelpers.RgbaVector4ToUint(colour.Value) : null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if all properties in record are valid
|
||||||
|
/// </summary>
|
||||||
|
public bool IsValid => Multiplier.IsValid && Roll.IsValid && Colour.IsValid;
|
||||||
|
}
|
||||||
85
HighRollerClassic/SettingsStructure/TrackedValue.cs
Normal file
85
HighRollerClassic/SettingsStructure/TrackedValue.cs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using HighRollerClassic.DataStructures;
|
||||||
|
|
||||||
|
namespace HighRollerClassic.SettingsStructure;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tracks value and its validity
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">Type of the value</param>
|
||||||
|
/// <param name="configuration">only gets sent if type is Step, to check it against existing MaxBet</param>
|
||||||
|
/// <param name="value">Its value</param>
|
||||||
|
public class TrackedValue(SettingValueType type, Configuration? configuration, uint? valueInit)
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The main value
|
||||||
|
/// </summary>
|
||||||
|
public uint? Value
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == field) return;
|
||||||
|
|
||||||
|
IsValid = CheckValid(value);
|
||||||
|
field = value;
|
||||||
|
}
|
||||||
|
} = valueInit;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tracks validity of the value
|
||||||
|
/// </summary>
|
||||||
|
public bool IsValid { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Minimum rng roll (/random)
|
||||||
|
/// </summary>
|
||||||
|
private const uint MinRoll = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum rng roll (/random)
|
||||||
|
/// </summary>
|
||||||
|
private const uint MaxRoll = 999;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum possible gil in-game
|
||||||
|
/// </summary>
|
||||||
|
private const uint MaxGil = 999_999_999;
|
||||||
|
|
||||||
|
private readonly Func<uint?, bool> multiplierValid = v => v is not null;
|
||||||
|
private readonly Func<uint?, bool> rollValid = v => v is >= MinRoll and <= MaxRoll;
|
||||||
|
private readonly Func<uint?, bool> maxBetValid = v => v is <= MaxGil;
|
||||||
|
|
||||||
|
private bool StepValid(uint? value)
|
||||||
|
{
|
||||||
|
if (configuration is { Settings.MaxBet.IsValid: true })
|
||||||
|
{
|
||||||
|
var maxBet = configuration.Settings.MaxBet.Value!.Value;
|
||||||
|
return value <= maxBet;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if max bet is not set allow the user to set whichever they want
|
||||||
|
// it will get invalidated as soon as maxbet is set anyway
|
||||||
|
/* TODO if any of setting is considered INVALID
|
||||||
|
DO NOT USER USE THE APPLICATION
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the value is valid
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
private bool CheckValid(uint? value)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
SettingValueType.Multiplier => multiplierValid(value),
|
||||||
|
SettingValueType.Roll => rollValid(value),
|
||||||
|
SettingValueType.Colour => true,
|
||||||
|
SettingValueType.MaxBet => maxBetValid(value),
|
||||||
|
SettingValueType.Step => StepValid(value),
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,21 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Game.Gui.ContextMenu;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
|
|
||||||
namespace HighRollerClassic.Windows;
|
namespace HighRollerClassic.Windows;
|
||||||
|
|
||||||
public class MainWindow : Window, IDisposable
|
public class GambaWindow : Window, IDisposable
|
||||||
{
|
{
|
||||||
private readonly Configuration configuration;
|
private readonly Configuration configuration;
|
||||||
private readonly Plugin plugin;
|
private readonly string name;
|
||||||
private readonly PluginState state;
|
|
||||||
|
|
||||||
public MainWindow(Plugin plugin, PluginState state)
|
private readonly Player? player;
|
||||||
: base($"High Roller Classic###{state.Target?.TargetName ?? "null"}",
|
private readonly Plugin plugin;
|
||||||
|
|
||||||
|
public GambaWindow(Plugin plugin, MenuTargetDefault target)
|
||||||
|
: base($"High Roller Classic - {target.TargetName}##HRC{target.TargetContentId}",
|
||||||
ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse)
|
ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse)
|
||||||
{
|
{
|
||||||
SizeConstraints = new WindowSizeConstraints
|
SizeConstraints = new WindowSizeConstraints
|
||||||
@@ -23,38 +26,35 @@ public class MainWindow : Window, IDisposable
|
|||||||
|
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
configuration = this.plugin.Configuration;
|
configuration = this.plugin.Configuration;
|
||||||
this.state = state;
|
|
||||||
|
player = configuration.Players.GetOrCreatePlayer(target);
|
||||||
|
name = target.TargetName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
{
|
{
|
||||||
// TODO check if local player is null and if it is do not load anything
|
|
||||||
|
|
||||||
if (!plugin.PlayerIsLoaded())
|
if (!plugin.PlayerIsLoaded())
|
||||||
{
|
{
|
||||||
ImGui.Text("Player must be loaded in the world in order for the plugin to function");
|
ImGui.Text("Player must be loaded in the world in order for the plugin to function");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO check if all settings are set
|
if (!configuration.Settings.Set)
|
||||||
roll settings
|
{
|
||||||
message/macro settings
|
ImGui.Text("Please set up settings");
|
||||||
*/
|
return;
|
||||||
// TODO create player project and clear the existing shared state
|
}
|
||||||
|
|
||||||
if (state.Target == null)
|
if (player == null)
|
||||||
{
|
{
|
||||||
ImGui.Text(
|
ImGui.Text(
|
||||||
"No target selected, please open HRC by right clicking the player and choosing the 'High Roller Classic' option");
|
"No target selected, please open HRC by right clicking the player and choosing the 'High Roller Classic' option");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var player = configuration.players.GetPlayer(state.Target);
|
ImGui.Text($"Player: {name}");
|
||||||
state.Target = null;
|
|
||||||
|
|
||||||
ImGui.Text($"Player: {player}");
|
|
||||||
ImGui.Spacing();
|
ImGui.Spacing();
|
||||||
|
|
||||||
ImGui.Text($"Bank balance: {player.Bank} gil");
|
ImGui.Text($"Bank balance: {player.Bank} gil");
|
||||||
@@ -1,27 +1,43 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Interface;
|
||||||
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using HighRollerClassic.DataStructures;
|
using HighRollerClassic.DataStructures;
|
||||||
|
using HighRollerClassic.SettingsStructure;
|
||||||
|
|
||||||
namespace HighRollerClassic.Windows;
|
namespace HighRollerClassic.Windows;
|
||||||
|
|
||||||
public class SettingsWindow : Window, IDisposable
|
public class SettingsWindow : Window, IDisposable
|
||||||
{
|
{
|
||||||
|
private const int XOffset = 80;
|
||||||
|
private const int Spacing = 5;
|
||||||
|
private const int InputWidth = 105;
|
||||||
|
private const int InputMaxLen = 11;
|
||||||
|
private const uint RollInputWidth = 50;
|
||||||
|
|
||||||
private readonly Configuration configuration;
|
private readonly Configuration configuration;
|
||||||
|
|
||||||
// We give this window a constant ID using ###.
|
// colours
|
||||||
// This allows for labels to be dynamic, like "{FPS Counter}fps###XYZ counter window",
|
private readonly Vector4 red = new(1, 0, 0, 1f);
|
||||||
// and the window ID will always be "###XYZ counter window" for ImGui
|
private readonly Vector4 yellow = new(249 / 255f, 180 / 255f, 45 / 255f, 1);
|
||||||
public SettingsWindow(Plugin plugin) : base("Settings###HRC")
|
|
||||||
{
|
|
||||||
Flags = ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoScrollbar |
|
|
||||||
ImGuiWindowFlags.NoScrollWithMouse;
|
|
||||||
|
|
||||||
Size = new Vector2(232, 90);
|
private Settings settings;
|
||||||
|
|
||||||
|
public SettingsWindow(Plugin plugin) : base("Settings##HRC")
|
||||||
|
{
|
||||||
|
Flags = ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse;
|
||||||
|
|
||||||
|
Size = new Vector2(500, 300);
|
||||||
SizeCondition = ImGuiCond.Always;
|
SizeCondition = ImGuiCond.Always;
|
||||||
|
|
||||||
configuration = plugin.Configuration;
|
configuration = plugin.Configuration;
|
||||||
|
|
||||||
|
// todo settings from config can be null
|
||||||
|
// todo if null create new, if not copy existing
|
||||||
|
settings = new Settings(configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
@@ -30,13 +46,167 @@ public class SettingsWindow : Window, IDisposable
|
|||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
{
|
{
|
||||||
Settings settings;
|
|
||||||
|
|
||||||
// todo set up multiplier, roll, color, etc
|
// todo set up multiplier, roll, color, etc
|
||||||
// todo add button for rolls
|
|
||||||
|
|
||||||
// todo setup max bet, change
|
if (ImGui.CollapsingHeader("Rolls##settings"))
|
||||||
|
{
|
||||||
|
if (ImGui.Button("Add roll"))
|
||||||
|
{
|
||||||
|
settings.Rolls.Rolls.Add(new SettingsRoll(null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
// todo save button which will copy our settings to configuration and invoke .Save() to save configuration to disk
|
// todo display new roll
|
||||||
|
|
||||||
|
for (uint i = 0; i < settings.Rolls.Rolls.Count; i++)
|
||||||
|
{
|
||||||
|
DisplayRollSetting(i, settings.Rolls.Rolls[(int)i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo reorder by multiplier/roll
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.CollapsingHeader("General##settings"))
|
||||||
|
{
|
||||||
|
LabelTextInput("max_bet_label", "Max bet", "max_bet_text", settings.MaxBet);
|
||||||
|
ImGui.Spacing();
|
||||||
|
|
||||||
|
LabelTextInput("step_label", "Step", "step_input", settings.Step);
|
||||||
|
ImGui.Spacing();
|
||||||
|
|
||||||
|
ImGui.Checkbox("Developer options", ref settings.devOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configuration.Settings.devOptions && ImGui.CollapsingHeader("Developer options"))
|
||||||
|
{
|
||||||
|
// todo add developer settings - like the ability to have every character have HRC open
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.Spacing();
|
||||||
|
var validation = settings.Rolls.ValidateAll();
|
||||||
|
ImGui.BeginDisabled(validation != null);
|
||||||
|
|
||||||
|
if (ImGui.Button("Save"))
|
||||||
|
{
|
||||||
|
configuration.Settings = settings;
|
||||||
|
configuration.Save();
|
||||||
|
Plugin.Log.Debug($"Configuration data: \n\n " +
|
||||||
|
$"Max bet: {configuration.Settings.MaxBet}\n" +
|
||||||
|
$"Step change: {configuration.Settings.Step}");
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndDisabled();
|
||||||
|
ImGui.SameLine();
|
||||||
|
if (validation != null && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||||
|
ImGui.SetTooltip(validation);
|
||||||
|
|
||||||
|
if (ImGui.Button("Reset")) settings = configuration.Settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawError()
|
||||||
|
{
|
||||||
|
// todo integrate for every field
|
||||||
|
var drawList = ImGui.GetWindowDrawList();
|
||||||
|
|
||||||
|
var center = ImGui.GetCursorScreenPos();
|
||||||
|
const uint radius = 10;
|
||||||
|
|
||||||
|
var circleColor = ImGui.GetColorU32(yellow);
|
||||||
|
var borderColor = ImGui.GetColorU32(red);
|
||||||
|
var textColor = ImGui.GetColorU32(red);
|
||||||
|
|
||||||
|
drawList.AddCircleFilled(center + new Vector2(radius, radius), radius, circleColor);
|
||||||
|
drawList.AddCircle(center + new Vector2(radius, radius), radius, borderColor, 0, 2.5f);
|
||||||
|
|
||||||
|
const string text = "!";
|
||||||
|
var textSize = ImGui.CalcTextSize(text);
|
||||||
|
var textPos = center + new Vector2(
|
||||||
|
radius - (textSize.X * 0.5f),
|
||||||
|
radius - (textSize.Y * 0.5f)
|
||||||
|
);
|
||||||
|
|
||||||
|
drawList.AddText(textPos, textColor, text);
|
||||||
|
|
||||||
|
ImGui.Dummy(new Vector2(radius * 2f, radius * 2f));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns false if the roll is to be removed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="multiplier">gil multiplication in case of a roll</param>
|
||||||
|
/// <param name="roll">how much user rolls</param>
|
||||||
|
/// <param name="colour">colours the rolls in main window, depending on their value</param>
|
||||||
|
/// <param name="id">tracks which roll we're setting so input fields don't have the same ids</param>
|
||||||
|
private void DisplayRollSetting(uint id, SettingsRoll rollConfig)
|
||||||
|
{
|
||||||
|
uint multiplier = rollConfig.Multiplier.Value ?? 0;
|
||||||
|
ImGui.SetNextItemWidth(RollInputWidth);
|
||||||
|
if (ImGui.InputUInt($"##multiplier{id}", ref multiplier))
|
||||||
|
{
|
||||||
|
// todo edge case if we change but don't get good value
|
||||||
|
/* possible solutions
|
||||||
|
1. do int
|
||||||
|
2. do string textbox
|
||||||
|
3. make a fucky check if the new value = old value and in that case don't send it in
|
||||||
|
*/
|
||||||
|
rollConfig.Multiplier.Value = multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
ImGui.Text("x");
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
ImGui.SetNextItemWidth(RollInputWidth);
|
||||||
|
ImGui.InputUInt($"##roll{id}", ref roll);
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
var colourVal = rollConfig.Colour.Value.HasValue
|
||||||
|
? ColorHelpers.RgbaUintToVector4(rollConfig.Colour.Value.Value)
|
||||||
|
: new Vector4(0, 0, 0, 1);
|
||||||
|
var newColour = ImGuiComponents.ColorPickerWithPalette(
|
||||||
|
(int)id, "placeholder", colourVal);
|
||||||
|
// TODO if colour is black (0,0,0) set it to null
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
if (ImGui.Button("-"))
|
||||||
|
{
|
||||||
|
// signals to the colour to remove this roll setting
|
||||||
|
settings.Rolls.Rolls.Remove(rollConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO verify input
|
||||||
|
// we need to verify if data inputted is "good"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if valid, false if invalid or null if validity has no changed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="labelId">id of the label field</param>
|
||||||
|
/// <param name="labelText">text for the label input field</param>
|
||||||
|
/// <param name="inputId">id of the input field</param>
|
||||||
|
/// <param name="original">the original value in configuration to compare it to</param>
|
||||||
|
private void LabelTextInput(
|
||||||
|
string labelId, string labelText, string inputId, TrackedValue original)
|
||||||
|
{
|
||||||
|
ImGui.LabelText($"###{labelId}", $"{labelText}: ");
|
||||||
|
ImGui.SameLine(XOffset, Spacing);
|
||||||
|
ImGui.SetNextItemWidth(InputWidth);
|
||||||
|
|
||||||
|
var buf = original.Value?.ToString("N0") ?? "";
|
||||||
|
|
||||||
|
if (ImGui.InputText($"###{inputId}", ref buf, InputMaxLen))
|
||||||
|
{
|
||||||
|
var num = buf.Replace(",", string.Empty).Replace(".", string.Empty);
|
||||||
|
if (uint.TryParse(num, out var parsedValue))
|
||||||
|
{
|
||||||
|
original.Value = parsedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (original.IsValid) return;
|
||||||
|
ImGui.SameLine();
|
||||||
|
// todo alert that appears when field doesn't match the configuration
|
||||||
|
ImGui.Text("ERROR");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user