Add quick turn-in option for manual turn-ins

pull/3/head v4.10
Liza 2024-06-06 22:03:42 +02:00
parent 4290e1432d
commit 2be09089f5
Signed by: liza
GPG Key ID: 7199F8D727D55F67
11 changed files with 171 additions and 90 deletions

View File

@ -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();

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<Version>4.9</Version>
<Version>4.10</Version>
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

View File

@ -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;
}
}
}

View File

@ -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})");

View File

@ -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<PurchaseItemRequest> 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);

View File

@ -1,9 +0,0 @@
using Dalamud.Game.Text.SeStringHandling;
namespace Deliveroo
{
internal sealed class DeliveryResult
{
public SeString? Message { get; init; }
}
}

View File

@ -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<AddonGrandCompanySupplyReward>("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<AddonGrandCompanySupplyList>("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;
}
}

View File

@ -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;

View File

@ -21,4 +21,6 @@ internal enum Stage
RequestStop,
Stopped,
SingleFinalizeTurnIn,
}

View File

@ -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<uint, GcRewardItem> _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<XivChatType>()
.Where(x => x != XivChatType.StandardEmote)

View File

@ -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}");
}