The example below is something I cooked up to "mirror" the CGObject_C virtual functions.
Basically, from version to version of WoW, you'll likely only need to update the indices.
You can discover at runtime which entries in the vtable are used for each function, that's an exercise for the reader.
And if you don't know how to do so, and wish to just update the indexes on a per-release basis.... have fun, but you're not going to learn anything by copy/pasting.
Code:
template <typename T, typename F>
T CallVTable0(void *o, int fptr_idx)
{
if(!o) return T();
void** vtable = (*reinterpret_cast<void***>(o));
F f = reinterpret_cast<F>(vtable[fptr_idx]);
return f(o);
}
template <typename T, typename F, typename T1>
T CallVTable1(void *o, int fptr_idx, T1 t1)
{
if(!o) return T();
void** vtable = (*reinterpret_cast<void***>(o));
F f = reinterpret_cast<F>(vtable[fptr_idx]);
return f(o, t1);
}
struct Object_Wrapper
{
private:
/* These have a first parameter acting as a 'this' pointer */
typedef void (__thiscall *fGetPosition)( void *o, WOWPOS& wowPos );
typedef float (__thiscall *fGetFacing)(void *o);
typedef float (__thiscall *fGetScale)(void *o);
typedef void (__thiscall *fInteract)(void *o);
typedef const char * (__thiscall *fGetObjectName)(void *o);
static const int fGetPositionVTidx = 9;
static const int fGetFacingVTidx = 10;
static const int fGetScaleVTidx = 11;
static const int fInteractVTidx = 38;
static const int fGetObjectNameVTidx = 48;
public:
Object_Wrapper(void *object_) : object(object_) {}
void *object;
inline void GetPosition(WOWPOS& pos) {
return CallVTable1<void,fGetPosition,WOWPOS&>(object, fGetPositionVTidx, pos);
}
inline float GetFacing() {
return CallVTable0<float,fGetFacing>(object, fGetFacingVTidx);
}
inline float GetScale() {
return CallVTable0<float,fGetScale>(object, fGetScaleVTidx);
}
inline void Interact() {
return CallVTable0<void,fInteract>(object, fInteractVTidx);
}
inline const char * GetObjectName() {
return CallVTable0<const char *,fGetObjectName>(object, fGetObjectNameVTidx);
}
};
/******************************/
/******************************/
Object_Wrapper wplayer = GetObjectByGUID(g_curMgr->wLocal, -1);