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 Dalamud.Configuration;
using Dalamud.Game.Text;
using Deliveroo.GameData;
namespace Deliveroo;
@ -29,6 +30,23 @@ internal sealed class Configuration : IPluginConfiguration
public uint ItemId { get; set; }
public int Limit { get; set; }
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()

View File

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

View File

@ -38,8 +38,16 @@ partial class DeliverooPlugin
toBuy = Math.Min(toBuy, 99);
}
if (GetItemCount(request.ItemId) + toBuy < request.EffectiveLimit)
return request;
if (request.Type == Configuration.PurchaseType.KeepStocked)
{
if (GetItemCount(request.ItemId) + toBuy < request.EffectiveLimit)
return request;
}
else
{
if (toBuy < request.EffectiveLimit)
return request;
}
}
return null;
@ -139,7 +147,10 @@ partial class DeliverooPlugin
{
_pluginLog.Information($"Selecting item {itemId}, {i}");
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)
toBuy = Math.Min(toBuy, 99);
@ -150,6 +161,7 @@ partial class DeliverooPlugin
return false;
}
item.TemporaryPurchaseQuantity = toBuy;
_chatGui.Print(new SeString(new TextPayload($"Buying {toBuy}x "))
.Append(SeString.CreateItemLink(item.ItemId))
.Append(new TextPayload("...")));

View File

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

View File

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