Compare commits

..

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

11 changed files with 275 additions and 415 deletions

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; }
@ -32,18 +27,8 @@ internal sealed class Configuration : IPluginConfiguration
public WindowConfig 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;
} }

View File

@ -1,6 +1,6 @@
<Project Sdk="Dalamud.NET.Sdk/11.0.0"> <Project Sdk="Dalamud.NET.Sdk/9.0.2">
<PropertyGroup> <PropertyGroup>
<Version>6.0</Version> <Version>5.2</Version>
<OutputPath>dist</OutputPath> <OutputPath>dist</OutputPath>
</PropertyGroup> </PropertyGroup>

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;
@ -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,
@ -117,23 +114,6 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
_addonLifecycle.RegisterListener(AddonEvent.PostSetup, "GrandCompanySupplyReward", GrandCompanySupplyRewardPostSetup); _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "GrandCompanySupplyReward", GrandCompanySupplyRewardPostSetup);
} }
private void MigrateConfiguration()
{
#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, private void ChatMessage(XivChatType type, int timestamp, ref SeString sender, ref SeString message,
ref bool isHandled) ref bool isHandled)
{ {
@ -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;
} }

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;
@ -26,7 +27,7 @@ internal sealed class GameStrings
dataManager.GetString<Addon>(102434, addon => addon.Text, pluginLog)?.ReplaceLineEndings("") 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,7 +19,7 @@ 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});
} }
} }

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

View File

@ -40,7 +40,7 @@ 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(IDalamudPluginInterface pluginInterface, DeliverooPlugin plugin, Configuration configuration,
GcRewardsCache gcRewardsCache, IClientState clientState, IPluginLog pluginLog, IconCache iconCache, GcRewardsCache gcRewardsCache, IClientState clientState, IPluginLog pluginLog, IconCache iconCache,
@ -89,52 +89,51 @@ 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)) var 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) icon.TryGetWrap(out IDalamudTextureWrap? wrap, out _);
if (wrap != 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 (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,26 +142,19 @@ 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) if (wrap != null)
{ {
ImGui.SameLine(0, 0); ImGui.SameLine(0, 0);
ImGui.SetCursorPos(pos); ImGui.SetCursorPos(pos);
ImGui.Image(icon.ImGuiHandle, iconSize); ImGui.Image(wrap.ImGuiHandle, iconSize);
}
wrap.Dispose();
} }
ImGui.EndDisabled(); ImGui.EndDisabled();
@ -174,20 +166,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,14 +194,14 @@ 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)) var icon = _iconCache.GetIcon(item.IconId);
if (icon.TryGetWrap(out IDalamudTextureWrap? wrap, out _))
{ {
if (icon != null) ImGui.Image(wrap.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);
}
wrap.Dispose();
} }
bool addThis = bool addThis =
@ -217,8 +209,7 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
$"{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 +235,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,7 +4,6 @@ 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;
@ -57,7 +56,6 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
private readonly GameFunctions _gameFunctions; private readonly GameFunctions _gameFunctions;
private bool _state; private bool _state;
private Guid? _draggedItem;
public TurnInWindow(DeliverooPlugin plugin, IDalamudPluginInterface pluginInterface, Configuration configuration, public TurnInWindow(DeliverooPlugin plugin, IDalamudPluginInterface pluginInterface, Configuration configuration,
ICondition condition, IClientState clientState, GcRewardsCache gcRewardsCache, ConfigWindow configWindow, ICondition condition, IClientState clientState, GcRewardsCache gcRewardsCache, ConfigWindow configWindow,
@ -126,7 +124,7 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
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)
@ -150,16 +148,13 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
.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,
@ -344,20 +339,13 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
{ {
(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)
@ -371,89 +359,11 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
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];
@ -516,27 +426,17 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
} }
var comboItem = comboValues[comboValueIndex]; var comboItem = comboValues[comboValueIndex];
using (var icon = _iconCache.GetIcon(comboItem.Item.IconId)) var icon = _iconCache.GetIcon(comboItem.Item.IconId);
if (icon.TryGetWrap(out IDalamudTextureWrap? wrap, out _))
{ {
if (icon != null) ImGui.Image(wrap.ImGuiHandle, new Vector2(ImGui.GetFrameHeight()));
{
ImGui.Image(icon.ImGuiHandle, new Vector2(ImGui.GetFrameHeight()));
ImGui.SameLine(0, 3); ImGui.SameLine(0, 3);
}
wrap.Dispose();
} }
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))
@ -550,72 +450,48 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
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;
@ -640,10 +516,49 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
} }
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)

View File

@ -4,9 +4,9 @@
"net8.0-windows7.0": { "net8.0-windows7.0": {
"DalamudPackager": { "DalamudPackager": {
"type": "Direct", "type": "Direct",
"requested": "[11.0.0, )", "requested": "[2.1.13, )",
"resolved": "11.0.0", "resolved": "2.1.13",
"contentHash": "bjT7XUlhIJSmsE/O76b7weUX+evvGQctbQB8aKXt94o+oPWxHpCepxAGMs7Thow3AzCyqWs7cOpp9/2wcgRRQA==" "contentHash": "rMN1omGe8536f4xLMvx9NwfvpAc9YFFfeXJ1t4P4PE6Gu8WCIoFliR1sh07hM+bfODmesk/dvMbji7vNI+B/pQ=="
}, },
"DotNet.ReproducibleBuilds": { "DotNet.ReproducibleBuilds": {
"type": "Direct", "type": "Direct",
@ -79,7 +79,7 @@
"llib": { "llib": {
"type": "Project", "type": "Project",
"dependencies": { "dependencies": {
"DalamudPackager": "[11.0.0, )" "DalamudPackager": "[2.1.13, )"
} }
} }
} }

2
LLib

@ -1 +1 @@
Subproject commit 538329a1e80acbcd09e28bd6dd459c35b5563c0a Subproject commit 7027d291efbbff6a55944dd521d3907210ddecbe