Add 'purchase once'/'keep stocked' option as in ARC

This commit is contained in:
Liza 2024-01-28 08:15:51 +01:00
parent eea9825723
commit 11420ab403
Signed by: liza
GPG Key ID: 7199F8D727D55F67
6 changed files with 116 additions and 31 deletions

View File

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Dalamud.Configuration; using Dalamud.Configuration;
using Dalamud.Game.Text;
using Deliveroo.GameData; using Deliveroo.GameData;
namespace Deliveroo; namespace Deliveroo;
@ -29,6 +30,23 @@ internal sealed class Configuration : IPluginConfiguration
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;
public PurchaseType Type { get; set; } = PurchaseType.KeepStocked;
public string GetIcon()
{
return Type switch
{
PurchaseType.PurchaseOneTime => SeIconChar.BoxedNumber1.ToIconString(),
PurchaseType.KeepStocked => SeIconChar.Circle.ToIconString(),
_ => SeIconChar.BoxedQuestionMark.ToIconString(),
};
}
}
public enum PurchaseType
{
PurchaseOneTime,
KeepStocked,
} }
public bool AddVentureIfNoItemToPurchaseSelected() public bool AddVentureIfNoItemToPurchaseSelected()

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework> <TargetFramework>net7.0-windows</TargetFramework>
<Version>2.26</Version> <Version>3.0</Version>
<LangVersion>11.0</LangVersion> <LangVersion>11.0</LangVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

View File

@ -38,8 +38,16 @@ partial class DeliverooPlugin
toBuy = Math.Min(toBuy, 99); toBuy = Math.Min(toBuy, 99);
} }
if (GetItemCount(request.ItemId) + toBuy < request.EffectiveLimit) if (request.Type == Configuration.PurchaseType.KeepStocked)
return request; {
if (GetItemCount(request.ItemId) + toBuy < request.EffectiveLimit)
return request;
}
else
{
if (toBuy < request.EffectiveLimit)
return request;
}
} }
return null; return null;
@ -139,7 +147,10 @@ partial class DeliverooPlugin
{ {
_pluginLog.Information($"Selecting item {itemId}, {i}"); _pluginLog.Information($"Selecting item {itemId}, {i}");
long toBuy = (GetCurrentSealCount() - EffectiveReservedSealCount) / item.SealCost; long toBuy = (GetCurrentSealCount() - EffectiveReservedSealCount) / item.SealCost;
toBuy = Math.Min(toBuy, item.EffectiveLimit - GetItemCount(item.ItemId)); if (item.Type == Configuration.PurchaseType.KeepStocked)
toBuy = Math.Min(toBuy, item.EffectiveLimit - GetItemCount(item.ItemId));
else
toBuy = Math.Min(toBuy, item.EffectiveLimit);
if (item.ItemId != ItemIds.Venture && !_configuration.IgnoreCertainLimitations) if (item.ItemId != ItemIds.Venture && !_configuration.IgnoreCertainLimitations)
toBuy = Math.Min(toBuy, 99); toBuy = Math.Min(toBuy, 99);
@ -150,6 +161,7 @@ partial class DeliverooPlugin
return false; return false;
} }
item.TemporaryPurchaseQuantity = toBuy;
_chatGui.Print(new SeString(new TextPayload($"Buying {toBuy}x ")) _chatGui.Print(new SeString(new TextPayload($"Buying {toBuy}x "))
.Append(SeString.CreateItemLink(item.ItemId)) .Append(SeString.CreateItemLink(item.ItemId))
.Append(new TextPayload("..."))); .Append(new TextPayload("...")));

View File

@ -27,9 +27,12 @@ partial class DeliverooPlugin
return; return;
} }
_pluginLog.Information($"Selecting 'yes' ({text})"); _pluginLog.Information($"Selecting 'yes' ({text}) (callback = {item.OnPurchase}, qty = {item.TemporaryPurchaseQuantity})");
addonSelectYesNo->AtkUnitBase.FireCallbackInt(0); addonSelectYesNo->AtkUnitBase.FireCallbackInt(0);
item.OnPurchase?.Invoke((int)item.TemporaryPurchaseQuantity);
item.TemporaryPurchaseQuantity = 0;
var nextItem = GetNextItemToPurchase(item); var nextItem = GetNextItemToPurchase(item);
if (nextItem != null && GetCurrentSealCount() >= EffectiveReservedSealCount + nextItem.SealCost) if (nextItem != null && GetCurrentSealCount() >= EffectiveReservedSealCount + nextItem.SealCost)
CurrentStage = Stage.SelectRewardTier; CurrentStage = Stage.SelectRewardTier;

View File

