Give retained buttons a reusable item-drop seam, wire the toolbar backpack target, and port retail stack-merge legality, capacity clamping, wire dispatch, destination selection, and immediate shortcut rekey notice. Record the live ACE merge gate and keep split quantity under AP-101. Co-Authored-By: Codex <codex@openai.com>
49 lines
1.6 KiB
C#
49 lines
1.6 KiB
C#
using System;
|
|
|
|
namespace AcDream.Core.Items;
|
|
|
|
public readonly record struct StackMergeItem(
|
|
uint ObjectId,
|
|
uint WeenieClassId,
|
|
int StackSize,
|
|
int MaxStackSize,
|
|
int TradeState);
|
|
|
|
public readonly record struct StackMergePlan(uint SourceObjectId, uint TargetObjectId, uint Amount);
|
|
|
|
/// <summary>
|
|
/// Pure port of <c>ItemHolder::IsMergeAttemptLegal @ 0x00586F30</c> and the
|
|
/// transfer-size branch in <c>ItemHolder::AttemptMerge @ 0x005878F0</c>.
|
|
/// </summary>
|
|
public static class StackMergePlanner
|
|
{
|
|
public static StackMergePlan? Plan(
|
|
in StackMergeItem source,
|
|
in StackMergeItem target,
|
|
bool readyForInventoryRequest,
|
|
int requestedAmount)
|
|
{
|
|
if (!readyForInventoryRequest
|
|
|| source.ObjectId == 0
|
|
|| target.ObjectId == 0
|
|
|| source.ObjectId == target.ObjectId
|
|
|| source.MaxStackSize <= 1
|
|
|| target.MaxStackSize <= 1
|
|
|| source.TradeState == 1
|
|
|| target.TradeState == 1
|
|
|| source.WeenieClassId != target.WeenieClassId)
|
|
return null;
|
|
|
|
int targetSize = Math.Max(1, target.StackSize);
|
|
int available = target.MaxStackSize - targetSize;
|
|
if (available <= 0)
|
|
return null;
|
|
|
|
int sourceSize = Math.Max(1, source.StackSize);
|
|
int desired = requestedAmount > 0 ? Math.Min(requestedAmount, sourceSize) : sourceSize;
|
|
uint transfer = (uint)Math.Min(desired, available);
|
|
return transfer == 0
|
|
? null
|
|
: new StackMergePlan(source.ObjectId, target.ObjectId, transfer);
|
|
}
|
|
}
|