Compare commits

..

No commits in common. "master" and "v4.10" have entirely different histories.

21 changed files with 414 additions and 624 deletions

View File

@ -17,10 +17,10 @@ internal sealed class CharacterConfiguration
public bool OverrideItemsToPurchase { get; set; } public bool OverrideItemsToPurchase { get; set; }
public List<Configuration.PurchasePriority> ItemsToPurchase { get; set; } = new(); public List<Configuration.PurchasePriority> ItemsToPurchase { get; set; } = new();
public static string ResolveFilePath(IDalamudPluginInterface pluginInterface, ulong localContentId) public static string ResolveFilePath(DalamudPluginInterface pluginInterface, ulong localContentId)
=> Path.Join(pluginInterface.GetPluginConfigDirectory(), $"char.{localContentId:X}.json"); => Path.Join(pluginInterface.GetPluginConfigDirectory(), $"char.{localContentId:X}.json");
public static CharacterConfiguration? Load(IDalamudPluginInterface pluginInterface, ulong localContentId) public static CharacterConfiguration? Load(DalamudPluginInterface pluginInterface, ulong localContentId)
{ {
string path = ResolveFilePath(pluginInterface, localContentId); string path = ResolveFilePath(pluginInterface, localContentId);
if (!File.Exists(path)) if (!File.Exists(path))
@ -29,11 +29,11 @@ internal sealed class CharacterConfiguration
return JsonConvert.DeserializeObject<CharacterConfiguration>(File.ReadAllText(path)); return JsonConvert.DeserializeObject<CharacterConfiguration>(File.ReadAllText(path));
} }
public void Save(IDalamudPluginInterface pluginInterface) public void Save(DalamudPluginInterface pluginInterface)
{ {
File.WriteAllText(ResolveFilePath(pluginInterface, LocalContentId), JsonConvert.SerializeObject(this, Formatting.Indented)); File.WriteAllText(ResolveFilePath(pluginInterface, LocalContentId), JsonConvert.SerializeObject(this, Formatting.Indented));
} }
public void Delete(IDalamudPluginInterface pluginInterface) => public void Delete(DalamudPluginInterface pluginInterface) =>
File.Delete(ResolveFilePath(pluginInterface, LocalContentId)); File.Delete(ResolveFilePath(pluginInterface, LocalContentId));
} }

View File

@ -1,6 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Dalamud.Configuration; using Dalamud.Configuration;
using Dalamud.Game.ClientState.Keys; using Dalamud.Game.ClientState.Keys;
using Dalamud.Game.Text; using Dalamud.Game.Text;
@ -11,13 +9,10 @@ namespace Deliveroo;
internal sealed class Configuration : IPluginConfiguration internal sealed class Configuration : IPluginConfiguration
{ {
public int Version { get; set; } = 2; public int Version { get; set; } = 1;
[Obsolete] public List<uint> ItemsAvailableForPurchase { get; set; } = new();
public List<uint> ItemsAvailableForPurchase { get; set; } = []; public List<PurchasePriority> ItemsToPurchase { get; set; } = new();
public List<PurchaseOption> ItemsAvailableToPurchase { get; set; } = [];
public List<PurchasePriority> ItemsToPurchase { get; set; } = [];
public int ReservedSealCount { get; set; } public int ReservedSealCount { get; set; }
public bool ReserveDifferentSealCountAtMaxRank { get; set; } public bool ReserveDifferentSealCountAtMaxRank { get; set; }
@ -29,21 +24,11 @@ internal sealed class Configuration : IPluginConfiguration
public bool UncapFrameRate { get; set; } public bool UncapFrameRate { get; set; }
public VirtualKey QuickTurnInKey { get; set; } = VirtualKey.SHIFT; public VirtualKey QuickTurnInKey { get; set; } = VirtualKey.SHIFT;
public MinimizableWindowConfig TurnInWindowConfig { get; } = new(); public WindowConfig TurnInWindowConfig { get; } = new();
public WindowConfig ConfigWindowConfig { get; } = new(); public WindowConfig ConfigWindowConfig { get; } = new();
internal sealed class PurchaseOption
{
public uint ItemId { get; set; }
public bool SameQuantityForAllLists { get; set; }
public int GlobalLimit { get; set; }
}
internal sealed class PurchasePriority internal sealed class PurchasePriority
{ {
[JsonIgnore]
public Guid InternalId { get; } = Guid.NewGuid();
public uint ItemId { get; set; } public uint ItemId { get; set; }
public int Limit { get; set; } public int Limit { get; set; }
public bool Enabled { get; set; } = true; public bool Enabled { get; set; } = true;
@ -69,9 +54,9 @@ internal sealed class Configuration : IPluginConfiguration
public bool AddVentureIfNoItemToPurchaseSelected() public bool AddVentureIfNoItemToPurchaseSelected()
{ {
if (ItemsAvailableToPurchase.Count == 0) if (ItemsAvailableForPurchase.Count == 0)
{ {
ItemsAvailableToPurchase.Add(new PurchaseOption { ItemId = ItemIds.Venture }); ItemsAvailableForPurchase.Add(ItemIds.Venture);
return true; return true;
} }
@ -84,9 +69,4 @@ internal sealed class Configuration : IPluginConfiguration
Warning, Warning,
DisableTurnIn, DisableTurnIn,
} }
internal sealed class MinimizableWindowConfig : WindowConfig
{
public bool IsMinimized { get; set; }
}
} }

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project> <Project>
<Target Name="PackagePluginDebug" AfterTargets="Build" Condition="'$(Configuration)' == 'Debug'"> <Target Name="PackagePlugin" AfterTargets="Build" Condition="'$(Configuration)' == 'Debug'">
<DalamudPackager <DalamudPackager
ProjectDir="$(ProjectDir)" ProjectDir="$(ProjectDir)"
OutputPath="$(OutputPath)" OutputPath="$(OutputPath)"

View File

@ -1,13 +1,63 @@
<Project Sdk="Dalamud.NET.Sdk/11.0.0"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Version>6.3</Version> <TargetFramework>net8.0-windows</TargetFramework>
<Version>4.10</Version>
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<OutputPath>dist</OutputPath> <OutputPath>dist</OutputPath>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<DebugType>portable</DebugType>
<PathMap Condition="$(SolutionDir) != ''">$(SolutionDir)=X:\</PathMap>
</PropertyGroup> </PropertyGroup>
<Import Project="..\LLib\LLib.targets"/> <PropertyGroup>
<Import Project="..\LLib\RenameZip.targets"/> <DalamudLibPath>$(appdata)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
</PropertyGroup>
<PropertyGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))'">
<DalamudLibPath>$(DALAMUD_HOME)/</DalamudLibPath>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\LLib\LLib.csproj" /> <ProjectReference Include="..\LLib\LLib.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="DalamudPackager" Version="2.1.12"/>
</ItemGroup>
<ItemGroup>
<Reference Include="Dalamud">
<HintPath>$(DalamudLibPath)Dalamud.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="ImGui.NET">
<HintPath>$(DalamudLibPath)ImGui.NET.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Lumina">
<HintPath>$(DalamudLibPath)Lumina.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Lumina.Excel">
<HintPath>$(DalamudLibPath)Lumina.Excel.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>$(DalamudLibPath)Newtonsoft.Json.dll</HintPath>
<Private>false</Private>
</Reference>
<Reference Include="FFXIVClientStructs">
<HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath>
<Private>false</Private>
</Reference>
</ItemGroup>
<Target Name="RenameLatestZip" AfterTargets="PackagePlugin">
<Exec Command="rename $(OutDir)$(AssemblyName)\latest.zip $(AssemblyName)-$(Version).zip"/>
</Target>
</Project> </Project>

View File

