Recently I faced a need to detect spell casts. COMBAT_LOG_EVENT_UNFILTERED wasn't enough for me because it doesn't have position information. So I found these 2 functions(build 17371 x86, rebased): sub_379F6C and sub_3838C8. Both of them are actually packet handlers. The former function is called upon cast start and the latter when cast succeeded.
Now some structures:
PHP Code:
int sub_379F6C( CDataStore* arg1<eax>, PendingSpellCastData* pSpellCast<esi>, void* arg3 ) // arg1 is passed in eax and pSpellCast in esi
int sub_3838C8( PendingSpellCastData* pSpellCast, CDataStore* arg2, void* arg3 )
struct SCInternal
{
uint64_t caster0; // 0x000 + 8
uint64_t caster1; // 0x008 + 8
uint32_t pad_018[2]; // 0x010 + 8
uint32_t spellID; // 0x018 + 8
uint32_t flags0; // 0x01C + 8
uint32_t flags1; // 0x020 + 8
uint32_t pad_030; // 0x024 + 8
uint64_t targetGuid0[2]; // 0x028 + 8
uint32_t pad_038[2]; // 0x038 + 8
uint64_t targetGuid1[2]; // 0x040 + 8
Point3 pos0; // 0x050 + 8
Point3 pos1; // 0x05C + 8
uint32_t pad_074[10]; // 0x068 + 8
Point3 pos2; // 0x090 + 8
uint32_t pad_09C[29]; // 0x09C + 8
uint32_t flags2; // 0x110 + 8
uint32_t flags3; // 0x114 + 8
uint32_t unk2; // 0x118 + 8
float unk3; // 0x11C + 8
uint32_t pad_120[16]; // 0x120 + 8
// Target position
const Point3& pos() const
{
if(flags1 & 0x20)
return pos0;
else if(flags1 & 0x40)
return pos1;
else
return pos2;
}
// Target GUID
uint64_t target() const
{
if(flags1 & 0x18A02)
return targetGuid0[0];
else if(flags1 & 0x1010)
return targetGuid0[1];
else if(flags1 & 0x20)
return targetGuid1[0];
else if(flags1 & 0x40)
return targetGuid1[1];
else
return targetGuid0[0];
}
};
struct PendingSpellCastData
{
uint32_t pad_000[2]; // 0x000
SCInternal cast_impl; // 0x008
uint32_t pad_168[2]; // 0x168
uint64_t guid0; // 0x170
uint32_t unk_178; // 0x178
uint32_t timestamp; // 0x17C
uint32_t pad_180[2]; // 0x180
// Get location
const Point3& pos() const
{
return cast_impl.pos();
}
uint64_t target() const
{
return cast_impl.target();
}
};