AgentInterfaces and their relation to remote windows - nt153133/RebornBuddy-Tutorials GitHub Wiki
Remote windows a fairly self explanatory, if there’s a window in the game then there’s 99% chance there’s a correspondingly named remote window. Now the annoying part is the window’s name might not seem to be related to the actual window due to translating from the Japanese name. IE Armoire is actually referred to as Cabinet in the game files or the trust window is just Dawn
. I’ll assume you can get the right name for now.
So you may ask where AgentInterfaces come into play. Well Remote Windows are temporary, they exist in memory only while the window is open and as such the pointer is only valid during that time. Where as Agents are consistently in memory and serve basically as backing information for the window. Some fields of the agent might only be available after a window is open or an event but many of them can be accessed without the corresponding window open. Lets look at a few examples from Llama Library:
RetainerCharacter is an example of Agent that requires the window to be open first. In order to get the current ilvl of a retainers gear you’d need to open the RetainerCharacter window first where it displays the current retainers gear.
public int iLvl => Core.Memory.Read<byte>(Pointer + 0xa78);
that information is an offset off the RetainerCharacter Agent pointer which is much easier to access thought that then trying to read it off the window.
AgentDawn is an example of one that you can affect the information before opening the window. You can set the trust that you want to have selected and toggle Scenario/Avatars before opening the window.
public int TrustId
{
get => Core.Memory.Read<byte>(Pointer + Offsets.DawnTrustId);
set => Core.Memory.Write(Pointer + Offsets.DawnTrustId, (byte) value);
}
In rebornbuddy no matter if the agent has it’s own AgentInterface class or not, they are defined by a sequential numeric ID. The problem with solely using the ID number is that they can change per patch or in between version especially since China’s clients aren’t ever on the same client version as NA players. This is why you actually want the Agent’s Vtable offset’s memory pattern to be able to look up the agent by Vtable and not solely by ID. Armed with the vtable address you can also register a new Agent with RB after acquiring the ID.
With the window name and it open you can run this console command.
var windowName = "Dawn";
AtkAddonControl windowByName = RaptureAtkUnitManager.GetWindowByName(windowName);
if(windowByName != null)
{
var test = windowByName.TryFindAgentInterface();
if(test != null)
{
Log("Agent ID is: " + test.Id);
Log(string.Format("Agent Pointer: {0:X} Vtable: {1:X} VtableOffset 0x{2:X}", test.Pointer.ToInt64(), test.VTable.ToInt64(), Core.Memory.GetRelative(test.VTable).ToInt64()));
}
Log(string.Format("Window Pointer: {0:X}", windowByName.Pointer.ToInt64()));
}
Which for the trust ("Dawn") window will give this result on the current version
Agent ID is: 314
Agent Pointer: 1DCA9887C20 Vtable: 7FF6A8149490 VtableOffset 0x1649490
Window Pointer: 1DD24242FD0
Now would be a good time to point out the difference in the pointers. You'll notice Vtable starts with a 7, this is a static address. More importantly it's based off an offset of the ImageBase of the client's Exe. While the offset is static the imagebase of where the client is loaded into memory can change each time you start it which is why you use the offset and not 7FF6A8149490
. You can see the current imagebase with
Log(Core.Memory.ImageBase);
You can either subtract the imagebase from the address or use Core.Memory.GetRelative( )