Basic Saddlebags

This commit is contained in:
Zeffuro
2025-12-30 01:25:57 +01:00
parent acdd79f73a
commit 5f73a47fee
9 changed files with 81 additions and 9 deletions
@@ -17,7 +17,8 @@ public class InventoryLifecycles : IDisposable
public InventoryLifecycles()
{
Services.AddonLifecycle.RegisterListener(AddonEvent.PreRefresh, ["Inventory", "InventoryLarge", "InventoryExpansion"], PreRefreshHandler);
Services.AddonLifecycle.RegisterListener(AddonEvent.PreRefresh, ["Inventory", "InventoryLarge", "InventoryExpansion"], InventoryPreRefreshHandler);
Services.AddonLifecycle.RegisterListener(AddonEvent.PreRefresh, ["InventoryBuddy"], InventoryBuddyPreRefreshHandler);
Services.Logger.Verbose("InventoryLifecycles initialized");
}
@@ -32,7 +33,7 @@ public class InventoryLifecycles : IDisposable
values[7] = can use Saddlebags (Agent InventoryBuddy IsActivatable)
*/
private unsafe void PreRefreshHandler(AddonEvent type, AddonArgs args)
private unsafe void InventoryPreRefreshHandler(AddonEvent type, AddonArgs args)
{
if (args is not AddonRefreshArgs refreshArgs)
return;
@@ -69,8 +70,23 @@ public class InventoryLifecycles : IDisposable
}
}
private void InventoryBuddyPreRefreshHandler(AddonEvent type, AddonArgs args)
{
if (args is not AddonRefreshArgs refreshArgs)
return;
GeneralSettings config = System.Config.General;
if (config.HideGameSaddleBags) refreshArgs.AtkValueCount = 0;
if (config.OpenSaddleBagsWithGameInventory)
{
System.AddonSaddleBagWindow.Toggle();
}
}
public void Dispose()
{
Services.AddonLifecycle.UnregisterListener(AddonEvent.PreRefresh, ["Inventory", "InventoryLarge", "InventoryExpansion"]);
Services.AddonLifecycle.UnregisterListener(AddonEvent.PreRefresh, ["InventoryBuddy"]);
}
}
+25
View File
@@ -7,6 +7,7 @@ using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Component.GUI;
using KamiToolKit.Classes;
using KamiToolKit.Nodes;
namespace AetherBags.Addons;
@@ -14,16 +15,20 @@ namespace AetherBags.Addons;
public unsafe class AddonSaddleBagWindow : InventoryAddonBase
{
private readonly SaddleBagState _inventoryState = new();
private TextNode _slotCounterNode = null!;
protected override InventoryStateBase InventoryState => _inventoryState;
protected override bool HasFooter => false;
protected override bool HasSlotCounter => true;
protected override float MinWindowWidth => 400;
protected override float MaxWindowWidth => 600;
protected override void OnSetup(AtkUnitBase* addon)
{
WindowNode?.AddColor = new Vector3(-16f / 255f, -4f / 255f, 8f / 255f);
CategoriesNode = new WrappingGridNode<InventoryCategoryNode>
{
Position = ContentStartPosition,
@@ -64,6 +69,19 @@ public unsafe class AddonSaddleBagWindow : InventoryAddonBase
};
SettingsButtonNode.AttachNode(this);
_slotCounterNode = new TextNode
{
Position = new Vector2(Size.X - 10, 0),
Size = new Vector2(82, 20),
AlignmentType = AlignmentType.Right,
FontType = FontType.MiedingerMed,
TextFlags = TextFlags.Glare,
TextColor = ColorHelper.GetColor(50),
TextOutlineColor = ColorHelper.GetColor(32) // Could also be Color 65
};
_slotCounterNode.AttachNode(this);
SlotCounterNode = _slotCounterNode;
LayoutContent();
Services.AddonLifecycle.RegisterListener(AddonEvent.PostRequestedUpdate, "InventoryBuddy", OnSaddleBagUpdate);
@@ -74,6 +92,13 @@ public unsafe class AddonSaddleBagWindow : InventoryAddonBase
base.OnSetup(addon);
}
protected override void RefreshCategoriesCore(bool autosize)
{
_slotCounterNode.String = _inventoryState.GetEmptySlotsString();
base.RefreshCategoriesCore(autosize);
}
protected override void OnUpdate(AtkUnitBase* addon)
{
if (RefreshQueued)
+11 -3
View File
@@ -21,6 +21,7 @@ public abstract unsafe class InventoryAddonBase : NativeAddon
protected WrappingGridNode<InventoryCategoryNode> CategoriesNode = null!;
protected TextInputWithHintNode SearchInputNode = null!;
protected InventoryFooterNode FooterNode = null!;
protected TextNode? SlotCounterNode { get; set; }
protected CircleButtonNode SettingsButtonNode = null!;
protected virtual float MinWindowWidth => 600;
@@ -41,6 +42,7 @@ public abstract unsafe class InventoryAddonBase : NativeAddon
protected virtual bool HasFooter => true;
protected virtual bool HasPinning => true;
protected virtual bool HasSlotCounter => false;
public void ManualInventoryRefresh()
{
@@ -127,10 +129,16 @@ public abstract unsafe class InventoryAddonBase : NativeAddon
Vector2 contentPos = ContentStartPosition;
Vector2 contentSize = ContentSize;
float footerH = HasFooter || HasSlotCounter ? FooterHeight : 0;
if (HasFooter)
{
FooterNode.Position = new Vector2(contentPos.X, contentPos.Y + contentSize.Y - FooterHeight);
FooterNode.Size = new Vector2(contentSize.X, FooterHeight);
FooterNode.Position = new Vector2(contentPos.X, contentPos.Y + contentSize.Y - footerH);
FooterNode.Size = new Vector2(contentSize.X, footerH);
}
else if (HasSlotCounter && SlotCounterNode != null)
{
SlotCounterNode.Position = new Vector2(contentSize.X -80f, contentPos.Y + contentSize.Y - footerH + 4f);
}
float gridH = contentSize.Y - (HasFooter ? FooterHeight + FooterTopSpacing : 0);
@@ -168,7 +176,7 @@ public abstract unsafe class InventoryAddonBase : NativeAddon
float contentWidth = finalWidth - (ContentStartPosition.X * 2);
float footerSpace = HasFooter ? FooterHeight + FooterTopSpacing : 0;
float footerSpace = HasFooter || HasSlotCounter ? FooterHeight + FooterTopSpacing : 0;
float gridBudget = Math.Max(0f, MaxWindowHeight - footerSpace);
CategoriesNode.Position = ContentStartPosition;
@@ -10,6 +10,8 @@ public class GeneralSettings
public bool CompactStableInsert { get; set; } = true;
public bool OpenWithGameInventory { get; set; } = true;
public bool HideGameInventory { get; set; } = false;
public bool OpenSaddleBagsWithGameInventory { get; set; } = true;
public bool HideGameSaddleBags { get; set; } = false;
public bool ShowCategoryItemCount { get; set; } = false;
public bool LinkItemEnabled { get; set; } = false;
}
@@ -115,6 +115,9 @@ public static unsafe class InventoryItemExtensions {
if (InventoryManager.Instance()->GetInventoryItemCount(itemId, true) > 0)
itemId += 1_000_000;
if (!item.Container.IsMainInventory)
return;
AgentInventoryContext.Instance()->UseItem(itemId, type);
}
}
@@ -165,6 +165,8 @@ public static unsafe class InventoryTypeExtensions
_ => 0,
};
public bool IsLoaded => InventoryManager.Instance()->GetInventoryContainer(inventoryType)->IsLoaded;
public bool IsSameContainerGroup(InventoryType other)
=> inventoryType.ContainerGroup == other.ContainerGroup;
@@ -4,7 +4,6 @@ namespace AetherBags. Helpers;
public static unsafe class InventoryMoveHelper
{
// Requires the visual UI slots instead of actual slots.
public static void MoveItem(InventoryType sourceContainer, ushort sourceSlot, InventoryType destContainer, ushort destSlot)
{
Services.Logger.Debug($"[MoveItem] {sourceContainer}@{sourceSlot} -> {destContainer}@{destSlot}");
@@ -266,17 +266,20 @@ public class InventoryCategoryNode : SimpleComponentNode
private void OnPayloadAccepted(DragDropNode node, DragDropPayload payload, ItemInfo targetItemInfo)
{
InventoryItem item = targetItemInfo.Item;
if (!payload.IsValidInventoryPayload)
if (! payload.IsValidInventoryPayload)
{
Services.Logger.Warning($"[OnPayload] Invalid payload type: {payload.Type}");
return;
}
// Debug: log raw payload values
Services. Logger.Debug($"[OnPayload] Raw payload: Type={payload.Type} Int1={payload.Int1} Int2={payload.Int2}");
InventoryLocation sourceLocation = payload.InventoryLocation;
if (!sourceLocation.IsValid)
if (! sourceLocation.IsValid)
{
Services.Logger.Warning($"[OnPayload] Could not resolve source from payload");
Services.Logger. Warning($"[OnPayload] Could not resolve source from payload");
return;
}
@@ -285,6 +288,11 @@ public class InventoryCategoryNode : SimpleComponentNode
(ushort)item.Slot
);
// Debug: log resolved locations
Services.Logger.Debug($"[OnPayload] Source: {sourceLocation. Container} @ {sourceLocation. Slot}");
Services.Logger.Debug($"[OnPayload] Target: {targetLocation.Container} @ {targetLocation.Slot}");
if (sourceLocation.Container.IsSameContainerGroup(targetLocation.Container))
{
Services.Logger.Debug($"[OnPayload] Source and target are in the same container group; no move performed");
@@ -294,6 +302,12 @@ public class InventoryCategoryNode : SimpleComponentNode
return;
};
if (!sourceLocation.Container.IsLoaded || !targetLocation.Container.IsLoaded)
{
Services.Logger.Debug($"[OnPayload] Source or target container is not loaded; cannot move");
return;
}
Services.Logger.Debug($"[OnPayload] Moving {sourceLocation} -> {targetLocation}");
InventoryMoveHelper.MoveItem(
+3
View File
@@ -80,6 +80,8 @@ public unsafe class Plugin : IDalamudPlugin
_commandHandler.Dispose();
System.AddonInventoryWindow.Dispose();
System.AddonSaddleBagWindow.Dispose();
//System.AddonRetainerWindow.Dispose();
System.AddonConfigurationWindow.Dispose();
KamiToolKitLibrary.Dispose();
@@ -104,6 +106,7 @@ public unsafe class Plugin : IDalamudPlugin
Util.SaveConfig(System.Config);
InventoryState.TrackLootedItems = false;
System.AddonInventoryWindow.Close();
System.AddonSaddleBagWindow.Close();
System.AddonConfigurationWindow.Close();
}
}