Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .jules/scribe.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@
## 2026-06-24 - [RemoteAgents] Learning: "Dawn" is the internal game name for the Duty Support and Trust systems. Action: When documenting "Dawn" related agents or offsets, explicitly reference both Duty Support and Trust to ensure clarity for developers familiar with the in-game terminology.
## 2026-06-25 - [AetherialWheel] Learning: FC Aetherial Wheel data includes multiple item IDs (Starting, Current, Resulting) to track the transformation of a wheel as it primes. Action: When documenting aetherial wheel structures, distinguish between the unprimed source item and the final primed result to clarify the priming lifecycle.
## 2026-07-20 - [TripleTriadExchange] Learning: Triple Triad cards are exchanged for Manderville Gold Saucer Points (MGP), which are distinct from Grand Company Seals/Coins. Action: Always verify currency types in exchange interfaces to ensure accurate domain terminology.
## 2026-07-25 - [AgentWorldTravelSelect] Learning: World travel choice lists use region-specific skip logic (0 for Traditional Chinese, 1 for others) to filter the player's home world from the selection array. Action: When documenting world selection arrays, note the region-dependent filtering of the home world.
## 2026-07-25 - [AgentFreeCompany] Learning: The Free Company member roster is traversed using a 0x60-byte stride from a pointer resolved via a nested chain (Pointer + 0x48 -> + 0x98). Action: Clarify roster traversal logic and specific member data offsets (0x22 for name, 0xD for online status) in documentation to aid debugging of roster-related issues.
2 changes: 1 addition & 1 deletion LastCommit.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2026-06-30T16:03:22-04:00
2026-07-05T23:22:25-04:00
24 changes: 21 additions & 3 deletions RemoteAgents/AgentBankaCraftworksSupply.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,39 @@
namespace LlamaLibrary.RemoteAgents;


/// <summary>
/// Remote agent for the Banka Craftworks item submission interface.
/// Facilitates the hand-in of crafted items for the Banka Craftworks system.
/// </summary>
public class AgentBankaCraftworksSupply : AgentInterface<AgentBankaCraftworksSupply>, IAgent
{


/// <summary>
/// Initializes a new instance of the <see cref="AgentBankaCraftworksSupply"/> class.
/// </summary>
/// <param name="pointer">The memory address of the agent.</param>
protected AgentBankaCraftworksSupply(IntPtr pointer) : base(pointer)
{
}

/// <inheritdoc/>
public IntPtr RegisteredVtable => AgentBankaCraftworksSupplyOffsets.Vtable;

/// <summary>
/// Gets the memory pointer to the primary instance of the craftworks supply data.
/// </summary>
public IntPtr InstancePointer
{
get
{
var temp1 = Core.Memory.Read<IntPtr>(Pointer ) ;
var temp1 = Core.Memory.Read<IntPtr>(Pointer);
return temp1;
}
}

/// <summary>
/// Gets the memory pointer to the craftworks supply data, adjusted by the system-defined offset.
/// Used as the target for the hand-in function call.
/// </summary>
public IntPtr InstancePointerWithOffset
{
get
Expand All @@ -35,6 +49,10 @@ public IntPtr InstancePointerWithOffset
}
}

/// <summary>
/// Hands in the specified <see cref="BagSlot"/> to the Banka Craftworks interface.
/// </summary>
/// <param name="slot">The inventory slot containing the item to be handed in.</param>
public void HandIn(BagSlot slot)
{
//var instance = Core.Memory.Read<IntPtr>(Pointer) + Offsets.PointerOffset;
Expand Down
23 changes: 21 additions & 2 deletions RemoteAgents/AgentDawnStory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,23 @@

namespace LlamaLibrary.RemoteAgents
{
/// <summary>
/// Remote agent for the "Dawn Story" (Duty Support Story Mode) interface.
/// Manages the list of available duties and the selection of a specific duty for story progression.
/// </summary>
public class AgentDawnStory : AgentInterface<AgentDawnStory>, IAgent
{
/// <inheritdoc/>
public IntPtr RegisteredVtable => AgentDawnStoryOffsets.Vtable;



/// <summary>
/// Gets a value indicating whether the duty list has been successfully loaded from the game's data.
/// </summary>
public bool IsLoaded => Core.Memory.Read<byte>(Pointer + AgentDawnStoryOffsets.Loaded) != 0;

/// <summary>
/// Gets the memory pointer to the beginning of the duty information array.
/// </summary>
public IntPtr DutyArrayPtr
{
get
Expand All @@ -25,12 +34,22 @@ public IntPtr DutyArrayPtr
}
}

/// <summary>
/// Gets an array of <see cref="DutyInfo"/> structures representing the duties available in the story mode.
/// </summary>
public DutyInfo[] Duties => Core.Memory.ReadArray<DutyInfo>(DutyArrayPtr, AgentDawnStoryOffsets.DutyCount);

/// <summary>
/// Initializes a new instance of the <see cref="AgentDawnStory"/> class.
/// </summary>
/// <param name="pointer">The memory address of the agent.</param>
protected AgentDawnStory(IntPtr pointer) : base(pointer)
{
}

/// <summary>
/// Gets the index of the currently selected duty in the interface.
/// </summary>
public byte SelectedDuty => Core.Memory.Read<byte>(Pointer + 0x28);
}
}
82 changes: 74 additions & 8 deletions RemoteAgents/AgentFishGuide2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,82 @@

