Skip to content
Open
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
15 changes: 15 additions & 0 deletions RemoteAgents/AgentDeepDungeonStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,31 @@

namespace LlamaLibrary.RemoteAgents;

/// <summary>
/// Remote agent for tracking the player's Deep Dungeon status, progression, and state.
/// Handles accessing variables and vtable pointers specific to Deep Dungeons (such as Palace of the Dead, Heaven-on-High, and Eureka Orthos).
/// </summary>
public class AgentDeepDungeonStatus: AgentInterface
{
/// <inheritdoc/>
public IntPtr RegisteredVtable => AgentDeepDungeonStatusOffsets.VTable;

private static AgentInterface? _instance;

/// <summary>
/// Gets the raw Agent ID of the Deep Dungeon status agent.
/// </summary>
public static int IdRaw { get; } = AgentModule.FindAgentIdByVtable(AgentDeepDungeonStatusOffsets.VTable);

/// <summary>
/// Gets the singleton or active instance of the <see cref="AgentDeepDungeonStatus"/> remote agent.
/// </summary>
public static AgentInterface Instance => _instance ??= new AgentDeepDungeonStatus(AgentModule.AgentPointers[AgentModule.FindAgentIdByVtable(AgentDeepDungeonStatusOffsets.VTable)]);

/// <summary>
/// Initializes a new instance of the <see cref="AgentDeepDungeonStatus"/> class.
/// </summary>
/// <param name="pointer">The memory address of the agent.</param>
protected AgentDeepDungeonStatus(IntPtr pointer) : base(pointer)
{
}
Expand Down
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 tracking system.
/// Manages client-side state and data queries relating to Gold Saucer currencies, stats, and mini-games.
/// </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
11 changes: 9 additions & 2 deletions RemoteAgents/AgentHousing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@

namespace LlamaLibrary.RemoteAgents
{
/// <summary>
/// Remote agent for the main housing interface and system state.
/// Manages client-side interaction with general housing features, purchase windows, and estate setup.
/// </summary>
public class AgentHousing : AgentInterface<AgentHousing>, IAgent
{
/// <inheritdoc/>
public IntPtr RegisteredVtable => AgentHousingOffsets.VTable;



/// <summary>
/// Initializes a new instance of the <see cref="AgentHousing"/> class.
/// </summary>
/// <param name="pointer">The memory address of the agent.</param>
protected AgentHousing(IntPtr pointer) : base(pointer)
{
}
Expand Down
19 changes: 18 additions & 1 deletion RemoteAgents/AgentHousingSelectBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,38 @@

namespace LlamaLibrary.RemoteAgents
{
/// <summary>
/// Remote agent for the housing ward selection interface.
/// Manages the housing ward selection UI, tracking selected ward numbers and plot status data.
/// </summary>
public class AgentHousingSelectBlock : AgentInterface<AgentHousingSelectBlock>, IAgent
{
/// <inheritdoc/>
public IntPtr RegisteredVtable => AgentHousingSelectBlockOffsets.VTable;


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

/// <summary>
/// Gets or sets the selected ward number index.
/// </summary>
/// <value>The zero-based ward index in the housing area selection.</value>
public int WardNumber
{
get => Core.Memory.Read<int>(Pointer + AgentHousingSelectBlockOffsets.WardNumber);
set => Core.Memory.Write(Pointer + AgentHousingSelectBlockOffsets.WardNumber, value);
}

/// <summary>
/// Reads the status of housing plots for the selected ward block.
/// </summary>
/// <param name="count">The number of plots to read status for (usually up to 30 or 60 depending on ward size/subdivision).</param>
/// <returns>A byte array representing plot availability/purchase status in the current ward block.</returns>
public byte[] ReadPlots(int count)
{
return Core.Memory.ReadArray<byte>(Pointer + AgentHousingSelectBlockOffsets.PlotOffset, count);
Expand Down
31 changes: 30 additions & 1 deletion RemoteAgents/AgentMinionNoteBook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,32 @@

namespace LlamaLibrary.RemoteAgents
{
/// <summary>
/// Remote agent for the Minion Guide (Notebook) interface.
/// Manages the display and querying of acquired minions and their names.
/// </summary>
public class AgentMinionNoteBook : AgentInterface<AgentMinionNoteBook>, IAgent
{
/// <inheritdoc/>
public IntPtr RegisteredVtable => AgentMinionNoteBookOffsets.VTable;

/// <summary>
/// Gets the raw memory address of the minion list.
/// </summary>
public IntPtr MinionListAddress => Pointer + AgentMinionNoteBookOffsets.AgentOffset;


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

/// <summary>
/// Retrieves the list of currently owned or displayed minions from game memory.
/// </summary>
/// <returns>An array of <see cref="MinionStruct"/> representing the player's minion notebook list.</returns>
public MinionStruct[] GetCurrentMinions()
{
var address = Pointer + AgentMinionNoteBookOffsets.AgentOffset;
Expand All @@ -28,19 +43,33 @@ public MinionStruct[] GetCurrentMinions()
return Core.Memory.ReadArray<MinionStruct>(address1, (int)count);
}

/// <summary>
/// Resolves the in-game name of a minion by its database index.
/// </summary>
/// <param name="index">The internal database or row index of the minion companion.</param>
/// <returns>The UTF-8 string name of the minion, or an empty string if not found.</returns>
public static string GetMinionName(int index)
{
var result = Core.Memory.CallInjectedWraper<IntPtr>(AgentMinionNoteBookOffsets.GetCompanion, index);
return result != IntPtr.Zero ? Core.Memory.ReadString(result + 0x30, Encoding.UTF8) : "";
}
}

/// <summary>
/// Represents a 4-byte memory mapping for a minion entry in the player's collection.
/// </summary>
[StructLayout(LayoutKind.Explicit, Size = 0x4)]
public struct MinionStruct
{
/// <summary>
/// The unique ID of the minion companion.
/// </summary>
[FieldOffset(0)]
public ushort MinionId;

/// <summary>
/// An unknown/alignment field.
/// </summary>
[FieldOffset(2)]
public ushort unknown;
}
Expand Down
54 changes: 53 additions & 1 deletion RemoteAgents/AgentWorldTravelSelect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,45 +9,97 @@

namespace LlamaLibrary.RemoteAgents
{
/// <summary>
/// Remote agent for the World Travel selection interface.
/// Manages cross-world visit options and retrieves available target worlds.
/// </summary>
/// <remarks>
/// In other regions, a skip logic (<c>MaxSkip = 1</c>) is used to filter out the player's home world from the target choices,
/// while for the Tencent version (RB_TC), no home world skipping is applied (<c>MaxSkip = 0</c>).
/// </remarks>
public class AgentWorldTravelSelect : AgentInterface<AgentWorldTravelSelect>, IAgent
{
/// <inheritdoc/>
public IntPtr RegisteredVtable => AgentWorldTravelSelectOffsets.VTable;

#if RB_TC
const int MaxCountOffset = -1;
const int MaxSkip = 0;
const int MaxSkip = 0;
#else
const int MaxCountOffset = -1;
const int MaxSkip = 1;
#endif

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

/// <summary>
/// Gets the ID of the current world the player is physically on.
/// </summary>
public ushort CurrentWorld => Core.Memory.NoCacheRead<ushort>(ChoicesPointer + 0x4);

/// <summary>
/// Gets the pointer to the world choices data structure array.
/// </summary>
public IntPtr ChoicesPointer => Core.Memory.NoCacheRead<IntPtr>(Pointer + AgentWorldTravelSelectOffsets.ChoicesOffset);

/// <summary>
/// Gets the ID of the player's Home World.
/// </summary>
public ushort HomeWorld => Core.Memory.NoCacheRead<ushort>(ChoicesPointer);

/// <summary>
/// Gets the total number of worlds in the current logical data center/choices list.
/// </summary>
public int NumberOfWorlds => Core.Memory.NoCacheRead<byte>(Pointer + AgentWorldTravelSelectOffsets.MaxWorldOffset) + MaxCountOffset;

/// <summary>
/// Gets the collection of available worlds for cross-world travel.
/// </summary>
/// <remarks>
/// Filters out the Home World in standard configurations using <c>MaxSkip</c>.
/// </remarks>
public WorldChoice[] Choices => Core.Memory.ReadArray<WorldChoice>(ChoicesPointer + 0x8, NumberOfWorlds).Skip(MaxSkip).ToArray();
}

#if RB_TC
/// <summary>
/// Represents a world travel destination choice for the Tencent game client.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct WorldChoice
{
/// <summary>
/// The unique ID representing the destination game world.
/// </summary>
public ushort WorldID;

/// <summary>
/// An unknown field alignment/metadata value.
/// </summary>
public ushort Unk;
}
#else
/// <summary>
/// Represents a world travel destination choice.
/// </summary>
[StructLayout(LayoutKind.Explicit, Size = 0xC)]
public struct WorldChoice
{
/// <summary>
/// The unique ID representing the destination game world.
/// </summary>
[FieldOffset(0x4)]
public ushort WorldID;

/// <summary>
/// Gets the corresponding strongly-typed <see cref="World"/> enum representation for the world ID.
/// </summary>
public World World => (World)WorldID;
}
#endif
Expand Down