namespace AcDream.Core.Items;
///
/// Retail paperdoll body-part selection. Ports
/// InventoryPlacement::DetermineHigherPriority @ 0x004A44B0 and
/// gmPaperDollUI::GetUpperInvObj @ 0x004A4750.
///
public static class PaperdollSelectionPolicy
{
///
/// Returns the visually upper equipped object covering .
/// When the body part is valid but uncovered, retail returns the player object itself.
///
public static uint GetUpperInventoryObject(
ClientObjectTable objects,
uint playerId,
EquipMask bodyLocationMask)
{
if (playerId == 0 || bodyLocationMask == EquipMask.None || objects.Get(playerId) is null)
return 0;
ClientObject? winner = null;
foreach (ClientObject candidate in objects.Objects)
{
if ((candidate.CurrentlyEquippedLocation & bodyLocationMask) == EquipMask.None)
continue;
if (candidate.WielderId != playerId && candidate.ContainerId != playerId)
continue;
if (winner is null
|| EffectivePriority(candidate, bodyLocationMask)
> EffectivePriority(winner, bodyLocationMask))
winner = candidate;
}
return winner?.ObjectId ?? playerId;
}
private static uint EffectivePriority(ClientObject item, EquipMask bodyLocationMask)
{
uint priority = item.Priority;
uint coveredLocation = (uint)(item.CurrentlyEquippedLocation & bodyLocationMask);
if (priority == 0 && coveredLocation is >= 0x200u and <= 0x4000u)
priority = 0x7Fu;
return priority;
}
}