diff --git a/Deliveroo/Configuration.cs b/Deliveroo/Configuration.cs index 23210df..9f79084 100644 --- a/Deliveroo/Configuration.cs +++ b/Deliveroo/Configuration.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Dalamud.Configuration; +using Dalamud.Game.ClientState.Keys; using Dalamud.Game.Text; using Deliveroo.GameData; using LLib.ImGui; @@ -21,6 +22,7 @@ internal sealed class Configuration : IPluginConfiguration public EBehaviorOnOtherWorld BehaviorOnOtherWorld { get; set; } = EBehaviorOnOtherWorld.Warning; public bool DisableFrameLimiter { get; set; } = true; public bool UncapFrameRate { get; set; } + public VirtualKey QuickTurnInKey { get; set; } = VirtualKey.SHIFT; public WindowConfig TurnInWindowConfig { get; } = new(); public WindowConfig ConfigWindowConfig { get; } = new(); diff --git a/Deliveroo/Deliveroo.csproj b/Deliveroo/Deliveroo.csproj index daecc50..49d79b4 100644 --- a/Deliveroo/Deliveroo.csproj +++ b/Deliveroo/Deliveroo.csproj @@ -1,7 +1,7 @@ net8.0-windows - 4.9 + 4.10 12 enable true diff --git a/Deliveroo/DeliverooPlugin.GrandCompanySupplyReward.cs b/Deliveroo/DeliverooPlugin.GrandCompanySupplyReward.cs new file mode 100644 index 0000000..ebfb1ae --- /dev/null +++ b/Deliveroo/DeliverooPlugin.GrandCompanySupplyReward.cs @@ -0,0 +1,55 @@ +using System; +using System.Linq; +using Dalamud.Game.Addon.Lifecycle; +using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; +using Dalamud.Game.Text.SeStringHandling; +using Deliveroo.GameData; +using FFXIVClientStructs.FFXIV.Client.UI; +using LLib.GameUI; + +namespace Deliveroo; + +partial class DeliverooPlugin +{ + private unsafe void GrandCompanySupplyRewardPostSetup(AddonEvent type, AddonArgs args) + { + bool quickTurnIn = CurrentStage == Stage.Stopped && _keyState[_configuration.QuickTurnInKey]; + if (CurrentStage == Stage.TurnInSelected || quickTurnIn) + { + AddonGrandCompanySupplyReward* addonSupplyReward = (AddonGrandCompanySupplyReward*)args.Addon; + + string? itemName = addonSupplyReward->AtkUnitBase.AtkValues[4].ReadAtkString(); + if (itemName != null && _itemCache.GetItemIdFromItemName(itemName) + .Any(itemId => InternalConfiguration.QuickVentureExclusiveItems.Contains(itemId))) + { + DeliveryResult = new MessageDeliveryResult + { + Message = new SeStringBuilder() + .Append("Won't turn in ") + .AddItemLink(_itemCache.GetItemIdFromItemName(itemName).First()) + .Append(", as it can only be obtained through Quick Ventures.") + .Build(), + }; + + addonSupplyReward->AtkUnitBase.FireCallbackInt(1); + if (quickTurnIn) + CurrentStage = Stage.RequestStop; + else + CurrentStage = Stage.CloseGcSupplyWindowThenStop; + return; + } + + _pluginLog.Information($"Turning in '{itemName}'"); + + addonSupplyReward->AtkUnitBase.FireCallbackInt(0); + ContinueAt = DateTime.Now.AddSeconds(0.58); + if (quickTurnIn) + { + DeliveryResult = new NoDeliveryResult(); + CurrentStage = Stage.SingleFinalizeTurnIn; + } + else + CurrentStage = Stage.FinalizeTurnIn; + } + } +} diff --git a/Deliveroo/DeliverooPlugin.SelectYesNo.cs b/Deliveroo/DeliverooPlugin.SelectYesNo.cs index a8ba73d..c442b7e 100644 --- a/Deliveroo/DeliverooPlugin.SelectYesNo.cs +++ b/Deliveroo/DeliverooPlugin.SelectYesNo.cs @@ -40,7 +40,7 @@ partial class DeliverooPlugin CurrentStage = Stage.CloseGcExchange; ContinueAt = DateTime.Now.AddSeconds(0.5); } - else if (CurrentStage == Stage.TurnInSelected && + else if ((CurrentStage == Stage.TurnInSelected || _keyState[_configuration.QuickTurnInKey]) && _gameStrings.TradeHighQualityItem == text) { _pluginLog.Information($"Selecting 'yes' ({text})"); diff --git a/Deliveroo/DeliverooPlugin.cs b/Deliveroo/DeliverooPlugin.cs index 1b07eaa..c581b28 100644 --- a/Deliveroo/DeliverooPlugin.cs +++ b/Deliveroo/DeliverooPlugin.cs @@ -34,6 +34,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin private readonly ICommandManager _commandManager; private readonly IPluginLog _pluginLog; private readonly IAddonLifecycle _addonLifecycle; + private readonly IKeyState _keyState; // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable private readonly Configuration _configuration; @@ -46,6 +47,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin private readonly GcRewardsCache _gcRewardsCache; private readonly IconCache _iconCache; + private readonly ItemCache _itemCache; private readonly ExchangeHandler _exchangeHandler; private readonly SupplyHandler _supplyHandler; private readonly ConfigWindow _configWindow; @@ -56,7 +58,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin public DeliverooPlugin(DalamudPluginInterface pluginInterface, IChatGui chatGui, IGameGui gameGui, IFramework framework, IClientState clientState, IObjectTable objectTable, ITargetManager targetManager, IDataManager dataManager, ICondition condition, ICommandManager commandManager, IPluginLog pluginLog, - IAddonLifecycle addonLifecycle, ITextureProvider textureProvider, IGameConfig gameConfig) + IAddonLifecycle addonLifecycle, ITextureProvider textureProvider, IGameConfig gameConfig, IKeyState keyState) { ArgumentNullException.ThrowIfNull(dataManager); @@ -69,6 +71,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin _commandManager = commandManager; _pluginLog = pluginLog; _addonLifecycle = addonLifecycle; + _keyState = keyState; _configuration = (Configuration?)_pluginInterface.GetPluginConfig() ?? new Configuration(); _gameStrings = new GameStrings(dataManager, _pluginLog); @@ -77,17 +80,16 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin _externalPluginHandler, _pluginLog); _gcRewardsCache = new GcRewardsCache(dataManager); _iconCache = new IconCache(textureProvider); - var itemCache = new ItemCache(dataManager); + _itemCache = new ItemCache(dataManager); _exchangeHandler = new ExchangeHandler(this, _gameFunctions, targetManager, _gameGui, _chatGui, _pluginLog); - _supplyHandler = new SupplyHandler(this, _gameFunctions, targetManager, _gameGui, itemCache, - _pluginLog); + _supplyHandler = new SupplyHandler(this, _gameFunctions, targetManager, _gameGui, _pluginLog); _configWindow = new ConfigWindow(_pluginInterface, this, _configuration, _gcRewardsCache, _clientState, _pluginLog, _iconCache, _gameFunctions); _windowSystem.AddWindow(_configWindow); _turnInWindow = new TurnInWindow(this, _pluginInterface, _configuration, _condition, _clientState, - _gcRewardsCache, _configWindow, _iconCache, _gameFunctions); + _gcRewardsCache, _configWindow, _iconCache, _keyState, _gameGui, _gameFunctions); _windowSystem.AddWindow(_turnInWindow); _framework.Update += FrameworkUpdate; @@ -109,6 +111,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectString", SelectStringPostSetup); _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectYesno", SelectYesNoPostSetup); + _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "GrandCompanySupplyReward", GrandCompanySupplyRewardPostSetup); } private void ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, @@ -130,7 +133,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin { _turnInWindow.State = false; _pluginLog.Information($"Pausing GC delivery, FC reached rank {rank}"); - DeliveryResult = new DeliveryResult + DeliveryResult = new MessageDeliveryResult { Message = new SeStringBuilder() .Append($"Pausing Deliveroo, your FC reached rank {rank}.") @@ -160,7 +163,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin internal DateTime ContinueAt { private get; set; } = DateTime.MinValue; internal List ItemsToPurchaseNow { get; private set; } = new(); internal int LastTurnInListSize { get; set; } = int.MaxValue; - internal DeliveryResult? DeliveryResult { get; set; } + internal IDeliveryResult? DeliveryResult { get; set; } internal bool TurnInState { @@ -254,7 +257,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin { CurrentStage = Stage.TargetPersonnelOfficer; ItemsToPurchaseNow = _turnInWindow.SelectedItems; - DeliveryResult = new(); + DeliveryResult = new MessageDeliveryResult(); _supplyHandler.ResetTurnInErrorHandling(); if (ItemsToPurchaseNow.Count > 0) { @@ -310,10 +313,11 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin break; case Stage.TurnInSelected: - _supplyHandler.TurnInSelectedItem(); + // see GrandCompanySupplyReward break; case Stage.FinalizeTurnIn: + case Stage.SingleFinalizeTurnIn: _supplyHandler.FinalizeTurnInItem(); break; @@ -374,40 +378,43 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin _externalPluginHandler.Restore(); CurrentStage = Stage.Stopped; - var text = DeliveryResult?.Message ?? "Delivery completed."; - var message = _configuration.ChatType switch + if (DeliveryResult is null or MessageDeliveryResult) { - XivChatType.Say - or XivChatType.Shout - or XivChatType.TellOutgoing - or XivChatType.TellIncoming - or XivChatType.Party - or XivChatType.Alliance - or (>= XivChatType.Ls1 and <= XivChatType.Ls8) - or XivChatType.FreeCompany - or XivChatType.NoviceNetwork - or XivChatType.Yell - or XivChatType.CrossParty - or XivChatType.PvPTeam - or XivChatType.CrossLinkShell1 - or XivChatType.NPCDialogue - or XivChatType.NPCDialogueAnnouncements - or (>= XivChatType.CrossLinkShell2 and <= XivChatType.CrossLinkShell8) - => new XivChatEntry - { - Message = text, - Type = _configuration.ChatType, - Name = new SeStringBuilder().AddUiForeground("Deliveroo", 52).Build(), - }, - _ => new XivChatEntry + var text = (DeliveryResult as MessageDeliveryResult)?.Message ?? "Delivery completed."; + var message = _configuration.ChatType switch { - Message = new SeStringBuilder().AddUiForeground("[Deliveroo] ", 52) - .Append(text) - .Build(), - Type = _configuration.ChatType, - } - }; - _chatGui.Print(message); + XivChatType.Say + or XivChatType.Shout + or XivChatType.TellOutgoing + or XivChatType.TellIncoming + or XivChatType.Party + or XivChatType.Alliance + or (>= XivChatType.Ls1 and <= XivChatType.Ls8) + or XivChatType.FreeCompany + or XivChatType.NoviceNetwork + or XivChatType.Yell + or XivChatType.CrossParty + or XivChatType.PvPTeam + or XivChatType.CrossLinkShell1 + or XivChatType.NPCDialogue + or XivChatType.NPCDialogueAnnouncements + or (>= XivChatType.CrossLinkShell2 and <= XivChatType.CrossLinkShell8) + => new XivChatEntry + { + Message = text, + Type = _configuration.ChatType, + Name = new SeStringBuilder().AddUiForeground("Deliveroo", 52).Build(), + }, + _ => new XivChatEntry + { + Message = new SeStringBuilder().AddUiForeground("[Deliveroo] ", 52) + .Append(text) + .Build(), + Type = _configuration.ChatType, + } + }; + _chatGui.Print(message); + } DeliveryResult = null; } @@ -415,6 +422,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin public void Dispose() { + _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "GrandCompanySupplyReward", GrandCompanySupplyRewardPostSetup); _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "SelectYesno", SelectYesNoPostSetup); _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "SelectString", SelectStringPostSetup); diff --git a/Deliveroo/DeliveryResult.cs b/Deliveroo/DeliveryResult.cs deleted file mode 100644 index 79af2a0..0000000 --- a/Deliveroo/DeliveryResult.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Dalamud.Game.Text.SeStringHandling; - -namespace Deliveroo -{ - internal sealed class DeliveryResult - { - public SeString? Message { get; init; } - } -} diff --git a/Deliveroo/Handlers/SupplyHandler.cs b/Deliveroo/Handlers/SupplyHandler.cs index 6cd8892..ee5dcc1 100644 --- a/Deliveroo/Handlers/SupplyHandler.cs +++ b/Deliveroo/Handlers/SupplyHandler.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects.Types; -using Dalamud.Game.Text.SeStringHandling; using Dalamud.Plugin.Services; using Deliveroo.GameData; using FFXIVClientStructs.FFXIV.Client.UI; @@ -20,19 +18,17 @@ internal sealed class SupplyHandler private readonly GameFunctions _gameFunctions; private readonly ITargetManager _targetManager; private readonly IGameGui _gameGui; - private readonly ItemCache _itemCache; private readonly IPluginLog _pluginLog; private uint _turnInErrors; public SupplyHandler(DeliverooPlugin plugin, GameFunctions gameFunctions, ITargetManager targetManager, - IGameGui gameGui, ItemCache itemCache, IPluginLog pluginLog) + IGameGui gameGui, IPluginLog pluginLog) { _plugin = plugin; _gameFunctions = gameFunctions; _targetManager = targetManager; _gameGui = gameGui; - _itemCache = itemCache; _pluginLog = pluginLog; } @@ -198,37 +194,6 @@ internal sealed class SupplyHandler } } - public unsafe void TurnInSelectedItem() - { - if (_gameGui.TryGetAddonByName("GrandCompanySupplyReward", - out var addonSupplyReward) && LAddon.IsAddonReady(&addonSupplyReward->AtkUnitBase)) - { - string? itemName = addonSupplyReward->AtkUnitBase.AtkValues[4].ReadAtkString(); - if (itemName != null && _itemCache.GetItemIdFromItemName(itemName) - .Any(itemId => InternalConfiguration.QuickVentureExclusiveItems.Contains(itemId))) - { - _plugin.DeliveryResult = new DeliveryResult - { - Message = new SeStringBuilder() - .Append("Won't turn in ") - .AddItemLink(_itemCache.GetItemIdFromItemName(itemName).First()) - .Append(", as it can only be obtained through Quick Ventures.") - .Build(), - }; - - addonSupplyReward->AtkUnitBase.FireCallbackInt(1); - _plugin.CurrentStage = Stage.CloseGcSupplyWindowThenStop; - return; - } - - _pluginLog.Information($"Turning in '{itemName}'"); - - addonSupplyReward->AtkUnitBase.FireCallbackInt(0); - _plugin.ContinueAt = DateTime.Now.AddSeconds(0.58); - _plugin.CurrentStage = Stage.FinalizeTurnIn; - } - } - public unsafe void FinalizeTurnInItem() { if (_gameGui.TryGetAddonByName("GrandCompanySupplyList", @@ -241,7 +206,10 @@ internal sealed class SupplyHandler new() { Type = 0, Int = 0 } }; addonSupplyList->AtkUnitBase.FireCallback(3, updateFilter); - _plugin.CurrentStage = Stage.SelectItemToTurnIn; + if (_plugin.CurrentStage == Stage.FinalizeTurnIn) + _plugin.CurrentStage = Stage.SelectItemToTurnIn; + else + _plugin.CurrentStage = Stage.RequestStop; } } diff --git a/Deliveroo/MessageDeliveryResult.cs b/Deliveroo/MessageDeliveryResult.cs new file mode 100644 index 0000000..f339845 --- /dev/null +++ b/Deliveroo/MessageDeliveryResult.cs @@ -0,0 +1,12 @@ +using Dalamud.Game.Text.SeStringHandling; + +namespace Deliveroo; + +internal interface IDeliveryResult; + +internal sealed class MessageDeliveryResult : IDeliveryResult +{ + public SeString? Message { get; init; } +} + +internal sealed class NoDeliveryResult : IDeliveryResult; diff --git a/Deliveroo/Stage.cs b/Deliveroo/Stage.cs index a905747..7c70153 100644 --- a/Deliveroo/Stage.cs +++ b/Deliveroo/Stage.cs @@ -21,4 +21,6 @@ internal enum Stage RequestStop, Stopped, + + SingleFinalizeTurnIn, } diff --git a/Deliveroo/Windows/ConfigWindow.cs b/Deliveroo/Windows/ConfigWindow.cs index c96e133..9d27559 100644 --- a/Deliveroo/Windows/ConfigWindow.cs +++ b/Deliveroo/Windows/ConfigWindow.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; +using Dalamud.Game.ClientState.Keys; using Dalamud.Game.Text; using Dalamud.Interface; using Dalamud.Interface.Components; @@ -29,6 +30,15 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig private readonly GameFunctions _gameFunctions; private readonly IReadOnlyDictionary _itemLookup; + + private readonly List<(VirtualKey Key, string Label)> _keyCodes = + [ + (VirtualKey.NO_KEY, "Disabled"), + (VirtualKey.CONTROL, "CTRL"), + (VirtualKey.SHIFT, "SHIFT"), + (VirtualKey.MENU, "ALT"), + ]; + private string _searchString = string.Empty; private uint _dragDropSource; @@ -362,6 +372,15 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig ImGui.EndDisabled(); + ImGui.SetNextItemWidth(ImGuiHelpers.GlobalScale * 120); + int selectedKey = Math.Max(0, _keyCodes.FindIndex(x => x.Key == _configuration.QuickTurnInKey)); + if (ImGui.Combo("Quick Turn-In Key", ref selectedKey, _keyCodes.Select(x => x.Label).ToArray(), + _keyCodes.Count)) + { + _configuration.QuickTurnInKey = _keyCodes[selectedKey].Key; + Save(); + } + ImGui.SetNextItemWidth(ImGuiHelpers.GlobalScale * 120); var xivChatTypes = Enum.GetValues() .Where(x => x != XivChatType.StandardEmote) diff --git a/Deliveroo/Windows/TurnInWindow.cs b/Deliveroo/Windows/TurnInWindow.cs index a4122f2..5d0efb7 100644 --- a/Deliveroo/Windows/TurnInWindow.cs +++ b/Deliveroo/Windows/TurnInWindow.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; using Dalamud.Game.ClientState.Conditions; +using Dalamud.Game.ClientState.Keys; using Dalamud.Interface; using Dalamud.Interface.Colors; using Dalamud.Interface.Components; @@ -12,9 +13,11 @@ using Dalamud.Plugin; using Dalamud.Plugin.Services; using Deliveroo.GameData; using FFXIVClientStructs.FFXIV.Client.Game; +using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Client.UI.Agent; using ImGuiNET; using LLib; +using LLib.GameUI; using LLib.ImGui; namespace Deliveroo.Windows; @@ -51,13 +54,15 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig private readonly GcRewardsCache _gcRewardsCache; private readonly ConfigWindow _configWindow; private readonly IconCache _iconCache; + private readonly IKeyState _keyState; + private readonly IGameGui _gameGui; private readonly GameFunctions _gameFunctions; private bool _state; public TurnInWindow(DeliverooPlugin plugin, DalamudPluginInterface pluginInterface, Configuration configuration, ICondition condition, IClientState clientState, GcRewardsCache gcRewardsCache, ConfigWindow configWindow, - IconCache iconCache, GameFunctions gameFunctions) + IconCache iconCache, IKeyState keyState, IGameGui gameGui, GameFunctions gameFunctions) : base("GC Delivery###DeliverooTurnIn") { _plugin = plugin; @@ -68,6 +73,8 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig _gcRewardsCache = gcRewardsCache; _configWindow = configWindow; _iconCache = iconCache; + _keyState = keyState; + _gameGui = gameGui; _gameFunctions = gameFunctions; Position = new Vector2(100, 100); @@ -260,6 +267,23 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig } ImGui.Separator(); + if (_configuration.QuickTurnInKey != VirtualKey.NO_KEY) + { + var key = _configuration.QuickTurnInKey switch + { + VirtualKey.MENU => "ALT", + VirtualKey.SHIFT => "SHIFT", + VirtualKey.CONTROL => "CTRL", + _ => _configuration.QuickTurnInKey.ToString() + }; + if (!State && _keyState[_configuration.QuickTurnInKey]) + ImGui.TextColored(ImGuiColors.HealerGreen, "Click an item to turn it in without confirmation"); + else + ImGui.Text($"Hold '{key}' when clicking an item to turn it in without confirmation."); + + ImGui.Separator(); + } + ImGui.Text($"Debug (State): {_plugin.CurrentStage}"); }