Alright I'm happy to announce that I've solved the GetFacing function. Turns out that sub_5BC5C is probably just some float comparison method. In our case it's used to ensure the atan2 parameters are not zero. I hardly believe this is necessary these days since std::atan2 seems to handle zeroes just fine. Below are some functions I'm using in case anybody finds them useful. The offsets can be found in this post ([WoW] [5.4.7 18019] Release x86 Info Dump Thread). This appears to be working, however please feel free to correct any mistakes I might have made.
Code:
// Transforms relative positions into absolute positions using the transporter transform
Vector3 Vector3::Transform (const Matrix& matrix, const Vector3& value)
{
return Vector3
(
matrix.M11*value.X + matrix.M21*value.Y + matrix.M31*value.Z + matrix.M41,
matrix.M12*value.X + matrix.M22*value.Y + matrix.M32*value.Z + matrix.M42,
matrix.M13*value.X + matrix.M23*value.Y + matrix.M33*value.Z + matrix.M43
);
}
Code:
// Unpacks an eight byte quaternion
Vector4 Vector4::FromPacked (long long packed)
{
static const float a = 1 / 2097152.0f;
static const float b = 1 / 1048576.0f;
Vector4 result;
result.X = (packed << 0 >> 42) * a;
result.Y = (packed << 22 >> 43) * b;
result.Z = (packed << 43 >> 43) * b;
float w = result.X * result.X +
result.Y * result.Y +
result.Z * result.Z;
result.W = abs (w-1) >= b ? sqrt (1-w) : 0;
return result;
}
Code:
// Determines an objects angle based on its rotation
Vector4 v = Vector4::FromPacked (rotation);
entity.Angle = atan2
(0 + (v.X*v.Y + v.Z*v.W) * 2.0,
1 - (v.Y*v.Y + v.Z*v.Z) * 2.0);