Here is what i've found out yet. It's not that much since i didn't have too much time for reversing Guild Wars 2 lately.
The Informations have been gathered from the Executable from 2012.09.09. Forgot to write down the build number
Functions:
getClientContext():
Code:
.text:00636800 getCliContext proc near ; CODE XREF: sub_43E900p
.text:00636800 ; sub_43E910+71p ...
.text:00636800 mov eax, TlsIndex
.text:00636805 mov ecx, large fs:2Ch
.text:0063680C mov edx, [ecx+eax*4]
.text:0063680F mov eax, [edx+4]
.text:00636815 retn
.text:00636815 getCliContext endp
getAsContext():
Code:
.text:00ACE030 getAsContext proc near ; CODE XREF: sub_412470+41p
.text:00ACE030 ; sub_413860+357p ...
.text:00ACE030 mov eax, offset dword_1680640
.text:00ACE035 retn
.text:00ACE035 getAsContext endp
Classes:
Code:
VTable AsContext{
+58h - setTarget(DWORD targetID)
}
Code:
class CliContext{
+34h - m_chCliContext
}
Code:
class chCliContext{
+14h - m_CharacterArray
...
+1Ch - m_CharacterArrayCount
+28h - m_PlayerArray
+30h - mPlayerArrayCount
...
+38h - m_controlledCharacter
}
Code:
VTable chCliContext{
+14h - getControlledCharacter()
+18h - getControlledPlayer()
...
+38h - getPlayerFromListById()
}
Code:
class Character{
+44h - m_Agent
+48h - Type (some sort of ID may contain Type || 30000000 means player; Type || 20000000 means Monster; the lower bytes are the id into the Character Array)
...
+60h - m_attitudeTowardControlled
...
+68h - m_inWater (0 means no; 1 means diving; 2 means swimming on surface)
...
+0A0h - m_Alive (0 means alive; 1 means defeated; 2 means fighting for life)
...
+0ACh - m_nameOverride
...
+0C0h - m_renownSubRegion
...
+128h - m_CoreStats
...
+14Ch - m_endurance
+150h - m_healthClass
+154h - m_inventory
+158h - m_kennel
...
+184h - m_Profession
+188h - m_skillbar
}
Code:
VTable Character{
+34h - getInventory()
...
+4Ch - getProfession()
...
+54h - getSkillbar()
...
+80h - getAgent()
+84h - getAgentId()
...
+0B8h - getPlayer()
...
+0D4h - isAlive()
...
+0E0h - isDowned() (Alternatively this one may be called isDead)
...
+0FCh - isInWater()
...
+108h - isMonster()
...
+118h - isMonsterPlayerClone()
...
+12Ch - isPlayer()
}
Code:
class Player{
+8h - m_Character
...
+30h - m_name (Unicode)
...
+38h - m_playerId
}
Code:
VTable Player{
+2Ch - getPlayerId()
...
+0A8h - getSkillMgr()
...
+0C0h - getTraitMgr()
}
Code:
class CoreStats{
+7Ch - Actual Level
...
+84h - Power
+88h - Precision
+8Ch - Toughness
+90h - Vitality
...
+0A0h - Displayed Level (Zone Dependent)
+0A4h - Total Experience over all Levels
}
Code:
VTable CoreStats{
}
Code:
class Agent{
+10h - m_CharacterIndex (Index of the Character inside the Character Array)
...
+1Ch - m_Position
...
+5Ch - m_AgentId
...
+64h - ClientControl - Bit 3 sets wether the user can control his character. Using skills while Bit is 0 crashes the game
...
+90h - Rotation (Writable, but only while standing; positive Values rotate you counterclockwise)
}
Code:
VTable Agent{
+10h - getCategory() (0 equals AGENT_CATEGORY_CHAR)
...
+5Ch - getAgentId()
...
+9Ch - getType() (0 equals AGENT_TYPE_CHAR; 9 equals AGENT_TYPE_GADGET)
}
Code:
class Position{
+20h - X
+24h - Y
+28h - Z
}
Code:
class SkillBar{
+40h - m_activationInputPressedSkillbarSlot
...
+4Ch - m_autoAttack (-1 means no Auto Attack)
...
+5Ch - m_outOfRangeActivationSkillbarSlot
}
Code:
VTable SkillBar{
+0h - getAutoAttack()
...
+58h - castSpellBySlot(DWORD skillBarSlot, DWORD UNKNOWN)
}
Notes: The Skillbar is enumerated starting from left to right: 5, 6, 7, 8, 9, 0, 1, 2, 3, 4
Setting a breakpoint at castSpellBySlot and changing the skillBarSlot Argument changes the executed Attack. UNKNOWN was always 0 as i tested. Haven't tested to call this function with a Hook yet.
GetAsContext or "GetAgentSelectionContext" is usefull for calling a function that might be named setTarget.
Setting a breakpoint and changing the targetId Argument changes the then selected Target. 0 means deselect target. This one, in comparison to writing the memory value, not only sets the Target but it also Displays the targets Health bar. This one has been tested by calling with a hook.
This is the part of Code where i retrieve the current getContext functions:
Code:
.text:0045A908 call getAsContext ; 01418598
.text:0045A90D mov edx, [eax]
.text:0045A90F mov ecx, eax
.text:0045A911 mov eax, [edx+58h] ; 14185F0
.text:0045A914 push ebx
.text:0045A915 call eax ; 00AD1F40 <- Settarget
.text:0045A917 mov dword ptr [esi+64h], 1
.text:0045A91E cmp dword ptr [edi+18h], 2
.text:0045A922 jnz short loc_45A964
.text:0045A924 call charClientContext
.text:0045A929 mov edx, [eax]
.text:0045A92B mov ecx, eax
.text:0045A92D mov eax, [edx+18h]
.text:0045A930 call eax
.text:0045A932 mov [ebp+var_4], eax
.text:0045A935 test eax, eax
.text:0045A937 jnz short loc_45A94D
.text:0045A939 push 152h
.text:0045A93E mov edx, offset a______GameU_10 ; "..\\..\\..\\Game\\Ui\\Scenes\\Gameplay\\GpMous"...
.text:0045A943 mov ecx, offset aPlayer ; "player"
.text:0045A948 call sub_64E910
I hope this helps other people around here reversing the Game.
Please share your finds and corrections of my posted Informations.