Basic Saddlebags
This commit is contained in:
@@ -17,7 +17,8 @@ public class InventoryLifecycles : IDisposable
|
|||||||
|
|
||||||
public InventoryLifecycles()
|
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");
|
Services.Logger.Verbose("InventoryLifecycles initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ public class InventoryLifecycles : IDisposable
|
|||||||
values[7] = can use Saddlebags (Agent InventoryBuddy IsActivatable)
|
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)
|
if (args is not AddonRefreshArgs refreshArgs)
|
||||||
return;
|
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()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Services.AddonLifecycle.UnregisterListener(AddonEvent.PreRefresh, ["Inventory", "InventoryLarge", "InventoryExpansion"]);
|
Services.AddonLifecycle.UnregisterListener(AddonEvent.PreRefresh, ["Inventory", "InventoryLarge", "InventoryExpansion"]);
|
||||||
|
Services.AddonLifecycle.UnregisterListener(AddonEvent.PreRefresh, ["InventoryBuddy"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ using Dalamud.Game.Addon.Lifecycle;
|
|||||||
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
|
using KamiToolKit.Classes;
|
||||||
using KamiToolKit.Nodes;
|
using KamiToolKit.Nodes;
|
||||||
|
|
||||||
namespace AetherBags.Addons;
|
namespace AetherBags.Addons;
|
||||||
@@ -14,16 +15,20 @@ namespace AetherBags.Addons;
|
|||||||
public unsafe class AddonSaddleBagWindow : InventoryAddonBase
|
public unsafe class AddonSaddleBagWindow : InventoryAddonBase
|
||||||
{
|
{
|
||||||
private readonly SaddleBagState _inventoryState = new();
|
private readonly SaddleBagState _inventoryState = new();
|
||||||
|
private TextNode _slotCounterNode = null!;
|
||||||
|
|
||||||
protected override InventoryStateBase InventoryState => _inventoryState;
|
protected override InventoryStateBase InventoryState => _inventoryState;
|
||||||
|
|
||||||
protected override bool HasFooter => false;
|
protected override bool HasFooter => false;
|
||||||
|
protected override bool HasSlotCounter => true;
|
||||||
|
|
||||||
protected override float MinWindowWidth => 400;
|
protected override float MinWindowWidth => 400;
|
||||||
protected override float MaxWindowWidth => 600;
|
protected override float MaxWindowWidth => 600;
|
||||||
|
|
||||||
protected override void OnSetup(AtkUnitBase* addon)
|
protected override void OnSetup(AtkUnitBase* addon)
|
||||||
{
|
{
|
||||||
|
WindowNode?.AddColor = new Vector3(-16f / 255f, -4f / 255f, 8f / 255f);
|
||||||
|
|
||||||
CategoriesNode = new WrappingGridNode<InventoryCategoryNode>
|
CategoriesNode = new WrappingGridNode<InventoryCategoryNode>
|
||||||
{
|
{
|
||||||
Position = ContentStartPosition,
|
Position = ContentStartPosition,
|
||||||
@@ -64,6 +69,19 @@ public unsafe class AddonSaddleBagWindow : InventoryAddonBase
|
|||||||
};
|
};
|
||||||
SettingsButtonNode.AttachNode(this);
|
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();
|
LayoutContent();
|
||||||
|
|
||||||
Services.AddonLifecycle.RegisterListener(AddonEvent.PostRequestedUpdate, "InventoryBuddy", OnSaddleBagUpdate);
|
Services.AddonLifecycle.RegisterListener(AddonEvent.PostRequestedUpdate, "InventoryBuddy", OnSaddleBagUpdate);
|
||||||
@@ -74,6 +92,13 @@ public unsafe class AddonSaddleBagWindow : InventoryAddonBase
|
|||||||
base.OnSetup(addon);
|
base.OnSetup(addon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void RefreshCategoriesCore(bool autosize)
|
||||||
|
{
|
||||||
|
_slotCounterNode.String = _inventoryState.GetEmptySlotsString();
|
||||||
|
|
||||||
|
base.RefreshCategoriesCore(autosize);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnUpdate(AtkUnitBase* addon)
|
protected override void OnUpdate(AtkUnitBase* addon)
|
||||||
{
|
{
|
||||||
if (RefreshQueued)
|
if (RefreshQueued)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public abstract unsafe class InventoryAddonBase : NativeAddon
|
|||||||
protected WrappingGridNode<InventoryCategoryNode> CategoriesNode = null!;
|
protected WrappingGridNode<InventoryCategoryNode> CategoriesNode = null!;
|
||||||
protected TextInputWithHintNode SearchInputNode = null!;
|
protected TextInputWithHintNode SearchInputNode = null!;
|
||||||
protected InventoryFooterNode FooterNode = null!;
|
protected InventoryFooterNode FooterNode = null!;
|
||||||
|
protected TextNode? SlotCounterNode { get; set; }
|
||||||
protected CircleButtonNode SettingsButtonNode = null!;
|
protected CircleButtonNode SettingsButtonNode = null!;
|
||||||
|
|
||||||
protected virtual float MinWindowWidth => 600;
|
protected virtual float MinWindowWidth => 600;
|
||||||
@@ -41,6 +42,7 @@ public abstract unsafe class InventoryAddonBase : NativeAddon
|
|||||||
|
|
||||||
protected virtual bool HasFooter => true;
|
protected virtual bool HasFooter => true;
|
||||||
protected virtual bool HasPinning => true;
|
protected virtual bool HasPinning => true;
|
||||||
|
protected virtual bool HasSlotCounter => false;
|
||||||
|
|
||||||
public void ManualInventoryRefresh()
|
public void ManualInventoryRefresh()
|
||||||
{
|
{
|
||||||
@@ -127,10 +129,16 @@ public abstract unsafe class InventoryAddonBase : NativeAddon
|
|||||||
Vector2 contentPos = ContentStartPosition;
|
Vector2 contentPos = ContentStartPosition;
|
||||||
Vector2 contentSize = ContentSize;
|
Vector2 contentSize = ContentSize;
|
||||||
|
|
||||||
|
float footerH = HasFooter || HasSlotCounter ? FooterHeight : 0;
|
||||||
|
|
||||||
if (HasFooter)
|
if (HasFooter)
|
||||||
{
|
{
|
||||||
FooterNode.Position = new Vector2(contentPos.X, contentPos.Y + contentSize.Y - FooterHeight);
|
FooterNode.Position = new Vector2(contentPos.X, contentPos.Y + contentSize.Y - footerH);
|
||||||
FooterNode.Size = new Vector2(contentSize.X, FooterHeight);
|
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);
|
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 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);
|
float gridBudget = Math.Max(0f, MaxWindowHeight - footerSpace);
|
||||||
|
|
||||||
CategoriesNode.Position = ContentStartPosition;
|
CategoriesNode.Position = ContentStartPosition;
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ public class GeneralSettings
|
|||||||
public bool CompactStableInsert { get; set; } = true;
|
public bool CompactStableInsert { get; set; } = true;
|
||||||
public bool OpenWithGameInventory { get; set; } = true;
|
public bool OpenWithGameInventory { get; set; } = true;
|
||||||
public bool HideGameInventory { get; set; } = false;
|
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 ShowCategoryItemCount { get; set; } = false;
|
||||||
public bool LinkItemEnabled { 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)
|
if (InventoryManager.Instance()->GetInventoryItemCount(itemId, true) > 0)
|
||||||
itemId += 1_000_000;
|
itemId += 1_000_000;
|
||||||
|
|
||||||
|
if (!item.Container.IsMainInventory)
|
||||||
|
return;
|
||||||
|
|
||||||
AgentInventoryContext.Instance()->UseItem(itemId, type);
|
AgentInventoryContext.Instance()->UseItem(itemId, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ public static unsafe class InventoryTypeExtensions
|
|||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public bool IsLoaded => InventoryManager.Instance()->GetInventoryContainer(inventoryType)->IsLoaded;
|
||||||
|
|
||||||
public bool IsSameContainerGroup(InventoryType other)
|
public bool IsSameContainerGroup(InventoryType other)
|
||||||
=> inventoryType.ContainerGroup == other.ContainerGroup;
|
=> inventoryType.ContainerGroup == other.ContainerGroup;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ namespace AetherBags. Helpers;
|
|||||||
|
|
||||||
public static unsafe class InventoryMoveHelper
|
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)
|
public static void MoveItem(InventoryType sourceContainer, ushort sourceSlot, InventoryType destContainer, ushort destSlot)
|
||||||
{
|
{
|
||||||
Services.Logger.Debug($"[MoveItem] {sourceContainer}@{sourceSlot} -> {destContainer}@{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)
|
private void OnPayloadAccepted(DragDropNode node, DragDropPayload payload, ItemInfo targetItemInfo)
|
||||||
{
|
{
|
||||||
InventoryItem item = targetItemInfo.Item;
|
InventoryItem item = targetItemInfo.Item;
|
||||||
if (!payload.IsValidInventoryPayload)
|
if (! payload.IsValidInventoryPayload)
|
||||||
{
|
{
|
||||||
Services.Logger.Warning($"[OnPayload] Invalid payload type: {payload.Type}");
|
Services.Logger.Warning($"[OnPayload] Invalid payload type: {payload.Type}");
|
||||||
return;
|
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;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,6 +288,11 @@ public class InventoryCategoryNode : SimpleComponentNode
|
|||||||
(ushort)item.Slot
|
(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))
|
if (sourceLocation.Container.IsSameContainerGroup(targetLocation.Container))
|
||||||
{
|
{
|
||||||
Services.Logger.Debug($"[OnPayload] Source and target are in the same container group; no move performed");
|
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;
|
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}");
|
Services.Logger.Debug($"[OnPayload] Moving {sourceLocation} -> {targetLocation}");
|
||||||
|
|
||||||
InventoryMoveHelper.MoveItem(
|
InventoryMoveHelper.MoveItem(
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ public unsafe class Plugin : IDalamudPlugin
|
|||||||
_commandHandler.Dispose();
|
_commandHandler.Dispose();
|
||||||
|
|
||||||
System.AddonInventoryWindow.Dispose();
|
System.AddonInventoryWindow.Dispose();
|
||||||
|
System.AddonSaddleBagWindow.Dispose();
|
||||||
|
//System.AddonRetainerWindow.Dispose();
|
||||||
System.AddonConfigurationWindow.Dispose();
|
System.AddonConfigurationWindow.Dispose();
|
||||||
|
|
||||||
KamiToolKitLibrary.Dispose();
|
KamiToolKitLibrary.Dispose();
|
||||||
@@ -104,6 +106,7 @@ public unsafe class Plugin : IDalamudPlugin
|
|||||||
Util.SaveConfig(System.Config);
|
Util.SaveConfig(System.Config);
|
||||||
InventoryState.TrackLootedItems = false;
|
InventoryState.TrackLootedItems = false;
|
||||||
System.AddonInventoryWindow.Close();
|
System.AddonInventoryWindow.Close();
|
||||||
|
System.AddonSaddleBagWindow.Close();
|
||||||
System.AddonConfigurationWindow.Close();
|
System.AddonConfigurationWindow.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user