So what I've got:
To dump VMT functions you read VMT pointer (first 4 bytes of the object) and read [VMT+i*4] in cycle. I've wrote some simple snippet to get all sub objects:
PHP Code:
Dictionary<uint, int> subObjs= new Dictionary<uint, int>();
int wowTextEnd = (int)ai.wow.MainModule.BaseAddress + 0x8a0000; // .text section size
int wowTextStart = (int)ai.wow.MainModule.BaseAddress + 0x1000;
foreach (KeyValuePair<ulong, GameObject> pair in ObjectManager.GameObjectList)
{
for (uint i = 0; i < 166; i++) // 166*4 bytes is approximate game object size, got it by substracting base addresses of adjacent objects
{
try
{
uint VMT = ai.wow.ReadUInt(ai.wow.ReadUInt(pair.Value.BaseAddress + i * 4)); // read [base+offset] to get object address, then [object] to get VMT
int pointer1 = ai.wow.ReadInt(VMT); //read two function (probably) pointers
int pointer2 = ai.wow.ReadInt(VMT + 0x4);
if (pointer1 < wowTextStart || pointer1 > wowTextEnd) continue; //they must be in the .text segment
if (pointer2 < wowTextStart || pointer2 > wowTextEnd) continue;
uint objectOffset= 4 * i;
if (subObjs.ContainsKey(objectOffset))
subObjs[objectOffset]++;
else
subObjs.Add(objectOffset, 1);
}
catch
{
continue; //get rid of read fail exceptions
}
}
}
Scanned many game objects and got some pointers to sub objects (for sure) at: [base+8] [base+32] [base+52] [base+192] [base+220] [base+436]
So you were right, sub object with interact distance is at [base+0x1B4] (0x1b4=436) . Made a break point at (sub+0xC), got function that returns 0 if player cannot interact with object, 1 otherwise. Also it's accurate (checked ingame).
Also, it's [VMT+8*4] (sub object's VMT). I think it's just the same function JuJuBoSc told about. Going to try reversing it by myself, but a bit later, will update if i'll succeed.