@ -1,4 +1,5 @@
using Deliveroo.GameData; using System;
using Deliveroo.GameData;
namespace Deliveroo; namespace Deliveroo;
@ -6,9 +7,13 @@ internal sealed class PurchaseItemRequest
{ {
public required uint ItemId { get; init; } public required uint ItemId { get; init; }
public required string Name { get; set; } public required string Name { get; set; }
public required uint EffectiveLimit { get; init; } public required uint EffectiveLimit { get; set; }
public required uint SealCost { get; init; } public required uint SealCost { get; init; }
public required RewardTier Tier { get; init; } public required RewardTier Tier { get; init; }
public required RewardSubCategory SubCategory { get; init; } public required RewardSubCategory SubCategory { get; init; }
public required uint StackSize { get; init; } public required uint StackSize { get; init; }
public required Configuration.PurchaseType Type { get; init; }
public Action<int>? OnPurchase { get; set; }
public long TemporaryPurchaseQuantity { get; set; }
} }

View File

@ -20,7 +20,7 @@ namespace Deliveroo.Windows;
internal sealed class TurnInWindow : LImGui.LWindow internal sealed class TurnInWindow : LImGui.LWindow
{ {
private readonly IReadOnlyList<InventoryType> _inventoryTypes = new[] private static readonly IReadOnlyList<InventoryType> InventoryTypes = new[]
{ {
InventoryType.Inventory1, InventoryType.Inventory1,
InventoryType.Inventory2, InventoryType.Inventory2,
@ -40,6 +40,8 @@ internal sealed class TurnInWindow : LImGui.LWindow
InventoryType.EquippedItems InventoryType.EquippedItems
}.AsReadOnly(); }.AsReadOnly();
private static readonly string[] StockingTypeLabels = { "Purchase Once", "Keep in Stock" };
private readonly DeliverooPlugin _plugin; private readonly DeliverooPlugin _plugin;
private readonly DalamudPluginInterface _pluginInterface; private readonly DalamudPluginInterface _pluginInterface;
private readonly Configuration _configuration; private readonly Configuration _configuration;
@ -116,22 +118,38 @@ internal sealed class TurnInWindow : LImGui.LWindow
return ItemsWrapper.GetItemsToPurchase() return ItemsWrapper.GetItemsToPurchase()
.Where(x => x.ItemId != GcRewardItem.None.ItemId) .Where(x => x.ItemId != GcRewardItem.None.ItemId)
.Where(x => x.Enabled) .Where(x => x.Enabled)
.Where(x => x.Type == Configuration.PurchaseType.KeepStocked || x.Limit > 0)
.Select(x => new { Item = x, Reward = _gcRewardsCache.GetReward(x.ItemId) }) .Select(x => new { Item = x, Reward = _gcRewardsCache.GetReward(x.ItemId) })
.Where(x => x.Reward.GrandCompanies.Contains(grandCompany)) .Where(x => x.Reward.GrandCompanies.Contains(grandCompany))
.Where(x => x.Reward.RequiredRank <= rank) .Where(x => x.Reward.RequiredRank <= rank)
.Select(x => new PurchaseItemRequest .Select(x =>
{ {
ItemId = x.Item.ItemId, var request = new PurchaseItemRequest
Name = x.Reward.Name, {
EffectiveLimit = CalculateEffectiveLimit( ItemId = x.Item.ItemId,
x.Item.ItemId, Name = x.Reward.Name,
x.Item.Limit <= 0 ? uint.MaxValue : (uint)x.Item.Limit, EffectiveLimit = CalculateEffectiveLimit(
x.Reward.StackSize, x.Item.ItemId,
x.Reward.InventoryLimit), x.Item.Limit <= 0 ? uint.MaxValue : (uint)x.Item.Limit,
SealCost = x.Reward.SealCost, x.Reward.StackSize,
Tier = x.Reward.Tier, x.Reward.InventoryLimit),
SubCategory = x.Reward.SubCategory, SealCost = x.Reward.SealCost,
StackSize = x.Reward.StackSize, Tier = x.Reward.Tier,
SubCategory = x.Reward.SubCategory,
StackSize = x.Reward.StackSize,
Type = x.Item.Type,
};
if (x.Item.Type == Configuration.PurchaseType.PurchaseOneTime)
{
request.OnPurchase = qty =>
{
request.EffectiveLimit -= (uint)qty;
x.Item.Limit -= qty;
ItemsWrapper.Save();
};
}
return request;
}) })
.ToList(); .ToList();
} }
@ -153,7 +171,8 @@ internal sealed class TurnInWindow : LImGui.LWindow
ImGui.TextColored(ImGuiColors.DalamudRed, "You do not have the required rank for Expert Delivery."); ImGui.TextColored(ImGuiColors.DalamudRed, "You do not have the required rank for Expert Delivery.");
return; return;
} }
else if (_configuration.BehaviorOnOtherWorld == Configuration.EBehaviorOnOtherWorld.DisableTurnIn && !IsOnHomeWorld) else if (_configuration.BehaviorOnOtherWorld == Configuration.EBehaviorOnOtherWorld.DisableTurnIn &&
!IsOnHomeWorld)
{ {
State = false; State = false;
ImGui.TextColored(ImGuiColors.DalamudRed, "You are not on your home world."); ImGui.TextColored(ImGuiColors.DalamudRed, "You are not on your home world.");
@ -248,17 +267,40 @@ internal sealed class TurnInWindow : LImGui.LWindow
for (int i = 0; i < itemsWrapper.GetItemsToPurchase().Count; ++i) for (int i = 0; i < itemsWrapper.GetItemsToPurchase().Count; ++i)
{ {
ImGui.PushID($"ItemToBuy{i}"); ImGui.PushID($"ItemToBuy{i}");
var item = itemsWrapper.GetItemsToPurchase()[i]; Configuration.PurchasePriority item = itemsWrapper.GetItemsToPurchase()[i];
float indentX = ImGui.GetCursorPosX();
bool enabled = item.Enabled; bool enabled = item.Enabled;
ImGui.PushID($"Enable{i}"); int popColors = 0;
if (ImGui.Checkbox("", ref enabled)) if (!enabled)
{ {
item.Enabled = enabled; ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1f, 0.5f, 0.35f, 1f));
itemsWrapper.Save(); popColors++;
} }
ImGui.PopID(); if (ImGui.Button($"{item.GetIcon()}"))
ImGui.OpenPopup($"Configure{i}");
ImGui.PopStyleColor(popColors);
if (ImGui.BeginPopup($"Configure{i}"))
{
if (ImGui.Checkbox($"Enabled##Enabled{i}", ref enabled))
{
item.Enabled = enabled;
itemsWrapper.Save();
}
ImGui.SetNextItemWidth(150 * ImGuiHelpers.GlobalScale);
int type = (int)item.Type;
if (ImGui.Combo($"##Type{i}", ref type, StockingTypeLabels, StockingTypeLabels.Length))
{
item.Type = (Configuration.PurchaseType)type;
itemsWrapper.Save();
}
ImGui.EndPopup();
}
ImGui.SameLine(0, 3); ImGui.SameLine(0, 3);
ImGui.BeginDisabled(!enabled); ImGui.BeginDisabled(!enabled);
@ -280,6 +322,8 @@ internal sealed class TurnInWindow : LImGui.LWindow
ImGui.SameLine(0, 3); ImGui.SameLine(0, 3);
} }
indentX = ImGui.GetCursorPosX() - indentX;
if (ImGui.Combo("", ref comboValueIndex, comboValues.Select(x => x.Name).ToArray(), comboValues.Count)) if (ImGui.Combo("", ref comboValueIndex, comboValues.Select(x => x.Name).ToArray(), comboValues.Count))
{ {
comboItem = comboValues[comboValueIndex]; comboItem = comboValues[comboValueIndex];
@ -318,13 +362,16 @@ internal sealed class TurnInWindow : LImGui.LWindow
if (enabled) if (enabled)
{ {
ImGui.Indent(52); ImGui.Indent(indentX);
if (comboValueIndex > 0) if (comboValueIndex > 0)
{ {
ImGui.SetNextItemWidth(ImGuiHelpers.GlobalScale * 130); ImGui.SetNextItemWidth(ImGuiHelpers.GlobalScale * 130);
int limit = Math.Min(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;
if (ImGui.InputInt("Maximum items to buy", ref limit, stepSize, stepSize * 10)) 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); item.Limit = Math.Min(Math.Max(0, limit), (int)comboItem.Item.InventoryLimit);
itemsWrapper.Save(); itemsWrapper.Save();
@ -350,7 +397,7 @@ internal sealed class TurnInWindow : LImGui.LWindow
} }
} }
ImGui.Unindent(52); ImGui.Unindent(indentX);
} }
ImGui.PopID(); ImGui.PopID();
@ -403,7 +450,7 @@ internal sealed class TurnInWindow : LImGui.LWindow
{ {
uint slotsThatCanBeUsed = 0; uint slotsThatCanBeUsed = 0;
InventoryManager* inventoryManager = InventoryManager.Instance(); InventoryManager* inventoryManager = InventoryManager.Instance();
foreach (var inventoryType in _inventoryTypes) foreach (var inventoryType in InventoryTypes)
{ {
var container = inventoryManager->GetInventoryContainer(inventoryType); var container = inventoryManager->GetInventoryContainer(inventoryType);
for (int i = 0; i < container->Size; ++i) for (int i = 0; i < container->Size; ++i)