@ -2,7 +2,6 @@
using System.Linq; using System.Linq;
using Dalamud.Game.Addon.Lifecycle; using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
using Dalamud.Game.ClientState.Keys;
using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling;
using Deliveroo.GameData; using Deliveroo.GameData;
using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Client.UI;
@ -14,7 +13,7 @@ partial class DeliverooPlugin
{ {
private unsafe void GrandCompanySupplyRewardPostSetup(AddonEvent type, AddonArgs args) private unsafe void GrandCompanySupplyRewardPostSetup(AddonEvent type, AddonArgs args)
{ {
bool quickTurnIn = CurrentStage == Stage.Stopped && _configuration.QuickTurnInKey != VirtualKey.NO_KEY && _keyState[_configuration.QuickTurnInKey]; bool quickTurnIn = CurrentStage == Stage.Stopped && _keyState[_configuration.QuickTurnInKey];
if (CurrentStage == Stage.TurnInSelected || quickTurnIn) if (CurrentStage == Stage.TurnInSelected || quickTurnIn)
{ {
AddonGrandCompanySupplyReward* addonSupplyReward = (AddonGrandCompanySupplyReward*)args.Addon; AddonGrandCompanySupplyReward* addonSupplyReward = (AddonGrandCompanySupplyReward*)args.Addon;

View File

@ -1,7 +1,6 @@
using System; using System;
using Dalamud.Game.Addon.Lifecycle; using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
using Dalamud.Game.ClientState.Keys;
using Dalamud.Memory; using Dalamud.Memory;
using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Client.UI;
@ -41,7 +40,7 @@ partial class DeliverooPlugin
CurrentStage = Stage.CloseGcExchange; CurrentStage = Stage.CloseGcExchange;
ContinueAt = DateTime.Now.AddSeconds(0.5); ContinueAt = DateTime.Now.AddSeconds(0.5);
} }
else if ((CurrentStage == Stage.TurnInSelected || (_configuration.QuickTurnInKey != VirtualKey.NO_KEY && _keyState[_configuration.QuickTurnInKey])) && else if ((CurrentStage == Stage.TurnInSelected || _keyState[_configuration.QuickTurnInKey]) &&
_gameStrings.TradeHighQualityItem == text) _gameStrings.TradeHighQualityItem == text)
{ {
_pluginLog.Information($"Selecting 'yes' ({text})"); _pluginLog.Information($"Selecting 'yes' ({text})");

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Dalamud.Game.Addon.Lifecycle; using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects;
@ -26,7 +25,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
{ {
private readonly WindowSystem _windowSystem = new(typeof(DeliverooPlugin).AssemblyQualifiedName); private readonly WindowSystem _windowSystem = new(typeof(DeliverooPlugin).AssemblyQualifiedName);
private readonly IDalamudPluginInterface _pluginInterface; private readonly DalamudPluginInterface _pluginInterface;
private readonly IChatGui _chatGui; private readonly IChatGui _chatGui;
private readonly IGameGui _gameGui; private readonly IGameGui _gameGui;
private readonly IFramework _framework; private readonly IFramework _framework;
@ -56,7 +55,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
private Stage _currentStageInternal = Stage.Stopped; private Stage _currentStageInternal = Stage.Stopped;
public DeliverooPlugin(IDalamudPluginInterface pluginInterface, IChatGui chatGui, IGameGui gameGui, public DeliverooPlugin(DalamudPluginInterface pluginInterface, IChatGui chatGui, IGameGui gameGui,
IFramework framework, IClientState clientState, IObjectTable objectTable, ITargetManager targetManager, IFramework framework, IClientState clientState, IObjectTable objectTable, ITargetManager targetManager,
IDataManager dataManager, ICondition condition, ICommandManager commandManager, IPluginLog pluginLog, IDataManager dataManager, ICondition condition, ICommandManager commandManager, IPluginLog pluginLog,
IAddonLifecycle addonLifecycle, ITextureProvider textureProvider, IGameConfig gameConfig, IKeyState keyState) IAddonLifecycle addonLifecycle, ITextureProvider textureProvider, IGameConfig gameConfig, IKeyState keyState)
@ -75,8 +74,6 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
_keyState = keyState; _keyState = keyState;
_configuration = (Configuration?)_pluginInterface.GetPluginConfig() ?? new Configuration(); _configuration = (Configuration?)_pluginInterface.GetPluginConfig() ?? new Configuration();
MigrateConfiguration();
_gameStrings = new GameStrings(dataManager, _pluginLog); _gameStrings = new GameStrings(dataManager, _pluginLog);
_externalPluginHandler = new ExternalPluginHandler(_pluginInterface, gameConfig, _configuration, _pluginLog); _externalPluginHandler = new ExternalPluginHandler(_pluginInterface, gameConfig, _configuration, _pluginLog);
_gameFunctions = new GameFunctions(objectTable, _clientState, targetManager, dataManager, _gameFunctions = new GameFunctions(objectTable, _clientState, targetManager, dataManager,
@ -92,7 +89,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
_pluginLog, _iconCache, _gameFunctions); _pluginLog, _iconCache, _gameFunctions);
_windowSystem.AddWindow(_configWindow); _windowSystem.AddWindow(_configWindow);
_turnInWindow = new TurnInWindow(this, _pluginInterface, _configuration, _condition, _clientState, _turnInWindow = new TurnInWindow(this, _pluginInterface, _configuration, _condition, _clientState,
_gcRewardsCache, _configWindow, _iconCache, _keyState, _gameFunctions); _gcRewardsCache, _configWindow, _iconCache, _keyState, _gameGui, _gameFunctions);
_windowSystem.AddWindow(_turnInWindow); _windowSystem.AddWindow(_turnInWindow);
_framework.Update += FrameworkUpdate; _framework.Update += FrameworkUpdate;
@ -117,24 +114,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "GrandCompanySupplyReward", GrandCompanySupplyRewardPostSetup); _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "GrandCompanySupplyReward", GrandCompanySupplyRewardPostSetup);
} }
private void MigrateConfiguration() private void ChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message,
{
#pragma warning disable CS0612 // Type or member is obsolete
if (_configuration.Version == 1)
{
_configuration.ItemsAvailableToPurchase = _configuration.ItemsAvailableForPurchase.Select(x =>
new Configuration.PurchaseOption
{
ItemId = x,
SameQuantityForAllLists = false,
}).ToList();
_configuration.Version = 2;
_pluginInterface.SavePluginConfig(_configuration);
}
#pragma warning restore CS0612 // Type or member is obsolete
}
private void ChatMessage(XivChatType type, int timestamp, ref SeString sender, ref SeString message,
ref bool isHandled) ref bool isHandled)
{ {
if (_configuration.PauseAtRank <= 0) if (_configuration.PauseAtRank <= 0)
@ -218,11 +198,11 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
{ {
if (CharacterConfiguration.CachedPlayerName != _clientState.LocalPlayer!.Name.ToString() || if (CharacterConfiguration.CachedPlayerName != _clientState.LocalPlayer!.Name.ToString() ||
CharacterConfiguration.CachedWorldName != CharacterConfiguration.CachedWorldName !=
_clientState.LocalPlayer.HomeWorld.Value.Name.ToString()) _clientState.LocalPlayer.HomeWorld.GameData!.Name.ToString())
{ {
CharacterConfiguration.CachedPlayerName = _clientState.LocalPlayer!.Name.ToString(); CharacterConfiguration.CachedPlayerName = _clientState.LocalPlayer!.Name.ToString();
CharacterConfiguration.CachedWorldName = CharacterConfiguration.CachedWorldName =
_clientState.LocalPlayer.HomeWorld.Value.Name.ToString(); _clientState.LocalPlayer.HomeWorld.GameData!.Name.ToString();
CharacterConfiguration.Save(_pluginInterface); CharacterConfiguration.Save(_pluginInterface);
} }
@ -242,7 +222,7 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
} }
} }
private void Logout(int type, int code) private void Logout()
{ {
CharacterConfiguration = null; CharacterConfiguration = null;
} }
@ -253,8 +233,8 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
if (!_clientState.IsLoggedIn || if (!_clientState.IsLoggedIn ||
_clientState.TerritoryType is not 128 and not 130 and not 132 || _clientState.TerritoryType is not 128 and not 130 and not 132 ||
_condition[ConditionFlag.OccupiedInCutSceneEvent] || _condition[ConditionFlag.OccupiedInCutSceneEvent] ||
_gameFunctions.GetDistanceToNpc(_gameFunctions.GetQuartermasterId(), out IGameObject? quartermaster) >= 7f || _gameFunctions.GetDistanceToNpc(_gameFunctions.GetQuartermasterId(), out GameObject? quartermaster) >= 7f ||
_gameFunctions.GetDistanceToNpc(_gameFunctions.GetPersonnelOfficerId(), out IGameObject? personnelOfficer) >= _gameFunctions.GetDistanceToNpc(_gameFunctions.GetPersonnelOfficerId(), out GameObject? personnelOfficer) >=
7f || 7f ||
CharacterConfiguration is { DisableForCharacter: true } || CharacterConfiguration is { DisableForCharacter: true } ||
_configWindow.IsOpen) _configWindow.IsOpen)

View File

@ -25,7 +25,7 @@ internal sealed class AllaganToolsIpc
private readonly ICallGateSubscriber<uint, bool, uint[], uint> _itemCountOwned; private readonly ICallGateSubscriber<uint, bool, uint[], uint> _itemCountOwned;
public AllaganToolsIpc(IDalamudPluginInterface pluginInterface, IPluginLog pluginLog) public AllaganToolsIpc(DalamudPluginInterface pluginInterface, IPluginLog pluginLog)
{ {
_pluginLog = pluginLog; _pluginLog = pluginLog;
_itemCountOwned = pluginInterface.GetIpcSubscriber<uint, bool, uint[], uint>("AllaganTools.ItemCountOwned"); _itemCountOwned = pluginInterface.GetIpcSubscriber<uint, bool, uint[], uint>("AllaganTools.ItemCountOwned");

View File

@ -16,7 +16,7 @@ internal sealed class DeliverooIpc : IDisposable
private bool _running; private bool _running;
public DeliverooIpc(IDalamudPluginInterface pluginInterface) public DeliverooIpc(DalamudPluginInterface pluginInterface)
{ {
_isTurnInRunning = pluginInterface.GetIpcProvider<bool>(IsTurnInRunning); _isTurnInRunning = pluginInterface.GetIpcProvider<bool>(IsTurnInRunning);
_turnInStarted = pluginInterface.GetIpcProvider<object>(TurnInStarted); _turnInStarted = pluginInterface.GetIpcProvider<object>(TurnInStarted);

View File

@ -7,7 +7,7 @@ namespace Deliveroo.External;
internal sealed class ExternalPluginHandler : IDisposable internal sealed class ExternalPluginHandler : IDisposable
{ {
private readonly IDalamudPluginInterface _pluginInterface; private readonly DalamudPluginInterface _pluginInterface;
private readonly IGameConfig _gameConfig; private readonly IGameConfig _gameConfig;
private readonly Configuration _configuration; private readonly Configuration _configuration;
private readonly IPluginLog _pluginLog; private readonly IPluginLog _pluginLog;
@ -19,7 +19,7 @@ internal sealed class ExternalPluginHandler : IDisposable
private SystemConfigState? _limitFrameRateWhenClientInactive; private SystemConfigState? _limitFrameRateWhenClientInactive;
private SystemConfigState? _uncapFrameRate; private SystemConfigState? _uncapFrameRate;
public ExternalPluginHandler(IDalamudPluginInterface pluginInterface, IGameConfig gameConfig, public ExternalPluginHandler(DalamudPluginInterface pluginInterface, IGameConfig gameConfig,
Configuration configuration, IPluginLog pluginLog) Configuration configuration, IPluginLog pluginLog)
{ {
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;

View File

@ -13,7 +13,7 @@ internal sealed class PandoraIpc
private readonly ICallGateSubscriber<string, bool?> _getEnabled; private readonly ICallGateSubscriber<string, bool?> _getEnabled;
private readonly ICallGateSubscriber<string, bool, object?> _setEnabled; private readonly ICallGateSubscriber<string, bool, object?> _setEnabled;
public PandoraIpc(IDalamudPluginInterface pluginInterface, IPluginLog pluginLog) public PandoraIpc(DalamudPluginInterface pluginInterface, IPluginLog pluginLog)
{ {
_pluginLog = pluginLog; _pluginLog = pluginLog;
_getEnabled = pluginInterface.GetIpcSubscriber<string, bool?>("PandorasBox.GetFeatureEnabled"); _getEnabled = pluginInterface.GetIpcSubscriber<string, bool?>("PandorasBox.GetFeatureEnabled");

View File

@ -1,12 +1,13 @@
using System.Data; using System;
using System.Data;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Dalamud.Game.Text; using Dalamud.Game.Text;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using LLib; using LLib;
using Lumina.Excel; using Lumina.Excel;
using Lumina.Excel.Sheets; using Lumina.Excel.CustomSheets;
using Lumina.Text.ReadOnly; using Lumina.Excel.GeneratedSheets;
namespace Deliveroo.GameData; namespace Deliveroo.GameData;
@ -23,10 +24,10 @@ internal sealed class GameStrings
ExchangeItems = dataManager.GetRegex<Addon>(3290, addon => addon.Text, pluginLog) ExchangeItems = dataManager.GetRegex<Addon>(3290, addon => addon.Text, pluginLog)
?? throw new ConstraintException($"Unable to resolve {nameof(ExchangeItems)}"); ?? throw new ConstraintException($"Unable to resolve {nameof(ExchangeItems)}");
TradeHighQualityItem = TradeHighQualityItem =
dataManager.GetString<Addon>(102434, addon => addon.Text, pluginLog) dataManager.GetString<Addon>(102434, addon => addon.Text, pluginLog)?.ReplaceLineEndings("")
?? throw new ConstraintException($"Unable to resolve {nameof(TradeHighQualityItem)}"); ?? throw new ConstraintException($"Unable to resolve {nameof(TradeHighQualityItem)}");
var rankUpFc = dataManager.GetExcelSheet<LogMessage>().GetRow(3123); var rankUpFc = dataManager.GetExcelSheet<LogMessage>()!.GetRow(3123)!;
RankUpFc = rankUpFc.GetRegex(logMessage => logMessage.Text, pluginLog) RankUpFc = rankUpFc.GetRegex(logMessage => logMessage.Text, pluginLog)
?? throw new ConstraintException($"Unable to resolve {nameof(RankUpFc)}"); ?? throw new ConstraintException($"Unable to resolve {nameof(RankUpFc)}");
RankUpFcType = (XivChatType)rankUpFc.LogKind; RankUpFcType = (XivChatType)rankUpFc.LogKind;
@ -42,16 +43,7 @@ internal sealed class GameStrings
[Sheet("custom/000/ComDefGrandCompanyOfficer_00073")] [Sheet("custom/000/ComDefGrandCompanyOfficer_00073")]
[SuppressMessage("Performance", "CA1812")] [SuppressMessage("Performance", "CA1812")]
private readonly struct ComDefGrandCompanyOfficer(ExcelPage page, uint offset, uint row) private sealed class ComDefGrandCompanyOfficer : QuestDialogueText
: IQuestDialogueText, IExcelRow<ComDefGrandCompanyOfficer>
{ {
public uint RowId => row;
public ReadOnlySeString Key => page.ReadString(offset, offset);
public ReadOnlySeString Value => page.ReadString(offset + 4, offset);
static ComDefGrandCompanyOfficer IExcelRow<ComDefGrandCompanyOfficer>.Create(ExcelPage page, uint offset,
uint row) =>
new(page, offset, row);
} }
} }

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Lumina.Excel.Sheets; using Lumina.Excel.GeneratedSheets;
using GrandCompany = FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany; using GrandCompany = FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany;
namespace Deliveroo.GameData; namespace Deliveroo.GameData;
@ -10,32 +10,31 @@ internal sealed class GcRewardsCache
{ {
public GcRewardsCache(IDataManager dataManager) public GcRewardsCache(IDataManager dataManager)
{ {
var categories = dataManager.GetExcelSheet<GCScripShopCategory>() var categories = dataManager.GetExcelSheet<GCScripShopCategory>()!
.Where(x => x.RowId > 0) .Where(x => x.RowId > 0)
.ToDictionary(x => x.RowId, .ToDictionary(x => x.RowId,
x => x =>
(GrandCompany: (GrandCompany)x.GrandCompany.RowId, (GrandCompany: (GrandCompany)x.GrandCompany.Row,
Tier: (RewardTier)x.Tier, Tier: (RewardTier)x.Tier,
SubCategory: (RewardSubCategory)x.SubCategory)); SubCategory: (RewardSubCategory)x.SubCategory));
Rewards = dataManager.GetSubrowExcelSheet<GCScripShopItem>() Rewards = dataManager.GetExcelSheet<GCScripShopItem>()!
.SelectMany(x => x) .Where(x => x.RowId > 0 && x.Item.Row > 0)
.Where(x => x.RowId > 0 && x.Item.RowId > 0)
.GroupBy(item => .GroupBy(item =>
{ {
var category = categories[item.RowId]; var category = categories[item.RowId];
return new return new
{ {
ItemId = item.Item.RowId, ItemId = item.Item.Row,
Name = item.Item.Value.Name.ToString(), Name = item.Item.Value!.Name.ToString(),
IconId = item.Item.RowId == ItemIds.Venture ? 25917 : item.Item.Value.Icon, IconId = item.Item.Row == ItemIds.Venture ? 25917 : item.Item.Value!.Icon,
category.Tier, category.Tier,
category.SubCategory, category.SubCategory,
RequiredRank = item.RequiredGrandCompanyRank.RowId, RequiredRank = item.RequiredGrandCompanyRank.Row,
item.Item.Value.StackSize, item.Item!.Value.StackSize,
SealCost = item.CostGCSeals, SealCost = item.CostGCSeals,
InventoryLimit = item.Item.Value.IsUnique ? 1 InventoryLimit = item.Item.Value!.IsUnique ? 1
: item.Item.RowId == ItemIds.Venture ? item.Item.Value.StackSize : item.Item.Row == ItemIds.Venture ? item.Item.Value!.StackSize
: int.MaxValue, : int.MaxValue,
}; };
}) })

View File

@ -1,6 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Lumina.Excel.Sheets; using Lumina.Excel.GeneratedSheets;
namespace Deliveroo.GameData; namespace Deliveroo.GameData;
@ -10,7 +10,7 @@ internal sealed class ItemCache
public ItemCache(IDataManager dataManager) public ItemCache(IDataManager dataManager)
{ {
foreach (var item in dataManager.GetExcelSheet<Item>()) foreach (var item in dataManager.GetExcelSheet<Item>()!)
{ {
string name = item.Name.ToString(); string name = item.Name.ToString();
if (string.IsNullOrWhiteSpace(name)) if (string.IsNullOrWhiteSpace(name))
@ -19,10 +19,9 @@ internal sealed class ItemCache
if (_itemNamesToIds.TryGetValue(name, out HashSet<uint>? itemIds)) if (_itemNamesToIds.TryGetValue(name, out HashSet<uint>? itemIds))
itemIds.Add(item.RowId); itemIds.Add(item.RowId);
else else
_itemNamesToIds.Add(name, [item.RowId]); _itemNamesToIds.Add(name, new HashSet<uint>{item.RowId});
} }
} }
public HashSet<uint> GetItemIdFromItemName(string name) => public HashSet<uint> GetItemIdFromItemName(string name) => _itemNamesToIds[name];
_itemNamesToIds.TryGetValue(name, out var itemIds) ? itemIds : [];
} }

View File

@ -15,10 +15,8 @@ using FFXIVClientStructs.FFXIV.Client.Game.Control;
using FFXIVClientStructs.FFXIV.Client.Game.UI; using FFXIVClientStructs.FFXIV.Client.Game.UI;
using FFXIVClientStructs.FFXIV.Client.UI.Agent; using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Common.Math; using FFXIVClientStructs.FFXIV.Common.Math;
using FFXIVClientStructs.FFXIV.Component.Excel;
using Lumina.Excel; using Lumina.Excel;
using Lumina.Excel.Sheets; using Lumina.Excel.GeneratedSheets;
using Lumina.Text.ReadOnly;
using GrandCompany = FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany; using GrandCompany = FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany;
namespace Deliveroo; namespace Deliveroo;
@ -43,7 +41,7 @@ internal sealed class GameFunctions : IDisposable
_pluginLog = pluginLog; _pluginLog = pluginLog;
_gcRankInfo = dataManager.GetExcelSheet<GrandCompanyRank>().Where(x => x.RowId > 0) _gcRankInfo = dataManager.GetExcelSheet<GrandCompanyRank>()!.Where(x => x.RowId > 0)
.ToDictionary(x => x.RowId, x => new GcRankInfo .ToDictionary(x => x.RowId, x => new GcRankInfo
{ {
NameTwinAddersMale = ExtractRankName<GCRankGridaniaMaleText>(dataManager, x.RowId, r => r.Singular), NameTwinAddersMale = ExtractRankName<GCRankGridaniaMaleText>(dataManager, x.RowId, r => r.Singular),
@ -55,7 +53,7 @@ internal sealed class GameFunctions : IDisposable
ExtractRankName<GCRankUldahFemaleText>(dataManager, x.RowId, r => r.Singular), ExtractRankName<GCRankUldahFemaleText>(dataManager, x.RowId, r => r.Singular),
MaxSeals = x.MaxSeals, MaxSeals = x.MaxSeals,
RequiredSeals = x.RequiredSeals, RequiredSeals = x.RequiredSeals,
RequiredHuntingLog = x.Unknown0, RequiredHuntingLog = x.Unknown10,
}) })
.AsReadOnly(); .AsReadOnly();
@ -63,14 +61,14 @@ internal sealed class GameFunctions : IDisposable
_clientState.TerritoryChanged += TerritoryChanged; _clientState.TerritoryChanged += TerritoryChanged;
} }
private static string ExtractRankName<T>(IDataManager dataManager, uint rankId, Func<T, ReadOnlySeString> func) private static string ExtractRankName<T>(IDataManager dataManager, uint rankId, Func<T, Lumina.Text.SeString> func)
where T : struct, IExcelRow<T> where T : ExcelRow
{ {
return func(dataManager.GetExcelSheet<T>().GetRow(rankId)).ToString(); return func(dataManager.GetExcelSheet<T>()!.GetRow(rankId)!).ToString();
} }
private void Logout(int type, int code) private void Logout()
{ {
_retainerItemCache.Clear(); _retainerItemCache.Clear();
} }
@ -81,10 +79,10 @@ internal sealed class GameFunctions : IDisposable
_retainerItemCache.Clear(); _retainerItemCache.Clear();
} }
public unsafe void InteractWithTarget(IGameObject obj) public unsafe void InteractWithTarget(GameObject obj)
{ {
_pluginLog.Information($"Setting target to {obj}"); _pluginLog.Information($"Setting target to {obj}");
if (_targetManager.Target == null || _targetManager.Target.EntityId != obj.EntityId) if (_targetManager.Target == null || _targetManager.Target != obj)
{ {
_targetManager.Target = obj; _targetManager.Target = obj;
} }
@ -113,13 +111,13 @@ internal sealed class GameFunctions : IDisposable
public unsafe byte GetGrandCompanyRank() => PlayerState.Instance()->GetGrandCompanyRank(); public unsafe byte GetGrandCompanyRank() => PlayerState.Instance()->GetGrandCompanyRank();
public float GetDistanceToNpc(int npcId, out IGameObject? o) public float GetDistanceToNpc(int npcId, out GameObject? o)
{ {
foreach (var obj in _objectTable) foreach (var obj in _objectTable)
{ {
if (obj.ObjectKind == ObjectKind.EventNpc && obj is ICharacter c) if (obj.ObjectKind == ObjectKind.EventNpc && obj is Character c)
{ {
if (c.DataId == npcId) if (GetNpcId(obj) == npcId)
{ {
o = obj; o = obj;
return Vector3.Distance(_clientState.LocalPlayer?.Position ?? Vector3.Zero, c.Position); return Vector3.Distance(_clientState.LocalPlayer?.Position ?? Vector3.Zero, c.Position);
@ -131,7 +129,7 @@ internal sealed class GameFunctions : IDisposable
return float.MaxValue; return float.MaxValue;
} }
public static int GetNpcId(IGameObject obj) public static int GetNpcId(GameObject obj)
{ {
return Marshal.ReadInt32(obj.Address + 128); return Marshal.ReadInt32(obj.Address + 128);
} }

View File

@ -31,7 +31,7 @@ internal sealed class ExchangeHandler
_pluginLog = pluginLog; _pluginLog = pluginLog;
} }
public void InteractWithQuartermaster(IGameObject personnelOfficer, IGameObject quartermaster) public void InteractWithQuartermaster(GameObject personnelOfficer, GameObject quartermaster)
{ {
if (_gameFunctions.GetCurrentSealCount() < _plugin.EffectiveReservedSealCount) if (_gameFunctions.GetCurrentSealCount() < _plugin.EffectiveReservedSealCount)
{ {

View File

@ -32,9 +32,9 @@ internal sealed class SupplyHandler
_pluginLog = pluginLog; _pluginLog = pluginLog;
} }
public void InteractWithPersonnelOfficer(IGameObject personnelOfficer, IGameObject quartermaster) public void InteractWithPersonnelOfficer(GameObject personnelOfficer, GameObject quartermaster)
{ {
if (_targetManager.Target?.EntityId == quartermaster.EntityId) if (_targetManager.Target == quartermaster)
return; return;
_gameFunctions.InteractWithTarget(personnelOfficer); _gameFunctions.InteractWithTarget(personnelOfficer);
@ -46,7 +46,7 @@ internal sealed class SupplyHandler
var agentInterface = AgentModule.Instance()->GetAgentByInternalId(AgentId.GrandCompanySupply); var agentInterface = AgentModule.Instance()->GetAgentByInternalId(AgentId.GrandCompanySupply);
if (agentInterface != null && agentInterface->IsAgentActive()) if (agentInterface != null && agentInterface->IsAgentActive())
{ {
var addonId = agentInterface->GetAddonId(); var addonId = agentInterface->GetAddonID();
if (addonId == 0) if (addonId == 0)
return; return;
@ -89,7 +89,7 @@ internal sealed class SupplyHandler
var agentInterface = AgentModule.Instance()->GetAgentByInternalId(AgentId.GrandCompanySupply); var agentInterface = AgentModule.Instance()->GetAgentByInternalId(AgentId.GrandCompanySupply);
if (agentInterface != null && agentInterface->IsAgentActive()) if (agentInterface != null && agentInterface->IsAgentActive())
{ {
var addonId = agentInterface->GetAddonId(); var addonId = agentInterface->GetAddonID();
if (addonId == 0) if (addonId == 0)
return; return;
@ -99,7 +99,7 @@ internal sealed class SupplyHandler
var addonGc = (AddonGrandCompanySupplyList*)addon; var addonGc = (AddonGrandCompanySupplyList*)addon;
if (addonGc->ExpertDeliveryList == null || if (addonGc->ExpertDeliveryList == null ||
!addonGc->ExpertDeliveryList->AtkComponentBase.OwnerNode->AtkResNode.IsVisible()) !addonGc->ExpertDeliveryList->AtkComponentBase.OwnerNode->AtkResNode.IsVisible)
return; return;
if (addonGc->SelectedTab != 2) if (addonGc->SelectedTab != 2)
@ -117,7 +117,7 @@ internal sealed class SupplyHandler
} }
int currentListSize = addonGc->ExpertDeliveryList->ListLength; int currentListSize = addonGc->ExpertDeliveryList->ListLength;
if (addonGc->ListEmptyTextNode->AtkResNode.IsVisible() || currentListSize == 0) if (addonGc->ListEmptyTextNode->AtkResNode.IsVisible || currentListSize == 0)
{ {
_pluginLog.Information( _pluginLog.Information(
$"No items to turn in ({addonGc->ListEmptyTextNode->AtkResNode.IsVisible}, {currentListSize})"); $"No items to turn in ({addonGc->ListEmptyTextNode->AtkResNode.IsVisible}, {currentListSize})");
@ -226,7 +226,7 @@ internal sealed class SupplyHandler
var agentInterface = AgentModule.Instance()->GetAgentByInternalId(AgentId.GrandCompanySupply); var agentInterface = AgentModule.Instance()->GetAgentByInternalId(AgentId.GrandCompanySupply);
if (agentInterface != null && agentInterface->IsAgentActive()) if (agentInterface != null && agentInterface->IsAgentActive())
{ {
var addonId = agentInterface->GetAddonId(); var addonId = agentInterface->GetAddonID();
if (addonId == 0) if (addonId == 0)
return; return;

View File

@ -6,7 +6,7 @@ using Dalamud.Game.ClientState.Keys;
using Dalamud.Game.Text; using Dalamud.Game.Text;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Components; using Dalamud.Interface.Components;
using Dalamud.Interface.Textures.TextureWraps; using Dalamud.Interface.Internal;
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using Dalamud.Plugin; using Dalamud.Plugin;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
@ -20,7 +20,7 @@ namespace Deliveroo.Windows;
internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
{ {
private readonly IDalamudPluginInterface _pluginInterface; private readonly DalamudPluginInterface _pluginInterface;
private readonly DeliverooPlugin _plugin; private readonly DeliverooPlugin _plugin;
private readonly Configuration _configuration; private readonly Configuration _configuration;
private readonly GcRewardsCache _gcRewardsCache; private readonly GcRewardsCache _gcRewardsCache;
@ -40,9 +40,9 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
]; ];
private string _searchString = string.Empty; private string _searchString = string.Empty;
private Configuration.PurchaseOption? _dragDropSource; private uint _dragDropSource;
public ConfigWindow(IDalamudPluginInterface pluginInterface, DeliverooPlugin plugin, Configuration configuration, public ConfigWindow(DalamudPluginInterface pluginInterface, DeliverooPlugin plugin, Configuration configuration,
GcRewardsCache gcRewardsCache, IClientState clientState, IPluginLog pluginLog, IconCache iconCache, GcRewardsCache gcRewardsCache, IClientState clientState, IPluginLog pluginLog, IconCache iconCache,
GameFunctions gameFunctions) GameFunctions gameFunctions)
: base("Deliveroo - Configuration###DeliverooConfig") : base("Deliveroo - Configuration###DeliverooConfig")
@ -89,52 +89,56 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
{ {
if (ImGui.BeginTabItem("Items for Auto-Buy")) if (ImGui.BeginTabItem("Items for Auto-Buy"))
{ {
Configuration.PurchaseOption? itemToRemove = null; uint? itemToRemove = null;
Configuration.PurchaseOption? itemToAdd = null; uint? itemToAdd = null;
int indexToAdd = 0; int indexToAdd = 0;
if (ImGui.BeginChild("Items", new Vector2(-1, -ImGui.GetFrameHeightWithSpacing()), true, if (ImGui.BeginChild("Items", new Vector2(-1, -ImGui.GetFrameHeightWithSpacing()), true,
ImGuiWindowFlags.NoSavedSettings)) ImGuiWindowFlags.NoSavedSettings))
{ {
for (int i = 0; i < _configuration.ItemsAvailableToPurchase.Count; ++i) for (int i = 0; i < _configuration.ItemsAvailableForPurchase.Count; ++i)
{ {
var purchaseOption = _configuration.ItemsAvailableToPurchase[i]; uint itemId = _configuration.ItemsAvailableForPurchase[i];
ImGui.PushID($"###Item{i}"); ImGui.PushID($"###Item{i}");
ImGui.BeginDisabled( ImGui.BeginDisabled(
_configuration.ItemsAvailableToPurchase.Count == 1 && purchaseOption.ItemId == ItemIds.Venture); _configuration.ItemsAvailableForPurchase.Count == 1 && itemId == ItemIds.Venture);
var item = _itemLookup[purchaseOption.ItemId]; var item = _itemLookup[itemId];
using (var icon = _iconCache.GetIcon(item.IconId)) IDalamudTextureWrap? icon = _iconCache.GetIcon(item.IconId);
{
Vector2 pos = ImGui.GetCursorPos(); Vector2 pos = ImGui.GetCursorPos();
Vector2 iconSize = new Vector2(ImGui.GetTextLineHeight() + ImGui.GetStyle().ItemSpacing.Y); Vector2 iconSize = new Vector2(ImGui.GetTextLineHeight() + ImGui.GetStyle().ItemSpacing.Y);
if (icon != null) if (icon != null)
{ {
ImGui.SetCursorPos(pos + new Vector2(iconSize.X + ImGui.GetStyle().FramePadding.X, ImGui.SetCursorPos(pos + new Vector2(iconSize.X + ImGui.GetStyle().FramePadding.X,
ImGui.GetStyle().ItemSpacing.Y / 2)); ImGui.GetStyle().ItemSpacing.Y / 2));
} }
ImGui.Selectable( ImGui.Selectable($"{item.Name}{(item.Limited ? $" {SeIconChar.Hyadelyn.ToIconString()}" : "")}",
$"{item.Name}{(item.Limited ? $" {SeIconChar.Hyadelyn.ToIconString()}" : "")}{(purchaseOption.SameQuantityForAllLists ? $" {((SeIconChar)57412).ToIconString()} (Limit: {purchaseOption.GlobalLimit:N0})" : "")}",
false, ImGuiSelectableFlags.SpanAllColumns); false, ImGuiSelectableFlags.SpanAllColumns);
if (icon != null)
{
ImGui.SameLine(0, 0);
ImGui.SetCursorPos(pos);
ImGui.Image(icon.ImGuiHandle, iconSize);
}
if (ImGui.BeginDragDropSource()) if (ImGui.BeginDragDropSource())
{ {
ImGui.SetDragDropPayload("DeliverooDragDrop", nint.Zero, 0); ImGui.SetDragDropPayload("DeliverooDragDrop", nint.Zero, 0);
_dragDropSource = purchaseOption; _dragDropSource = itemId;
ImGui.EndDragDropSource(); ImGui.EndDragDropSource();
} }
if (ImGui.BeginDragDropTarget()) if (ImGui.BeginDragDropTarget())
{ {
if (_dragDropSource != null && if (_dragDropSource > 0 &&
ImGui.AcceptDragDropPayload("DeliverooDragDrop").NativePtr != null) ImGui.AcceptDragDropPayload("DeliverooDragDrop").NativePtr != null)
{ {
itemToAdd = _dragDropSource; itemToAdd = _dragDropSource;
indexToAdd = i; indexToAdd = i;
_dragDropSource = null; _dragDropSource = 0;
} }
ImGui.EndDragDropTarget(); ImGui.EndDragDropTarget();
@ -143,28 +147,12 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
ImGui.OpenPopupOnItemClick($"###ctx{i}", ImGuiPopupFlags.MouseButtonRight); ImGui.OpenPopupOnItemClick($"###ctx{i}", ImGuiPopupFlags.MouseButtonRight);
if (ImGui.BeginPopup($"###ctx{i}")) if (ImGui.BeginPopup($"###ctx{i}"))
{ {
bool sameQuantityForAllLists = purchaseOption.SameQuantityForAllLists; if (ImGui.Selectable($"Remove {_itemLookup[itemId].Name}"))
if (ImGui.MenuItem("Use same quantity for global and character-specific lists", null, itemToRemove = itemId;
ref sameQuantityForAllLists))
{
purchaseOption.SameQuantityForAllLists = sameQuantityForAllLists;
Save();
}
if (ImGui.MenuItem($"Remove {_itemLookup[purchaseOption.ItemId].Name}"))
itemToRemove = purchaseOption;
ImGui.EndPopup(); ImGui.EndPopup();
} }
if (icon != null)
{
ImGui.SameLine(0, 0);
ImGui.SetCursorPos(pos);
ImGui.Image(icon.ImGuiHandle, iconSize);
}
}
ImGui.EndDisabled(); ImGui.EndDisabled();
ImGui.PopID(); ImGui.PopID();
} }
@ -174,20 +162,20 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
if (itemToRemove != null) if (itemToRemove != null)
{ {
_configuration.ItemsAvailableToPurchase.Remove(itemToRemove); _configuration.ItemsAvailableForPurchase.Remove(itemToRemove.Value);
Save(); Save();
} }
if (itemToAdd != null) if (itemToAdd != null)
{ {
_configuration.ItemsAvailableToPurchase.Remove(itemToAdd); _configuration.ItemsAvailableForPurchase.Remove(itemToAdd.Value);
_configuration.ItemsAvailableToPurchase.Insert(indexToAdd, itemToAdd); _configuration.ItemsAvailableForPurchase.Insert(indexToAdd, itemToAdd.Value);
Save(); Save();
} }
List<(uint ItemId, string Name, ushort IconId, bool Limited)> comboValues = _gcRewardsCache.Rewards List<(uint ItemId, string Name, ushort IconId, bool Limited)> comboValues = _gcRewardsCache.Rewards
.Where(x => x.SubCategory is RewardSubCategory.Materials or RewardSubCategory.Materiel) .Where(x => x.SubCategory is RewardSubCategory.Materials or RewardSubCategory.Materiel)
.Where(x => _configuration.ItemsAvailableToPurchase.All(y => y.ItemId != x.ItemId)) .Where(x => !_configuration.ItemsAvailableForPurchase.Contains(x.ItemId))
.Select(x => (x.ItemId, x.Name, x.IconId, x.Limited)) .Select(x => (x.ItemId, x.Name, x.IconId, x.Limited))
.OrderBy(x => x.Name) .OrderBy(x => x.Name)
.ThenBy(x => x.GetHashCode()) .ThenBy(x => x.GetHashCode())
@ -202,23 +190,20 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
foreach (var item in comboValues.Where(x => foreach (var item in comboValues.Where(x =>
x.Name.Contains(_searchString, StringComparison.OrdinalIgnoreCase))) x.Name.Contains(_searchString, StringComparison.OrdinalIgnoreCase)))
{ {
using (var icon = _iconCache.GetIcon(item.IconId)) IDalamudTextureWrap? icon = _iconCache.GetIcon(item.IconId);
{
if (icon != null) if (icon != null)
{ {
ImGui.Image(icon.ImGuiHandle, new Vector2(ImGui.GetFrameHeight())); ImGui.Image(icon.ImGuiHandle, new Vector2(ImGui.GetFrameHeight()));
ImGui.SameLine(); ImGui.SameLine();
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ImGui.GetStyle().FramePadding.X); ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ImGui.GetStyle().FramePadding.X);
} }
}
bool addThis = bool addThis =
ImGui.Selectable( ImGui.Selectable(
$"{item.Name}{(item.Limited ? $" {SeIconChar.Hyadelyn.ToIconString()}" : "")}##SelectVenture{item.IconId}"); $"{item.Name}{(item.Limited ? $" {SeIconChar.Hyadelyn.ToIconString()}" : "")}##SelectVenture{item.IconId}");
if (addThis || addFirst) if (addThis || addFirst)
{ {
_configuration.ItemsAvailableToPurchase.Add(new Configuration.PurchaseOption _configuration.ItemsAvailableForPurchase.Add(item.ItemId);
{ ItemId = item.ItemId });
if (addFirst) if (addFirst)
{ {
@ -244,7 +229,7 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
if (_clientState is { IsLoggedIn: true, LocalContentId: > 0 }) if (_clientState is { IsLoggedIn: true, LocalContentId: > 0 })
{ {
string currentCharacterName = _clientState.LocalPlayer!.Name.ToString(); string currentCharacterName = _clientState.LocalPlayer!.Name.ToString();
string currentWorldName = _clientState.LocalPlayer.HomeWorld.Value.Name.ToString(); string currentWorldName = _clientState.LocalPlayer.HomeWorld.GameData!.Name.ToString();
ImGui.Text($"Current Character: {currentCharacterName} @ {currentWorldName}"); ImGui.Text($"Current Character: {currentCharacterName} @ {currentWorldName}");
ImGui.Spacing(); ImGui.Spacing();
ImGui.Separator(); ImGui.Separator();

View File

@ -4,25 +4,25 @@ using System.Linq;
using System.Numerics; using System.Numerics;
using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Keys; using Dalamud.Game.ClientState.Keys;
using Dalamud.Game.Text;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Colors; using Dalamud.Interface.Colors;
using Dalamud.Interface.Components; using Dalamud.Interface.Components;
using Dalamud.Interface.Textures.TextureWraps; using Dalamud.Interface.Internal;
using Dalamud.Interface.Utility; using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin; using Dalamud.Plugin;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Deliveroo.GameData; using Deliveroo.GameData;
using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game;
using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Client.UI.Agent; using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using ImGuiNET; using ImGuiNET;
using LLib; using LLib;
using LLib.GameUI;
using LLib.ImGui; using LLib.ImGui;
namespace Deliveroo.Windows; namespace Deliveroo.Windows;
internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configuration.MinimizableWindowConfig> internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
{ {
private static readonly IReadOnlyList<InventoryType> InventoryTypes = new[] private static readonly IReadOnlyList<InventoryType> InventoryTypes = new[]
{ {
@ -47,7 +47,7 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
private static readonly string[] StockingTypeLabels = { "Purchase Once", "Keep in Stock" }; private static readonly string[] StockingTypeLabels = { "Purchase Once", "Keep in Stock" };
private readonly DeliverooPlugin _plugin; private readonly DeliverooPlugin _plugin;
private readonly IDalamudPluginInterface _pluginInterface; private readonly DalamudPluginInterface _pluginInterface;
private readonly Configuration _configuration; private readonly Configuration _configuration;
private readonly ICondition _condition; private readonly ICondition _condition;
private readonly IClientState _clientState; private readonly IClientState _clientState;
@ -55,15 +55,14 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
private readonly ConfigWindow _configWindow; private readonly ConfigWindow _configWindow;
private readonly IconCache _iconCache; private readonly IconCache _iconCache;
private readonly IKeyState _keyState; private readonly IKeyState _keyState;
private readonly IGameGui _gameGui;
private readonly GameFunctions _gameFunctions; private readonly GameFunctions _gameFunctions;
private readonly TitleBarButton _minimizeButton;
private bool _state; private bool _state;
private Guid? _draggedItem;
public TurnInWindow(DeliverooPlugin plugin, IDalamudPluginInterface pluginInterface, Configuration configuration, public TurnInWindow(DeliverooPlugin plugin, DalamudPluginInterface pluginInterface, Configuration configuration,
ICondition condition, IClientState clientState, GcRewardsCache gcRewardsCache, ConfigWindow configWindow, ICondition condition, IClientState clientState, GcRewardsCache gcRewardsCache, ConfigWindow configWindow,
IconCache iconCache, IKeyState keyState, GameFunctions gameFunctions) IconCache iconCache, IKeyState keyState, IGameGui gameGui, GameFunctions gameFunctions)
: base("GC Delivery###DeliverooTurnIn") : base("GC Delivery###DeliverooTurnIn")
{ {
_plugin = plugin; _plugin = plugin;
@ -75,6 +74,7 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
_configWindow = configWindow; _configWindow = configWindow;
_iconCache = iconCache; _iconCache = iconCache;
_keyState = keyState; _keyState = keyState;
_gameGui = gameGui;
_gameFunctions = gameFunctions; _gameFunctions = gameFunctions;
Position = new Vector2(100, 100); Position = new Vector2(100, 100);
@ -90,20 +90,6 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
ShowCloseButton = false; ShowCloseButton = false;
AllowClickthrough = false; AllowClickthrough = false;
_minimizeButton = new TitleBarButton
{
Icon = FontAwesomeIcon.Minus,
Priority = int.MinValue,
IconOffset = new Vector2(1.5f, 1),
Click = _ =>
{
IsMinimized = !IsMinimized;
_minimizeButton!.Icon = IsMinimized ? FontAwesomeIcon.WindowMaximize : FontAwesomeIcon.Minus;
},
AvailableClickthrough = true,
};
TitleBarButtons.Insert(0, _minimizeButton);
TitleBarButtons.Add(new TitleBarButton TitleBarButtons.Add(new TitleBarButton
{ {
Icon = FontAwesomeIcon.Cog, Icon = FontAwesomeIcon.Cog,
@ -119,17 +105,7 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
}); });
} }
public Configuration.MinimizableWindowConfig WindowConfig => _configuration.TurnInWindowConfig; public WindowConfig WindowConfig => _configuration.TurnInWindowConfig;
private bool IsMinimized
{
get => WindowConfig.IsMinimized;
set
{
WindowConfig.IsMinimized = value;
SaveWindowConfig();
}
}
public bool State public bool State
{ {
@ -152,7 +128,7 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
private bool IsOnHomeWorld => private bool IsOnHomeWorld =>
_clientState.LocalPlayer == null || _clientState.LocalPlayer == null ||
_clientState.LocalPlayer.HomeWorld.RowId == _clientState.LocalPlayer.CurrentWorld.RowId; _clientState.LocalPlayer.HomeWorld.Id == _clientState.LocalPlayer.CurrentWorld.Id;
private IItemsToPurchase ItemsWrapper => UseCharacterSpecificItemsToPurchase private IItemsToPurchase ItemsWrapper => UseCharacterSpecificItemsToPurchase
? new CharacterSpecificItemsToPurchase(_plugin.CharacterConfiguration!, _pluginInterface) ? new CharacterSpecificItemsToPurchase(_plugin.CharacterConfiguration!, _pluginInterface)
@ -176,16 +152,13 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
.Where(x => x.Reward.RequiredRank <= rank) .Where(x => x.Reward.RequiredRank <= rank)
.Select(x => .Select(x =>
{ {
var purchaseOption = _configuration.ItemsAvailableToPurchase.Where(y => y.SameQuantityForAllLists)
.FirstOrDefault(y => y.ItemId == x.Item.ItemId);
int limit = purchaseOption?.GlobalLimit ?? x.Item.Limit;
var request = new PurchaseItemRequest var request = new PurchaseItemRequest
{ {
ItemId = x.Item.ItemId, ItemId = x.Item.ItemId,
Name = x.Reward.Name, Name = x.Reward.Name,
EffectiveLimit = CalculateEffectiveLimit( EffectiveLimit = CalculateEffectiveLimit(
x.Item.ItemId, x.Item.ItemId,
limit <= 0 ? uint.MaxValue : (uint)limit, x.Item.Limit <= 0 ? uint.MaxValue : (uint)x.Item.Limit,
x.Reward.StackSize, x.Reward.StackSize,
x.Reward.InventoryLimit), x.Reward.InventoryLimit),
SealCost = x.Reward.SealCost, SealCost = x.Reward.SealCost,
@ -244,17 +217,14 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
} }
float indentSize = ImGui.GetFrameHeight() + ImGui.GetStyle().ItemInnerSpacing.X; float indentSize = ImGui.GetFrameHeight() + ImGui.GetStyle().ItemInnerSpacing.X;
ImGui.Indent(indentSize);
if (!string.IsNullOrEmpty(Error)) if (!string.IsNullOrEmpty(Error))
{ {
using (ImRaii.PushIndent(indentSize))
ImGui.TextColored(ImGuiColors.DalamudRed, Error); ImGui.TextColored(ImGuiColors.DalamudRed, Error);
} }
else else
{ {
using (ImRaii.PushIndent(indentSize)) if (_configuration.BehaviorOnOtherWorld == Configuration.EBehaviorOnOtherWorld.Warning && !IsOnHomeWorld)
{
if (_configuration.BehaviorOnOtherWorld == Configuration.EBehaviorOnOtherWorld.Warning &&
!IsOnHomeWorld)
{ {
ImGui.TextColored(ImGuiColors.DalamudRed, ImGui.TextColored(ImGuiColors.DalamudRed,
"You are not on your home world and will not earn FC points."); "You are not on your home world and will not earn FC points.");
@ -278,8 +248,7 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
ImGui.BeginDisabled(_condition[ConditionFlag.OccupiedInQuestEvent] || ImGui.BeginDisabled(_condition[ConditionFlag.OccupiedInQuestEvent] ||
_condition[ConditionFlag.Casting] || _condition[ConditionFlag.Casting] ||
agentInventoryContext == null); agentInventoryContext == null);
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Bolt, if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Bolt, "Use Priority Seal Allowance (15%)"))
"Use Priority Seal Allowance (15%)"))
{ {
agentInventoryContext->UseItem(ItemIds.PrioritySealAllowance); agentInventoryContext->UseItem(ItemIds.PrioritySealAllowance);
} }
@ -287,16 +256,17 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
ImGui.EndDisabled(); ImGui.EndDisabled();
} }
} }
}
if (!IsMinimized) ImGui.Unindent(indentSize);
{
ImGui.Separator(); ImGui.Separator();
using (ImRaii.Disabled(state)) ImGui.BeginDisabled(state);
DrawItemsToBuy(grandCompany); DrawItemsToBuy(grandCompany);
}
ImGui.EndDisabled();
} }
ImGui.Separator();
if (_configuration.QuickTurnInKey != VirtualKey.NO_KEY) if (_configuration.QuickTurnInKey != VirtualKey.NO_KEY)
{ {
var key = _configuration.QuickTurnInKey switch var key = _configuration.QuickTurnInKey switch
@ -307,23 +277,15 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
_ => _configuration.QuickTurnInKey.ToString() _ => _configuration.QuickTurnInKey.ToString()
}; };
if (!State && _keyState[_configuration.QuickTurnInKey]) if (!State && _keyState[_configuration.QuickTurnInKey])
{
ImGui.Separator();
ImGui.TextColored(ImGuiColors.HealerGreen, "Click an item to turn it in without confirmation"); ImGui.TextColored(ImGuiColors.HealerGreen, "Click an item to turn it in without confirmation");
} else
else if (!IsMinimized)
{
ImGui.Separator();
ImGui.Text($"Hold '{key}' when clicking an item to turn it in without confirmation."); ImGui.Text($"Hold '{key}' when clicking an item to turn it in without confirmation.");
}
ImGui.Separator();
} }
if (!IsMinimized)
{
ImGui.Separator();
ImGui.Text($"Debug (State): {_plugin.CurrentStage}"); ImGui.Text($"Debug (State): {_plugin.CurrentStage}");
} }
}
private unsafe void DrawNextRankPrequesites() private unsafe void DrawNextRankPrequesites()
{ {
@ -334,7 +296,7 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
uint requiredSeals = _gameFunctions.GetSealsRequiredForNextRank(); uint requiredSeals = _gameFunctions.GetSealsRequiredForNextRank();
int currentHuntingLog = int currentHuntingLog =
MonsterNoteManager.Instance()->RankData[(int)_gameFunctions.GetGrandCompany() + 7] MonsterNoteManager.Instance()->RankDataArraySpan[(int)_gameFunctions.GetGrandCompany() + 7]
.Rank; .Rank;
byte requiredHuntingLog = _gameFunctions.GetRequiredHuntingLogForNextRank(); byte requiredHuntingLog = _gameFunctions.GetRequiredHuntingLogForNextRank();
@ -381,20 +343,13 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
{ {
(GcRewardItem.None, GcRewardItem.None.Name, GcRewardItem.None.Name), (GcRewardItem.None, GcRewardItem.None.Name, GcRewardItem.None.Name),
}; };
foreach (Configuration.PurchaseOption purchaseOption in _configuration.ItemsAvailableToPurchase) foreach (uint itemId in _configuration.ItemsAvailableForPurchase)
{ {
var gcReward = _gcRewardsCache.GetReward(purchaseOption.ItemId); var gcReward = _gcRewardsCache.GetReward(itemId);
int itemCountWithoutRetainers = _gameFunctions.GetItemCount(purchaseOption.ItemId, false); int itemCountWithoutRetainers = _gameFunctions.GetItemCount(itemId, false);
int itemCountWithRetainers = _gameFunctions.GetItemCount(purchaseOption.ItemId, true); int itemCountWithRetainers = _gameFunctions.GetItemCount(itemId, true);
string itemNameWithoutRetainers = gcReward.Name; string itemNameWithoutRetainers = gcReward.Name;
string itemNameWithRetainers = gcReward.Name; string itemNameWithRetainers = gcReward.Name;
if (purchaseOption.SameQuantityForAllLists)
{
itemNameWithoutRetainers += $" {((SeIconChar)57412).ToIconString()}";
itemNameWithRetainers += $" {((SeIconChar)57412).ToIconString()}";
}
if (itemCountWithoutRetainers > 0) if (itemCountWithoutRetainers > 0)
itemNameWithoutRetainers += $" ({itemCountWithoutRetainers:N0})"; itemNameWithoutRetainers += $" ({itemCountWithoutRetainers:N0})";
if (itemCountWithRetainers > 0) if (itemCountWithRetainers > 0)
@ -408,89 +363,11 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
itemsWrapper.Save(); itemsWrapper.Save();
} }
Configuration.PurchasePriority? itemToRemove = null; int? itemToRemove = null;
Configuration.PurchasePriority? itemToAdd = null; Configuration.PurchasePriority? itemToAdd = null;
int indexToAdd = 0; int indexToAdd = 0;
float width = ImGui.GetContentRegionAvail().X;
List<(Vector2 TopLeft, Vector2 BottomRight)> itemPositions = [];
for (int i = 0; i < itemsWrapper.GetItemsToPurchase().Count; ++i) for (int i = 0; i < itemsWrapper.GetItemsToPurchase().Count; ++i)
{ {
DrawItemToBuy(grandCompany, i, itemsWrapper, comboValues, width, ref itemToRemove, itemPositions);
}
if (!ImGui.IsMouseDragging(ImGuiMouseButton.Left))
_draggedItem = null;
else if (_draggedItem != null)
{
var items = itemsWrapper.GetItemsToPurchase().ToList();
var draggedItem = items.Single(x => x.InternalId == _draggedItem);
int oldIndex = items.IndexOf(draggedItem);
var (topLeft, bottomRight) = itemPositions[oldIndex];
ImGui.GetWindowDrawList().AddRect(topLeft, bottomRight, ImGui.GetColorU32(ImGuiColors.DalamudGrey), 3f,
ImDrawFlags.RoundCornersAll);
int newIndex = itemPositions.FindIndex(x => ImGui.IsMouseHoveringRect(x.TopLeft, x.BottomRight, true));
if (newIndex >= 0 && oldIndex != newIndex)
{
itemToAdd = items.Single(x => x.InternalId == _draggedItem);
indexToAdd = newIndex;
}
}
if (itemToRemove != null)
{
itemsWrapper.Remove(itemToRemove);
itemsWrapper.Save();
}
if (itemToAdd != null)
{
itemsWrapper.Remove(itemToAdd);
itemsWrapper.Insert(indexToAdd, itemToAdd);
itemsWrapper.Save();
}
if (_configuration.ItemsAvailableToPurchase.Any(x =>
itemsWrapper.GetItemsToPurchase().All(y => x.ItemId != y.ItemId)))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Plus, "Add Item"))
ImGui.OpenPopup("##AddItem");
if (ImGui.BeginPopupContextItem("##AddItem", ImGuiPopupFlags.NoOpenOverItems))
{
foreach (var purchaseOption in _configuration.ItemsAvailableToPurchase.Distinct())
{
if (_gcRewardsCache.RewardLookup.TryGetValue(purchaseOption.ItemId, out var reward))
{
if (ImGui.MenuItem($"{reward.Name}##{purchaseOption.ItemId}"))
{
itemsWrapper.Add(new Configuration.PurchasePriority
{ ItemId = purchaseOption.ItemId, Limit = 0 });
itemsWrapper.Save();
ImGui.CloseCurrentPopup();
}
}
}
ImGui.EndPopup();
}
ImGui.SameLine();
}
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Cog, "Configure available Items"))
_configWindow.IsOpen = true;
}
private void DrawItemToBuy(GrandCompany grandCompany, int i, IItemsToPurchase itemsWrapper,
List<(GcRewardItem Item, string NameWithoutRetainers, string NameWithRetainers)> comboValues, float width,
ref Configuration.PurchasePriority? itemToRemove, List<(Vector2 TopLeft, Vector2 BottomRight)> itemPositions)
{
Vector2 topLeft = ImGui.GetCursorScreenPos() + new Vector2(0, -ImGui.GetStyle().ItemSpacing.Y / 2);
ImGui.PushID($"ItemToBuy{i}"); ImGui.PushID($"ItemToBuy{i}");
Configuration.PurchasePriority item = itemsWrapper.GetItemsToPurchase()[i]; Configuration.PurchasePriority item = itemsWrapper.GetItemsToPurchase()[i];
@ -553,27 +430,15 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
} }
var comboItem = comboValues[comboValueIndex]; var comboItem = comboValues[comboValueIndex];
using (var icon = _iconCache.GetIcon(comboItem.Item.IconId)) IDalamudTextureWrap? icon = _iconCache.GetIcon(comboItem.Item.IconId);
{
if (icon != null) if (icon != null)
{ {
ImGui.Image(icon.ImGuiHandle, new Vector2(ImGui.GetFrameHeight())); ImGui.Image(icon.ImGuiHandle, new Vector2(ImGui.GetFrameHeight()));
ImGui.SameLine(0, 3); ImGui.SameLine(0, 3);
} }
}
indentX = ImGui.GetCursorPosX() - indentX; indentX = ImGui.GetCursorPosX() - indentX;
ImGui.PushFont(UiBuilder.IconFont);
ImGui.SetNextItemWidth(width -
ImGui.GetStyle().WindowPadding.X -
ImGui.CalcTextSize(FontAwesomeIcon.Circle.ToIconString()).X -
ImGui.CalcTextSize(FontAwesomeIcon.ArrowsUpDown.ToIconString()).X -
ImGui.CalcTextSize(FontAwesomeIcon.Times.ToIconString()).X -
ImGui.GetStyle().FramePadding.X * 8 -
ImGui.GetStyle().ItemSpacing.X * 2 - 3 * 3);
ImGui.PopFont();
if (ImGui.Combo("", ref comboValueIndex, if (ImGui.Combo("", ref comboValueIndex,
comboValues.Select(x => item.CheckRetainerInventory ? x.NameWithRetainers : x.NameWithoutRetainers) comboValues.Select(x => item.CheckRetainerInventory ? x.NameWithRetainers : x.NameWithoutRetainers)
.ToArray(), comboValues.Count)) .ToArray(), comboValues.Count))
@ -587,72 +452,48 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
if (itemsWrapper.GetItemsToPurchase().Count >= 2) if (itemsWrapper.GetItemsToPurchase().Count >= 2)
{ {
ImGui.PushFont(UiBuilder.IconFont); ImGui.SameLine();
ImGui.SameLine(ImGui.GetContentRegionAvail().X + if (ImGuiComponents.IconButton($"##Up{i}", FontAwesomeIcon.ArrowUp))
ImGui.GetStyle().WindowPadding.X -
ImGui.CalcTextSize(FontAwesomeIcon.ArrowsUpDown.ToIconString()).X -
ImGui.CalcTextSize(FontAwesomeIcon.Times.ToIconString()).X -
ImGui.GetStyle().FramePadding.X * 4 -
ImGui.GetStyle().ItemSpacing.X);
ImGui.PopFont();
if (_draggedItem == item.InternalId)
{ {
ImGuiComponents.IconButton("##Move", FontAwesomeIcon.ArrowsUpDown, itemToAdd = item;
ImGui.ColorConvertU32ToFloat4(ImGui.GetColorU32(ImGuiCol.ButtonActive))); if (i > 0)
} indexToAdd = i - 1;
else else
ImGuiComponents.IconButton("##Move", FontAwesomeIcon.ArrowsUpDown); indexToAdd = itemsWrapper.GetItemsToPurchase().Count - 1;
}
if (_draggedItem == null && ImGui.IsItemActive() && ImGui.IsMouseDragging(ImGuiMouseButton.Left)) ImGui.SameLine(0, 0);
_draggedItem = item.InternalId; if (ImGuiComponents.IconButton($"##Down{i}", FontAwesomeIcon.ArrowDown))
{
itemToAdd = item;
if (i < itemsWrapper.GetItemsToPurchase().Count - 1)
indexToAdd = i + 1;
else
indexToAdd = 0;
}
ImGui.SameLine(); ImGui.SameLine();
}
else
{
ImGui.PushFont(UiBuilder.IconFont);
ImGui.SameLine(ImGui.GetContentRegionAvail().X +
ImGui.GetStyle().WindowPadding.X -
ImGui.CalcTextSize(FontAwesomeIcon.Times.ToIconString()).X -
ImGui.GetStyle().FramePadding.X * 2);
ImGui.PopFont();
}
if (ImGuiComponents.IconButton($"###Remove{i}", FontAwesomeIcon.Times)) if (ImGuiComponents.IconButton($"###Remove{i}", FontAwesomeIcon.Times))
itemToRemove = item; itemToRemove = i;
}
if (enabled) if (enabled)
{ {
ImGui.Indent(indentX); ImGui.Indent(indentX);
if (comboValueIndex > 0) if (comboValueIndex > 0)
{ {
var purchaseOption =
_configuration.ItemsAvailableToPurchase
.Where(x => x.SameQuantityForAllLists)
.FirstOrDefault(x => x.ItemId == item.ItemId);
ImGui.SetNextItemWidth(ImGuiHelpers.GlobalScale * 130); ImGui.SetNextItemWidth(ImGuiHelpers.GlobalScale * 130);
int limit = Math.Min(purchaseOption?.GlobalLimit ?? item.Limit, (int)comboItem.Item.InventoryLimit); int limit = Math.Min(item.Limit, (int)comboItem.Item.InventoryLimit);
int stepSize = comboItem.Item.StackSize < 99 ? 1 : 50; int stepSize = comboItem.Item.StackSize < 99 ? 1 : 50;
string label = item.Type == Configuration.PurchaseType.KeepStocked string label = item.Type == Configuration.PurchaseType.KeepStocked
? "Maximum items to buy" ? "Maximum items to buy"
: "Remaining items to buy"; : "Remaining items to buy";
if (ImGui.InputInt(label, ref limit, stepSize, stepSize * 10)) if (ImGui.InputInt(label, ref limit, stepSize, stepSize * 10))
{ {
int newLimit = Math.Min(Math.Max(0, limit), (int)comboItem.Item.InventoryLimit); item.Limit = Math.Min(Math.Max(0, limit), (int)comboItem.Item.InventoryLimit);
if (purchaseOption != null)
{
purchaseOption.GlobalLimit = newLimit;
_pluginInterface.SavePluginConfig(_configuration);
}
else
{
item.Limit = newLimit;
itemsWrapper.Save(); itemsWrapper.Save();
} }
} }
}
else if (item.Limit != 0) else if (item.Limit != 0)
{ {
item.Limit = 0; item.Limit = 0;
@ -677,10 +518,49 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
} }
ImGui.PopID(); ImGui.PopID();
}
Vector2 bottomRight = new Vector2(topLeft.X + width, if (itemToAdd != null)
ImGui.GetCursorScreenPos().Y - ImGui.GetStyle().ItemSpacing.Y + 2); {
itemPositions.Add((topLeft, bottomRight)); itemsWrapper.Remove(itemToAdd);
itemsWrapper.Insert(indexToAdd, itemToAdd);
itemsWrapper.Save();
}
if (itemToRemove != null)
{
itemsWrapper.RemoveAt(itemToRemove.Value);
itemsWrapper.Save();
}
if (_configuration.ItemsAvailableForPurchase.Any(x =>
itemsWrapper.GetItemsToPurchase().All(y => x != y.ItemId)))
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Plus, "Add Item"))
ImGui.OpenPopup("##AddItem");
if (ImGui.BeginPopupContextItem("##AddItem", ImGuiPopupFlags.NoOpenOverItems))
{
foreach (var itemId in _configuration.ItemsAvailableForPurchase.Distinct())
{
if (_gcRewardsCache.RewardLookup.TryGetValue(itemId, out var reward))
{
if (ImGui.MenuItem($"{reward.Name}##{itemId}"))
{
itemsWrapper.Add(new Configuration.PurchasePriority { ItemId = itemId, Limit = 0 });
itemsWrapper.Save();
ImGui.CloseCurrentPopup();
}
}
}
ImGui.EndPopup();
}
ImGui.SameLine();
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Cog, "Configure available Items"))
_configWindow.IsOpen = true;
}
} }
private unsafe uint CalculateEffectiveLimit(uint itemId, uint limit, uint stackSize, uint inventoryLimit) private unsafe uint CalculateEffectiveLimit(uint itemId, uint limit, uint stackSize, uint inventoryLimit)
@ -697,7 +577,7 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
for (int i = 0; i < container->Size; ++i) for (int i = 0; i < container->Size; ++i)
{ {
var item = container->GetInventorySlot(i); var item = container->GetInventorySlot(i);
if (item == null || item->ItemId == 0 || item->ItemId == itemId) if (item == null || item->ItemID == 0 || item->ItemID == itemId)
{ {
slotsThatCanBeUsed++; slotsThatCanBeUsed++;
} }
@ -725,10 +605,10 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
private sealed class CharacterSpecificItemsToPurchase : IItemsToPurchase private sealed class CharacterSpecificItemsToPurchase : IItemsToPurchase
{ {
private readonly CharacterConfiguration _characterConfiguration; private readonly CharacterConfiguration _characterConfiguration;
private readonly IDalamudPluginInterface _pluginInterface; private readonly DalamudPluginInterface _pluginInterface;
public CharacterSpecificItemsToPurchase(CharacterConfiguration characterConfiguration, public CharacterSpecificItemsToPurchase(CharacterConfiguration characterConfiguration,
IDalamudPluginInterface pluginInterface) DalamudPluginInterface pluginInterface)
{ {
_characterConfiguration = characterConfiguration; _characterConfiguration = characterConfiguration;
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
@ -758,9 +638,9 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig<Configura
private sealed class GlobalItemsToPurchase : IItemsToPurchase private sealed class GlobalItemsToPurchase : IItemsToPurchase
{ {
private readonly Configuration _configuration; private readonly Configuration _configuration;
private readonly IDalamudPluginInterface _pluginInterface; private readonly DalamudPluginInterface _pluginInterface;
public GlobalItemsToPurchase(Configuration configuration, IDalamudPluginInterface pluginInterface) public GlobalItemsToPurchase(Configuration configuration, DalamudPluginInterface pluginInterface)
{ {
_configuration = configuration; _configuration = configuration;
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;

View File

@ -4,83 +4,12 @@
"net8.0-windows7.0": { "net8.0-windows7.0": {
"DalamudPackager": { "DalamudPackager": {
"type": "Direct", "type": "Direct",
"requested": "[11.0.0, )", "requested": "[2.1.12, )",
"resolved": "11.0.0", "resolved": "2.1.12",
"contentHash": "bjT7XUlhIJSmsE/O76b7weUX+evvGQctbQB8aKXt94o+oPWxHpCepxAGMs7Thow3AzCyqWs7cOpp9/2wcgRRQA==" "contentHash": "Sc0PVxvgg4NQjcI8n10/VfUQBAS4O+Fw2pZrAqBdRMbthYGeogzu5+xmIGCGmsEZ/ukMOBuAqiNiB5qA3MRalg=="
},
"DotNet.ReproducibleBuilds": {
"type": "Direct",
"requested": "[1.1.1, )",
"resolved": "1.1.1",
"contentHash": "+H2t/t34h6mhEoUvHi8yGXyuZ2GjSovcGYehJrS2MDm2XgmPfZL2Sdxg+uL2lKgZ4M6tTwKHIlxOob2bgh0NRQ==",
"dependencies": {
"Microsoft.SourceLink.AzureRepos.Git": "1.1.1",
"Microsoft.SourceLink.Bitbucket.Git": "1.1.1",
"Microsoft.SourceLink.GitHub": "1.1.1",
"Microsoft.SourceLink.GitLab": "1.1.1"
}
},
"Microsoft.SourceLink.Gitea": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "KOBodmDnlWGIqZt2hT47Q69TIoGhIApDVLCyyj9TT5ct8ju16AbHYcB4XeknoHX562wO1pMS/1DfBIZK+V+sxg==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.SourceLink.AzureRepos.Git": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "qB5urvw9LO2bG3eVAkuL+2ughxz2rR7aYgm2iyrB8Rlk9cp2ndvGRCvehk3rNIhRuNtQaeKwctOl1KvWiklv5w==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "1.1.1",
"Microsoft.SourceLink.Common": "1.1.1"
}
},
"Microsoft.SourceLink.Bitbucket.Git": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "cDzxXwlyWpLWaH0em4Idj0H3AmVo3L/6xRXKssYemx+7W52iNskj/SQ4FOmfCb8YQt39otTDNMveCZzYtMoucQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "1.1.1",
"Microsoft.SourceLink.Common": "1.1.1"
}
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"Microsoft.SourceLink.GitHub": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "1.1.1",
"Microsoft.SourceLink.Common": "1.1.1"
}
},
"Microsoft.SourceLink.GitLab": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "tvsg47DDLqqedlPeYVE2lmiTpND8F0hkrealQ5hYltSmvruy/Gr5nHAKSsjyw5L3NeM/HLMI5ORv7on/M4qyZw==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "1.1.1",
"Microsoft.SourceLink.Common": "1.1.1"
}
}, },
"llib": { "llib": {
"type": "Project", "type": "Project"
"dependencies": {
"DalamudPackager": "[11.0.0, )"
}
} }
} }
} }

2
LLib

@ -1 +1 @@
Subproject commit b581e2ea2a61f44ed3f0cb4f6ea8cc1595525544 Subproject commit b5125d4b3f7cdc0c7514a01764e5b5d4d85f80a7