namespace LlamaLibrary.RemoteAgents
{
/// <summary>
/// Remote agent for the fishing guide (log) interface.
/// Provides access to the player's fishing history, including which fish have been caught.
/// </summary>
public class AgentFishGuide2 : AgentInterface<AgentFishGuide2>, IAgent
{
/// <inheritdoc/>
public IntPtr RegisteredVtable => AgentFishGuide2Offsets.Vtable;

/// <summary>
/// The total number of tabs in the fishing guide.
/// </summary>
public const int TabCount = 37;



/// <summary>
/// Initializes a new instance of the <see cref="AgentFishGuide2"/> class.
/// </summary>
/// <param name="pointer">The memory address of the agent.</param>
protected AgentFishGuide2(IntPtr pointer) : base(pointer)
{
}

/// <summary>
/// Gets the memory pointer to the fishing guide's information block.
/// </summary>
public IntPtr InfoPointer => Core.Memory.Read<IntPtr>(Pointer + AgentFishGuide2Offsets.InfoOffset);

/// <summary>
/// Gets the memory pointer to the beginning of the fish list array.
/// </summary>
public IntPtr StartingPointer => Core.Memory.Read<IntPtr>(InfoPointer + AgentFishGuide2Offsets.StartingPointer);

/// <summary>
/// Gets the memory pointer to the end of the fish list array.
/// </summary>
public IntPtr EndingPointer => Core.Memory.Read<IntPtr>(InfoPointer + AgentFishGuide2Offsets.EndingPointer);

/// <summary>
/// Gets the memory pointer to a specific position in the fish list array.
/// </summary>
/// <param name="start">The zero-based index to start from.</param>
/// <returns>An <see cref="IntPtr"/> to the specified fish list entry.</returns>
public IntPtr FishListPointer(int start = 0) => Core.Memory.Read<IntPtr>(StartingPointer + (8 * start));

/// <summary>
/// Gets the total number of fish entries (slots) available in the current fishing guide view.
/// </summary>
public int SlotCount => (int)((EndingPointer.ToInt64() - StartingPointer.ToInt64()) / 8);

/// <summary>
/// Retrieves the entire fish list from game memory.
/// </summary>
/// <returns>An array of <see cref="FishGuide2Item"/> structures.</returns>
public FishGuide2Item[] GetFishListRaw()
{
return Core.Memory.ReadArray<FishGuide2Item>(Core.Memory.Read<IntPtr>(StartingPointer), SlotCount); //.Select(x => x.FishItem) as List<uint>;
}

/// <summary>
/// Retrieves a portion of the fish list from game memory.
/// </summary>
/// <param name="start">The index of the first item to retrieve.</param>
/// <param name="count">The number of items to retrieve.</param>
/// <returns>An array of <see cref="FishGuide2Item"/> structures.</returns>
public FishGuide2Item[] GetFishListRaw(int start, int count)
{
return Core.Memory.ReadArray<FishGuide2Item>(FishListPointer(start), count); //.Select(x => x.FishItem) as List<uint>;
}

/// <summary>
/// Opens the fishing guide UI and retrieves the fish list.
/// Handles UI navigation to ensure the correct tab and mode are selected.
/// </summary>
/// <param name="start">The index of the first item to retrieve.</param>
/// <param name="count">The number of items to retrieve. If 0, retrieves all items up to <see cref="SlotCount"/>.</param>
/// <returns>An array of <see cref="FishGuide2Item"/> structures, or an empty array if the UI could not be opened.</returns>
public async Task<FishGuide2Item[]> GetFishList(int start = 0, int count = 0)
{
if (!FishGuide2.Instance.IsOpen)
Expand Down Expand Up @@ -71,35 +115,57 @@ public async Task<FishGuide2Item[]> GetFishList(int start = 0, int count = 0)
}
}

/// <summary>
/// Represents an entry in the fishing guide.
/// </summary>
[StructLayout(LayoutKind.Explicit, Size = 0x14)]
public struct FishGuide2Item
{
//0
/// <summary>
/// The item ID of the fish.
/// </summary>
[FieldOffset(0x0)]
public uint FishItem;

//0x4
/// <summary>
/// The internal index of the fish in the guide.
/// </summary>
[FieldOffset(0X4)]
public ushort Index;

//0x6
/// <summary>
/// Unknown field.
/// </summary>
[FieldOffset(0x6)]
public ushort Unknown;

//0x8
/// <summary>
/// Unknown field.
/// </summary>
[FieldOffset(0x8)]
public ushort Unknown2;

//0xA
/// <summary>
/// Unknown field.
/// </summary>
[FieldOffset(0xA)]
public ushort Unknown5;

//0xE
/// <summary>
/// Raw byte indicating whether the player has caught this fish (1 if caught, 0 otherwise).
/// </summary>
[FieldOffset(0xE)]
public byte bHasCaught;

/// <summary>
/// Gets a value indicating whether the player has caught this fish.
/// </summary>
public bool HasCaught => bHasCaught == 1;

/// <summary>
/// Returns a string representation of the fish entry.
/// </summary>
/// <returns>A string containing the fish name and its caught status.</returns>
public override string ToString()
{
return $"{DataManager.GetItem(FishItem)} : {HasCaught}";
Expand Down
38 changes: 37 additions & 1 deletion RemoteAgents/AgentFreeCompany.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,28 @@

namespace LlamaLibrary.RemoteAgents
{
/// <summary>
/// Remote agent for the Free Company (FC) interface.
/// Manages the FC roster, online status of members, and active/available FC actions.
/// </summary>
//TODO This agent has way too many hardcoded memory offsets
public class AgentFreeCompany : AgentInterface<AgentFreeCompany>, IAgent
{
/// <inheritdoc/>
public IntPtr RegisteredVtable => AgentFreeCompanyOffsets.VTable;


/// <summary>
/// Initializes a new instance of the <see cref="AgentFreeCompany"/> class.
/// </summary>
/// <param name="pointer">The memory address of the agent.</param>
protected AgentFreeCompany(IntPtr pointer) : base(pointer)
{
}

/// <summary>
/// Gets the base memory pointer for the Free Company member roster.
/// </summary>
/// <returns>The pointer to the member roster data.</returns>
public IntPtr GetRosterPtr()
{
var ptr1 = Core.Memory.Read<IntPtr>(Pointer + 0x48);
Expand All @@ -29,6 +41,10 @@ public IntPtr GetRosterPtr()
return ptr2;
}

/// <summary>
/// Retrieves a list of all Free Company members including their names and current online status.
/// </summary>
/// <returns>A list of tuples containing member names and their online status.</returns>
public List<(string Name, bool Online)> GetMembers()
{
var i = 0;
Expand All @@ -51,9 +67,15 @@ public IntPtr GetRosterPtr()
return result;
}

/// <summary>
/// Gets the number of entries currently displayed in the FC history log.
/// </summary>
[Obsolete("Not sure what's using this but pattern is returning multiple values")]
public byte HistoryLineCount => Core.Memory.Read<byte>(Pointer + AgentFreeCompanyOffsets.HistoryCount);

/// <summary>
/// Gets the memory address of the FC actions structure by traversing the ATK stage hierarchy.
/// </summary>
public IntPtr ActionAddress
{
get
Expand All @@ -67,6 +89,10 @@ public IntPtr ActionAddress
}
}

/// <summary>
/// Retrieves the list of FC actions that are currently active (primed and providing buffs).
/// </summary>
/// <returns>An array of <see cref="FcAction"/> representing active buffs.</returns>
public async Task<FcAction[]> GetCurrentActions()
{
var wasopen = FreeCompany.Instance.IsOpen;
Expand Down Expand Up @@ -96,6 +122,10 @@ public async Task<FcAction[]> GetCurrentActions()
return new FcAction[0];
}

/// <summary>
/// Retrieves the list of FC actions available for activation from the company's current stock.
/// </summary>
/// <returns>An array of <see cref="FcAction"/> representing available actions.</returns>
public async Task<FcAction[]> GetAvailableActions()
{
var wasopen = FreeCompany.Instance.IsOpen;
Expand Down Expand Up @@ -126,11 +156,17 @@ public async Task<FcAction[]> GetAvailableActions()
}
}

/// <summary>
/// Represents a single Free Company action (buff) in memory.
/// </summary>
[StructLayout(LayoutKind.Sequential, Size = 0xC)]
public struct FcAction
{
/// <summary>The internal action identifier.</summary>
public uint id;
/// <summary>The icon identifier for the action.</summary>
public uint iconId;
/// <summary>Unknown field at offset 0x8.</summary>
public uint unk;
}
}
10 changes: 9 additions & 1 deletion RemoteAgents/AgentGoldSaucerInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@

namespace LlamaLibrary.RemoteAgents
{
/// <summary>
/// Remote agent for the Gold Saucer information interface.
/// Provides access to Gold Saucer related data and state.
/// </summary>
public class AgentGoldSaucerInfo : AgentInterface<AgentGoldSaucerInfo>, IAgent
{
/// <inheritdoc/>
public IntPtr RegisteredVtable => AgentGoldSaucerInfoOffsets.VTable;


/// <summary>
/// Initializes a new instance of the <see cref="AgentGoldSaucerInfo"/> class.
/// </summary>
/// <param name="pointer">The memory address of the agent.</param>
protected AgentGoldSaucerInfo(IntPtr pointer) : base(pointer)
{
}
Expand Down
Loading