1
0
Fork 0

Compare commits

...

5 Commits

5 changed files with 321 additions and 193 deletions

View File

@ -1,4 +1,6 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Dalamud.Configuration;
using Dalamud.Game.ClientState.Keys;
using Dalamud.Game.Text;
@ -9,10 +11,13 @@ namespace Deliveroo;
internal sealed class Configuration : IPluginConfiguration
{
public int Version { get; set; } = 1;
public int Version { get; set; } = 2;
public List<uint> ItemsAvailableForPurchase { get; set; } = new();
public List<PurchasePriority> ItemsToPurchase { get; set; } = new();
[Obsolete]
public List<uint> ItemsAvailableForPurchase { get; set; } = [];
public List<PurchaseOption> ItemsAvailableToPurchase { get; set; } = [];
public List<PurchasePriority> ItemsToPurchase { get; set; } = [];
public int ReservedSealCount { get; set; }
public bool ReserveDifferentSealCountAtMaxRank { get; set; }
@ -27,8 +32,18 @@ internal sealed class Configuration : IPluginConfiguration
public WindowConfig TurnInWindowConfig { 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
{
[JsonIgnore]
public Guid InternalId { get; } = Guid.NewGuid();
public uint ItemId { get; set; }
public int Limit { get; set; }
public bool Enabled { get; set; } = true;
@ -54,9 +69,9 @@ internal sealed class Configuration : IPluginConfiguration
public bool AddVentureIfNoItemToPurchaseSelected()
{
if (ItemsAvailableForPurchase.Count == 0)
if (ItemsAvailableToPurchase.Count == 0)
{
ItemsAvailableForPurchase.Add(ItemIds.Venture);
ItemsAvailableToPurchase.Add(new PurchaseOption { ItemId = ItemIds.Venture });
return true;
}

View File

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

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects;
@ -74,6 +75,8 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
_keyState = keyState;
_configuration = (Configuration?)_pluginInterface.GetPluginConfig() ?? new Configuration();
MigrateConfiguration();
_gameStrings = new GameStrings(dataManager, _pluginLog);
_externalPluginHandler = new ExternalPluginHandler(_pluginInterface, gameConfig, _configuration, _pluginLog);
_gameFunctions = new GameFunctions(objectTable, _clientState, targetManager, dataManager,
@ -114,6 +117,23 @@ public sealed partial class DeliverooPlugin : IDalamudPlugin
_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,
ref bool isHandled)
{

View File

@ -40,7 +40,7 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
];
private string _searchString = string.Empty;
private uint _dragDropSource;
private Configuration.PurchaseOption? _dragDropSource;
public ConfigWindow(IDalamudPluginInterface pluginInterface, DeliverooPlugin plugin, Configuration configuration,
GcRewardsCache gcRewardsCache, IClientState clientState, IPluginLog pluginLog, IconCache iconCache,
@ -89,20 +89,20 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
{
if (ImGui.BeginTabItem("Items for Auto-Buy"))
{
uint? itemToRemove = null;
uint? itemToAdd = null;
Configuration.PurchaseOption? itemToRemove = null;
Configuration.PurchaseOption? itemToAdd = null;
int indexToAdd = 0;
if (ImGui.BeginChild("Items", new Vector2(-1, -ImGui.GetFrameHeightWithSpacing()), true,
ImGuiWindowFlags.NoSavedSettings))
{
for (int i = 0; i < _configuration.ItemsAvailableForPurchase.Count; ++i)
for (int i = 0; i < _configuration.ItemsAvailableToPurchase.Count; ++i)
{
uint itemId = _configuration.ItemsAvailableForPurchase[i];
var purchaseOption = _configuration.ItemsAvailableToPurchase[i];
ImGui.PushID($"###Item{i}");
ImGui.BeginDisabled(
_configuration.ItemsAvailableForPurchase.Count == 1 && itemId == ItemIds.Venture);
_configuration.ItemsAvailableToPurchase.Count == 1 && purchaseOption.ItemId == ItemIds.Venture);
var item = _itemLookup[itemId];
var item = _itemLookup[purchaseOption.ItemId];
var icon = _iconCache.GetIcon(item.IconId);
Vector2 pos = ImGui.GetCursorPos();
Vector2 iconSize = new Vector2(ImGui.GetTextLineHeight() + ImGui.GetStyle().ItemSpacing.Y);
@ -114,26 +114,26 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
ImGui.GetStyle().ItemSpacing.Y / 2));
}
ImGui.Selectable($"{item.Name}{(item.Limited ? $" {SeIconChar.Hyadelyn.ToIconString()}" : "")}",
ImGui.Selectable($"{item.Name}{(item.Limited ? $" {SeIconChar.Hyadelyn.ToIconString()}" : "")}{(purchaseOption.SameQuantityForAllLists ? $" {((SeIconChar)57412).ToIconString()} (Limit: {purchaseOption.GlobalLimit:N0})" : "")}",
false, ImGuiSelectableFlags.SpanAllColumns);
if (ImGui.BeginDragDropSource())
{
ImGui.SetDragDropPayload("DeliverooDragDrop", nint.Zero, 0);
_dragDropSource = itemId;
_dragDropSource = purchaseOption;
ImGui.EndDragDropSource();
}
if (ImGui.BeginDragDropTarget())
{
if (_dragDropSource > 0 &&
if (_dragDropSource != null &&
ImGui.AcceptDragDropPayload("DeliverooDragDrop").NativePtr != null)
{
itemToAdd = _dragDropSource;
indexToAdd = i;
_dragDropSource = 0;
_dragDropSource = null;
}
ImGui.EndDragDropTarget();
@ -142,8 +142,16 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
ImGui.OpenPopupOnItemClick($"###ctx{i}", ImGuiPopupFlags.MouseButtonRight);
if (ImGui.BeginPopup($"###ctx{i}"))
{
if (ImGui.Selectable($"Remove {_itemLookup[itemId].Name}"))
itemToRemove = itemId;
bool sameQuantityForAllLists = purchaseOption.SameQuantityForAllLists;
if (ImGui.MenuItem("Use same quantity for global and character-specific lists", null,
ref sameQuantityForAllLists))
{
purchaseOption.SameQuantityForAllLists = sameQuantityForAllLists;
Save();
}
if (ImGui.MenuItem($"Remove {_itemLookup[purchaseOption.ItemId].Name}"))
itemToRemove = purchaseOption;
ImGui.EndPopup();
}
@ -166,20 +174,20 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
if (itemToRemove != null)
{
_configuration.ItemsAvailableForPurchase.Remove(itemToRemove.Value);
_configuration.ItemsAvailableToPurchase.Remove(itemToRemove);
Save();
}
if (itemToAdd != null)
{
_configuration.ItemsAvailableForPurchase.Remove(itemToAdd.Value);
_configuration.ItemsAvailableForPurchase.Insert(indexToAdd, itemToAdd.Value);
_configuration.ItemsAvailableToPurchase.Remove(itemToAdd);
_configuration.ItemsAvailableToPurchase.Insert(indexToAdd, itemToAdd);
Save();
}
List<(uint ItemId, string Name, ushort IconId, bool Limited)> comboValues = _gcRewardsCache.Rewards
.Where(x => x.SubCategory is RewardSubCategory.Materials or RewardSubCategory.Materiel)
.Where(x => !_configuration.ItemsAvailableForPurchase.Contains(x.ItemId))
.Where(x => _configuration.ItemsAvailableToPurchase.All(y => y.ItemId != x.ItemId))
.Select(x => (x.ItemId, x.Name, x.IconId, x.Limited))
.OrderBy(x => x.Name)
.ThenBy(x => x.GetHashCode())
@ -209,7 +217,7 @@ internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
$"{item.Name}{(item.Limited ? $" {SeIconChar.Hyadelyn.ToIconString()}" : "")}##SelectVenture{item.IconId}");
if (addThis || addFirst)
{
_configuration.ItemsAvailableForPurchase.Add(item.ItemId);
_configuration.ItemsAvailableToPurchase.Add(new Configuration.PurchaseOption { ItemId = item.ItemId });
if (addFirst)
{

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Numerics;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Keys;
using Dalamud.Game.Text;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Components;
@ -56,6 +57,7 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
private readonly GameFunctions _gameFunctions;
private bool _state;
private Guid? _draggedItem;
public TurnInWindow(DeliverooPlugin plugin, IDalamudPluginInterface pluginInterface, Configuration configuration,
ICondition condition, IClientState clientState, GcRewardsCache gcRewardsCache, ConfigWindow configWindow,
@ -148,13 +150,16 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
.Where(x => x.Reward.RequiredRank <= rank)
.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
{
ItemId = x.Item.ItemId,
Name = x.Reward.Name,
EffectiveLimit = CalculateEffectiveLimit(
x.Item.ItemId,
x.Item.Limit <= 0 ? uint.MaxValue : (uint)x.Item.Limit,
limit <= 0 ? uint.MaxValue : (uint)limit,
x.Reward.StackSize,
x.Reward.InventoryLimit),
SealCost = x.Reward.SealCost,
@ -339,13 +344,20 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
{
(GcRewardItem.None, GcRewardItem.None.Name, GcRewardItem.None.Name),
};
foreach (uint itemId in _configuration.ItemsAvailableForPurchase)
foreach (Configuration.PurchaseOption purchaseOption in _configuration.ItemsAvailableToPurchase)
{
var gcReward = _gcRewardsCache.GetReward(itemId);
int itemCountWithoutRetainers = _gameFunctions.GetItemCount(itemId, false);
int itemCountWithRetainers = _gameFunctions.GetItemCount(itemId, true);
var gcReward = _gcRewardsCache.GetReward(purchaseOption.ItemId);
int itemCountWithoutRetainers = _gameFunctions.GetItemCount(purchaseOption.ItemId, false);
int itemCountWithRetainers = _gameFunctions.GetItemCount(purchaseOption.ItemId, true);
string itemNameWithoutRetainers = gcReward.Name;
string itemNameWithRetainers = gcReward.Name;
if (purchaseOption.SameQuantityForAllLists)
{
itemNameWithoutRetainers += $" {((SeIconChar)57412).ToIconString()}";
itemNameWithRetainers += $" {((SeIconChar)57412).ToIconString()}";
}
if (itemCountWithoutRetainers > 0)
itemNameWithoutRetainers += $" ({itemCountWithoutRetainers:N0})";
if (itemCountWithRetainers > 0)
@ -359,11 +371,89 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
itemsWrapper.Save();
}
int? itemToRemove = null;
Configuration.PurchasePriority? itemToRemove = null;
Configuration.PurchasePriority? itemToAdd = null;
int indexToAdd = 0;
float width = ImGui.GetContentRegionAvail().X;
List<(Vector2 TopLeft, Vector2 BottomRight)> itemPositions = [];
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}");
Configuration.PurchasePriority item = itemsWrapper.GetItemsToPurchase()[i];
@ -437,6 +527,16 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
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,
comboValues.Select(x => item.CheckRetainerInventory ? x.NameWithRetainers : x.NameWithoutRetainers)
.ToArray(), comboValues.Count))
@ -450,48 +550,72 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
if (itemsWrapper.GetItemsToPurchase().Count >= 2)
{
ImGui.SameLine();
if (ImGuiComponents.IconButton($"##Up{i}", FontAwesomeIcon.ArrowUp))
{
itemToAdd = item;
if (i > 0)
indexToAdd = i - 1;
else
indexToAdd = itemsWrapper.GetItemsToPurchase().Count - 1;
}
ImGui.PushFont(UiBuilder.IconFont);
ImGui.SameLine(ImGui.GetContentRegionAvail().X +
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();
ImGui.SameLine(0, 0);
if (ImGuiComponents.IconButton($"##Down{i}", FontAwesomeIcon.ArrowDown))
if (_draggedItem == item.InternalId)
{
itemToAdd = item;
if (i < itemsWrapper.GetItemsToPurchase().Count - 1)
indexToAdd = i + 1;
else
indexToAdd = 0;
ImGuiComponents.IconButton("##Move", FontAwesomeIcon.ArrowsUpDown,
ImGui.ColorConvertU32ToFloat4(ImGui.GetColorU32(ImGuiCol.ButtonActive)));
}
else
ImGuiComponents.IconButton("##Move", FontAwesomeIcon.ArrowsUpDown);
if (_draggedItem == null && ImGui.IsItemActive() && ImGui.IsMouseDragging(ImGuiMouseButton.Left))
_draggedItem = item.InternalId;
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))
itemToRemove = i;
}
itemToRemove = item;
if (enabled)
{
ImGui.Indent(indentX);
if (comboValueIndex > 0)
{
var purchaseOption =
_configuration.ItemsAvailableToPurchase
.Where(x => x.SameQuantityForAllLists)
.FirstOrDefault(x => x.ItemId == item.ItemId);
ImGui.SetNextItemWidth(ImGuiHelpers.GlobalScale * 130);
int limit = Math.Min(item.Limit, (int)comboItem.Item.InventoryLimit);
int limit = Math.Min(purchaseOption?.GlobalLimit ?? item.Limit, (int)comboItem.Item.InventoryLimit);
int stepSize = comboItem.Item.StackSize < 99 ? 1 : 50;
string label = item.Type == Configuration.PurchaseType.KeepStocked
? "Maximum items to buy"
: "Remaining items to buy";
if (ImGui.InputInt(label, ref limit, stepSize, stepSize * 10))
{
item.Limit = Math.Min(Math.Max(0, limit), (int)comboItem.Item.InventoryLimit);
int newLimit = 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();
}
}
}
else if (item.Limit != 0)
{
item.Limit = 0;
@ -516,49 +640,10 @@ internal sealed class TurnInWindow : LWindow, IPersistableWindowConfig
}
ImGui.PopID();
}
if (itemToAdd != null)
{
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;
}
Vector2 bottomRight = new Vector2(topLeft.X + width,
ImGui.GetCursorScreenPos().Y - ImGui.GetStyle().ItemSpacing.Y + 2);
itemPositions.Add((topLeft, bottomRight));
}
private unsafe uint CalculateEffectiveLimit(uint itemId, uint limit, uint stackSize, uint inventoryLimit)