Skip to content

Instantly share code, notes, and snippets.

@xDShot
Last active May 1, 2024 17:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xDShot/7dcf5f25c48f787718dba237ef109f7f to your computer and use it in GitHub Desktop.
Save xDShot/7dcf5f25c48f787718dba237ef109f7f to your computer and use it in GitHub Desktop.
Source Engine mdl pattern for ImHex
//
#pragma pattern_limit 0x20000
#pragma array_limit 0x20000
#include <std/mem.pat>
#include <std/io.pat>
#include <std/string.pat>
#define MAX_NUM_LODS 8
using byte = u8;
using uchar = u8;
using int = s32;
using uint = u32;
using short = s16;
using ushort = u16;
using uint32 = u32;
fn Print_pszName(auto structure) {
str retVal = std::format("{}", structure.pszName);
return retVal;
};
struct Vector
{
float x, y, z;
};
struct Quaternion
{
float x, y, z, w;
};
using RadianEuler = Vector;
using QAngle = Vector;
struct matrix3x4_t{
float m00; float m01; float m02; float m03;
float m10; float m11; float m12; float m13;
float m20; float m21; float m22; float m23;
};
bitfield STUDIOMDL_FLAGS {
AUTOGENERATED_HITBOX : 1;
USES_ENV_CUBEMAP : 1;
FORCE_OPAQUE : 1;
TRANSLUCENT_TWOPASS : 1;
STATIC_PROP : 1;
USES_FB_TEXTURE : 1;
HASSHADOWLOD : 1;
USES_BUMPMAPPING : 1;
USE_SHADOWLOD_MATERIALS : 1;
OBSOLETE : 1;
UNUSED : 1;
NO_FORCED_FADE : 1;
FORCE_PHONEME_CROSSFADE : 1;
CONSTANT_DIRECTIONAL_LIGHT_DOT : 1;
FLEXES_CONVERTED : 1;
BUILT_IN_PREVIEW_MODE : 1;
AMBIENT_BOOST : 1;
DO_NOT_CAST_SHADOWS : 1;
CAST_TEXTURE_SHADOWS : 1;
padding : 1;
VERT_ANIM_FIXED_POINT_SCALE : 1;
padding : 11;
}; // [[right_to_left]];
struct mstudiobone_t
{
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
int parentbone; // parent bone
int bonecontroller[6]; // bone controller index, -1 == none
Vector pos;
Quaternion quat;
RadianEuler rot;
Vector posscale;
Vector rotscale;
matrix3x4_t poseToBone;
Quaternion qAlignment;
int flags;
int proctype;
int procindex; // procedural rule
int physicsbone; // index into physically simulated bone
int surfacepropidx; // index into string tablefor property name
char pszSurfaceProp[] @ addressof(this) + surfacepropidx;
int contents; // See BSPFlags.h for the contents flags
int surfacepropLookup; // this index must be cached by the loader, not saved in the file
int unused[7]; // remove as appropriate
};
struct mstudiobonecontroller_t
{
int bone; // -1 == 0
int type; // X, Y, Z, XR, YR, ZR, M
float start;
float end;
int rest; // byte index value at rest
int inputfield; // 0-3 user set controller, 4 mouth
int unused[8];
};
struct mstudiobbox_t
{
int bone;
int group; // intersection group
Vector bbmin; // bounding box
Vector bbmax;
int szhitboxnameindex; // offset to the name of the hitbox.
QAngle angOffsetOrientation;
float flCapsuleRadius;
int unused[4];
char pszHitboxName[] @ addressof(this) + szhitboxnameindex;
};
struct mstudiohitboxset_t
{
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
int numhitboxes;
int hitboxindex;
mstudiobbox_t pHitbox[numhitboxes] @ addressof(this) + hitboxindex;
};
using float16 = u16;
struct mstudioikrulezeroframe_t
{
short chain;
short slot;
float16 start; // beginning of influence
float16 peak; // start of full influence
float16 tail; // end of full influence
float16 end; // end of all influence
};
struct mstudioanimvalue_t_num
{
byte valid;
byte total;
};
union mstudioanimvalue_t
{
mstudioanimvalue_t_num num;
//byte valid_total[2];
short value;
};
struct mstudioikerror_t
{
Vector pos;
Quaternion q;
};
struct mstudiocompressedikerror_t
{
float scale[6];
short offset[6];
//inline mstudioanimvalue_t *pAnimvalue( int i ) const { if (offset[i] > 0) return (mstudioanimvalue_t *)(((byte *)this) + offset[i]); else return NULL; };
mstudioanimvalue_t pAnimvalue1 @ addressof(this) + offset[0];
mstudioanimvalue_t pAnimvalue2 @ addressof(this) + offset[1];
mstudioanimvalue_t pAnimvalue3 @ addressof(this) + offset[2];
mstudioanimvalue_t pAnimvalue4 @ addressof(this) + offset[3];
mstudioanimvalue_t pAnimvalue5 @ addressof(this) + offset[4];
mstudioanimvalue_t pAnimvalue6 @ addressof(this) + offset[5];
};
struct mstudioikrule_t
{
int index;
int type;
int chain;
int bone;
int slot; // iktarget slot. Usually same as chain.
float height;
float radius;
float floor;
Vector pos;
Quaternion q;
int compressedikerrorindex;
//inline mstudiocompressedikerror_t *pCompressedError() const { return (mstudiocompressedikerror_t *)(((byte *)this) + compressedikerrorindex); };
mstudiocompressedikerror_t pCompressedError @ addressof(this) + compressedikerrorindex;
int unused2;
int iStart;
int ikerrorindex;
//inline mstudioikerror_t *pError( int i ) const { return (ikerrorindex) ? (mstudioikerror_t *)(((byte *)this) + ikerrorindex) + (i - iStart) : NULL; };
float start; // beginning of influence
float peak; // start of full influence
float tail; // end of full influence
float end; // end of all influence
float unused3; //
float contact; // frame footstep makes ground concact
float drop; // how far down the foot should drop when reaching for IK
float top; // top of the foot box
int unused6;
int unused7;
int unused8;
int szattachmentindex; // name of world attachment
//inline char * const pszAttachment( void ) const { return ((char *)this) + szattachmentindex; }
int unused[7];
};
struct mstudiomovement_t
{
int endframe;
int motionflags;
float v0; // velocity at start of block
float v1; // velocity at end of block
float angle; // YAW rotation at end of this blocks movement
Vector vector; // movement vector relative to this blocks initial angle
Vector position; // relative to start of animation???
};
struct mstudioanimblock_t
{
int datastart;
int dataend;
};
struct mstudioanimdesc_t
{
int baseptr;
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
float fps; // frames per second
int flags; // looping/non-looping flags
int numframes;
int nummovements;
int movementindex;
mstudiomovement_t pMovement[nummovements] @ addressof(this) + movementindex;
int ikrulezeroframeindex;
mstudioikrulezeroframe_t pIKRuleZeroFrame[ikrulezeroframeindex != 0] @ addressof(this) + ikrulezeroframeindex;
int unused1[5];
int animblock;
int animindex; // non-zero when anim data isn't in sections
int numikrules;
int ikruleindex; // non-zero when IK data is stored in the mdl
int animblockikruleindex; // non-zero when IK data is stored in animblock file
mstudioikrule_t pIKRule[numikrules] @ addressof(this) + ikruleindex;
int numlocalhierarchy;
int localhierarchyindex;
int sectionindex;
int sectionframes; // number of frames used in each fast lookup section, zero if not used
short zeroframespan; // frames per span
short zeroframecount; // number of spans
int zeroframeindex;
float zeroframestalltime [[hidden]]; // saved during read stalls
} [[format("Print_pszName")]];
struct mstudioevent_t
{
float cycle;
int event;
int type;
char options[64];
int szeventindex;
char pszEventName[] @ addressof(this) + szeventindex;
};
struct mstudioautolayer_t
{
short iSequence;
short iPose;
int flags;
float start; // beginning of influence
float peak; // start of full influence
float tail; // end of full influence
float end; // end of all influence
};
struct mstudioseqdesc_t
{
int baseptr;
int szlabelindex;
char pszLabel[] @ addressof(this) + szlabelindex;
int szactivitynameindex;
char pszActivityName[] @ addressof(this) + szactivitynameindex;
int flags; // looping/non-looping flags
int activity; // initialized at loadtime to game DLL values
int actweight;
int numevents;
int eventindex;
mstudioevent_t pEvent[numevents] @ addressof(this) + eventindex;
Vector bbmin; // per sequence bounding box
Vector bbmax;
int numblends;
// Index into array of shorts which is groupsize[0] x groupsize[1] in length
int animindexindex;
//inline int anim( int x, int y )
int movementindex; // [blend] float array for blended movement
int groupsize[2];
int paramindex[2]; // X, Y, Z, XR, YR, ZR
float paramstart[2]; // local (0..1) starting value
float paramend[2]; // local (0..1) ending value
int paramparent;
float fadeintime; // ideal cross fate in time (0.2 default)
float fadeouttime; // ideal cross fade out time (0.2 default)
int localentrynode; // transition node at entry
int localexitnode; // transition node at exit
int nodeflags; // transition rules
float entryphase; // used to match entry gait
float exitphase; // used to match exit gait
float lastframe; // frame that should generation EndOfSequence
int nextseq; // auto advancing sequences
int pose; // index of delta animation between end and nextseq
int numikrules;
int numautolayers; //
int autolayerindex;
mstudioautolayer_t pAutolayer[numautolayers] @ addressof(this) + autolayerindex;
int weightlistindex;
float pBoneweight[parent.numbones] @ addressof(this) + weightlistindex;
//inline float *pBoneweight( int i ) const { return ((float *)(((byte *)this) + weightlistindex) + i); };
//inline float weight( int i ) const { return *(pBoneweight( i)); };
// FIXME: make this 2D instead of 2x1D arrays
int posekeyindex;
//float *pPoseKey( int iParam, int iAnim ) const { return (float *)(((byte *)this) + posekeyindex) + iParam * groupsize[0] + iAnim; }
//float poseKey( int iParam, int iAnim ) const { return *(pPoseKey( iParam, iAnim )); }
int numiklocks;
int iklockindex;
//inline mstudioiklock_t *pIKLock( int i ) const { Assert( i >= 0 && i < numiklocks); return (mstudioiklock_t *)(((byte *)this) + iklockindex) + i; };
// Key values
int keyvalueindex;
int keyvaluesize;
//inline const char * KeyValueText( void ) const { return keyvaluesize != 0 ? ((char *)this) + keyvalueindex : NULL; }
int cycleposeindex; // index of pose parameter to use as cycle index
int activitymodifierindex;
int numactivitymodifiers;
//inline mstudioactivitymodifier_t *pActivityModifier( int i ) const { Assert( i >= 0 && i < numactivitymodifiers); return activitymodifierindex != 0 ? (mstudioactivitymodifier_t *)(((byte *)this) + activitymodifierindex) + i : NULL; };
int animtagindex;
int numanimtags;
//inline mstudioanimtag_t *pAnimTag( int i ) const { Assert( i >= 0 && i < numanimtags); return (mstudioanimtag_t *)(((byte *)this) + animtagindex) + i; };
int rootDriverIndex;
int unused[2]; // remove/add as appropriate (grow back to 8 ints on version change!)
};
struct mstudiotexture_t
{
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
int flags;
int used;
int unused1;
int material; // fixme: this needs to go away . .isn't used by the engine, but is used by studiomdl
int clientmaterial; // gary, replace with client material pointer if used
int unused[10];
};
struct mstudio_meshvertexdata_t
{
int unused_modelvertexdata; // 64b - Moved to follow num_LOD_Vertexes.
int numLODVertexes[MAX_NUM_LODS];
//int modelvertexdata;
};
struct mstudioflex_t
{
int flexdesc; // input value
float target0; // zero
float target1; // one
float target2; // one
float target3; // zero
int numverts;
int vertindex;
//inline mstudiovertanim_t *pVertanim( int i ) const { Assert( vertanimtype == STUDIO_VERT_ANIM_NORMAL ); return (mstudiovertanim_t *)(((byte *)this) + vertindex) + i; };
//inline mstudiovertanim_wrinkle_t *pVertanimWrinkle( int i ) const { Assert( vertanimtype == STUDIO_VERT_ANIM_WRINKLE ); return (mstudiovertanim_wrinkle_t *)(((byte *)this) + vertindex) + i; };
//inline byte *pBaseVertanim( ) const { return ((byte *)this) + vertindex; };
//inline int VertAnimSizeBytes() const { return ( vertanimtype == STUDIO_VERT_ANIM_NORMAL ) ? sizeof(mstudiovertanim_t) : sizeof(mstudiovertanim_wrinkle_t); }
int flexpair; // second flex desc
uchar vertanimtype; // See StudioVertAnimType_t
uchar unusedchar[3];
int unused[6];
};
struct mstudiomesh_t
{
int material;
int modelindex;
int numvertices; // number of unique vertices/normals/texcoords
int vertexoffset; // vertex mstudiovertex_t
int numflexes; // vertex animation
int flexindex;
mstudioflex_t pFlex[numflexes] @ addressof(this) + flexindex;
// special codes for material operations
int materialtype;
int materialparam;
// a unique ordinal for this mesh
int meshid;
Vector center;
mstudio_meshvertexdata_t vertexdata;
int unused[8]; // remove as appropriate
};
struct mstudioeyeball_t
{
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
int bone;
Vector org;
float zoffset;
float radius;
Vector up;
Vector forward;
int texture;
int unused1;
float iris_scale;
int unused2;
int upperflexdesc[3]; // index of raiser, neutral, and lowerer flexdesc that is set by flex controllers
int lowerflexdesc[3];
float uppertarget[3]; // angle (radians) of raised, neutral, and lowered lid positions
float lowertarget[3];
int upperlidflexdesc; // index of flex desc that actual lid flexes look to
int lowerlidflexdesc;
int unused[4]; // These were used before, so not guaranteed to be 0
bool m_bNonFACS; // Never used before version 44
char unused3[3];
int unused4[7];
};
struct mstudio_modelvertexdata_t
{
int pVertexData;
int pTangentData;
int pExtraData;
};
struct mstudiomodel_t
{
char name[64];
int type;
float boundingradius;
int nummeshes;
int meshindex;
mstudiomesh_t pMesh[nummeshes] @ addressof(this) + meshindex;
int numvertices; // number of unique vertices/normals/texcoords
int vertexindex; // vertex Vector
int tangentsindex; // tangents Vector
int numattachments;
int attachmentindex;
int numeyeballs;
int eyeballindex;
mstudioeyeball_t pEyeball[numeyeballs] @ addressof(this) + eyeballindex;
mstudio_modelvertexdata_t vertexdata;
int unused[7]; // remove as appropriate
};
struct mstudiobodyparts_t
{
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
int nummodels;
int base;
int modelindex; // index into models array
mstudiomodel_t pModel[nummodels] @ addressof(this) + modelindex;
};
struct mstudioattachment_t
{
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
uint flags;
int localbone;
matrix3x4_t local; // attachment point
int unused[8];
};
struct mstudioflexdesc_t
{
int szFACSindex;
char pszFACS[] @ addressof(this) + szFACSindex;
};
struct mstudioflexcontroller_t
{
int sztypeindex;
char pszType[] @ addressof(this) + sztypeindex;
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
int localToGlobal; // remapped at load time to master list
float min;
float max;
};
union flexd
{
int index;
float value;
};
struct mstudioflexop_t
{
int op;
flexd d;
};
struct mstudioflexrule_t
{
int flex;
int numops;
int opindex;
mstudioflexop_t iFlexOp[numops] @ addressof(this) + opindex;
};
struct mstudioiklink_t
{
int bone;
Vector kneeDir; // ideal bending direction (per link, if applicable)
Vector unused0; // unused
};
struct mstudioikchain_t
{
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
int linktype;
int numlinks;
int linkindex;
mstudioiklink_t pLink[numlinks] @ addressof(this) + linkindex;
};
struct mstudiomouth_t
{
int bone;
Vector forward;
int flexdesc;
};
struct mstudioposeparamdesc_t
{
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
int flags; // ????
float start; // starting value
float end; // ending value
float loop; // looping range, 0 for no looping, 360 for rotations, etc.
};
struct mstudioiklock_t
{
int chain;
float flPosWeight;
float flLocalQWeight;
int flags;
int unused[4];
};
struct mstudiomodelgroup_t
{
int szlabelindex; // textual name
char pszLabel[] @ addressof(this) + szlabelindex;
int sznameindex; // file name
char pszName[] @ addressof(this) + sznameindex;
};
enum RemapType : uchar //FlexControllerRemapType_t enum
{
PASSTHRU = 0,
TWOWAY, // Control 0 -> ramps from 1-0 from 0->0.5. Control 1 -> ramps from 0-1 from 0.5->1
NWAY, // StepSize = 1 / (control count-1) Control n -> ramps from 0-1-0 from (n-1)*StepSize to n*StepSize to (n+1)*StepSize. A second control is needed to specify amount to use
EYELID
};
struct mstudioflexcontrollerui_t
{
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
// These are used like a union to save space
// Here are the possible configurations for a UI controller
//
// SIMPLE NON-STEREO: 0: control 1: unused 2: unused
// STEREO: 0: left 1: right 2: unused
// NWAY NON-STEREO: 0: control 1: unused 2: value
// NWAY STEREO: 0: left 1: right 2: value
int szindex0;
int szindex1;
int szindex2;
//TODO inlines
RemapType remaptype; // See the FlexControllerRemapType_t enum
bool stereo; // Is this a stereo control?
byte unused[2];
};
struct mstudiosrcbonetransform_t
{
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
matrix3x4_t pretransform;
matrix3x4_t posttransform;
};
struct mstudiolinearbone_t
{
int numbones;
int flagsindex;
int flags[numbones] @ addressof(this) + flagsindex;
int parentindex;
int prnt[numbones] @ addressof(this) + parentindex;
int posindex;
Vector pos[numbones] @ addressof(this) + posindex;
int quatindex;
Quaternion quat[numbones] @ addressof(this) + quatindex;
int rotindex;
RadianEuler rot[numbones] @ addressof(this) + rotindex;
int posetoboneindex;
matrix3x4_t poseToBone[numbones] @ addressof(this) + posetoboneindex;
int posscaleindex;
Vector posscale[numbones] @ addressof(this) + posscaleindex;
int rotscaleindex;
Vector rotscale[numbones] @ addressof(this) + rotscaleindex;
int qalignmentindex;
Quaternion qalignment[numbones] @ addressof(this) + qalignmentindex;
int unused[6];
};
struct mstudiobodygrouppreset_t
{
int sznameindex;
char pszName[] @ addressof(this) + sznameindex;
int iValue;
int iMask;
};
enum StudioBoneFlexComponent_t : int
{
STUDIO_BONE_FLEX_INVALID = -1, // Invalid
STUDIO_BONE_FLEX_TX = 0, // Translate X
STUDIO_BONE_FLEX_TY = 1, // Translate Y
STUDIO_BONE_FLEX_TZ = 2 // Translate Z
};
struct mstudioboneflexdrivercontrol_t
{
StudioBoneFlexComponent_t m_nBoneComponent; // Bone component that drives flex, StudioBoneFlexComponent_t
int m_nFlexControllerIndex; // Flex controller to drive
float m_flMin; // Min value of bone component mapped to 0 on flex controller
float m_flMax; // Max value of bone component mapped to 1 on flex controller
};
struct mstudioboneflexdriver_t
{
int m_nBoneIndex; // Bone to drive flex controller
int m_nControlCount; // Number of flex controllers being driven
int m_nControlIndex; // Index into data where controllers are (relative to this)
mstudioboneflexdrivercontrol_t pBoneFlexDriverControl[m_nControlCount] @ addressof(this) + m_nControlIndex;
int unused[3];
};
struct studiohdr2_t
{
int numsrcbonetransform;
int srcbonetransformindex;
int illumpositionattachmentindex;
float flMaxEyeDeflection;
int linearboneindex;
mstudiolinearbone_t pLinearBones @ addressof(this) + linearboneindex;
int sznameindex;
char StudioHdr2_pszName[] @ addressof(this) + sznameindex;
int m_nBoneFlexDriverCount;
int m_nBoneFlexDriverIndex;
mstudioboneflexdriver_t pBoneFlexDriver[m_nBoneFlexDriverCount] @ addressof(this) + m_nBoneFlexDriverIndex;
int m_pFeModel_index;
int m_nBodyGroupPresetCount;
int m_nBodyGroupPresetIndex;
mstudiobodygrouppreset_t pBodyGroupPreset[m_nBodyGroupPresetCount] @ addressof(this) + m_nBodyGroupPresetIndex;
int reserved[53];
};
struct studiohdr_t
{
int id;
int version;
int checksum;
char name[64];
int length;
Vector eyeposition; // ideal eye position
Vector illumposition; // illumination center
Vector hull_min; // ideal movement hull size
Vector hull_max;
Vector view_bbmin; // clipping bounding box
Vector view_bbmax;
STUDIOMDL_FLAGS flags;
int numbones; // bones
int boneindex;
mstudiobone_t pBone[numbones] @ addressof(this) + boneindex;
int numbonecontrollers; // bone controllers
int bonecontrollerindex;
mstudiobonecontroller_t pBonecontroller[numbonecontrollers] @ addressof(this) + boneindex;
int numhitboxsets;
int hitboxsetindex;
mstudiohitboxset_t pHitboxSet[numhitboxsets] @ addressof(this) + hitboxsetindex;
int numlocalanim; // animations/poses
int localanimindex; // animation descriptions
mstudioanimdesc_t pLocalAnimdesc[numlocalanim] @ addressof(this) + localanimindex;
int numlocalseq; // sequences
int localseqindex;
mstudioseqdesc_t pLocalSeqdesc[numlocalseq] @ addressof(this) + localseqindex;
int activitylistversion; // initialization flag - have the sequences been indexed?
int eventsindexed;
int numtextures;
int textureindex;
mstudiotexture_t pTexture[numtextures] @ addressof(this) + textureindex;
int numcdtextures;
int cdtextureindex;
int numskinref;
int numskinfamilies;
int skinindex;
short pSkinref[numskinfamilies*numskinref] @ addressof(this) + skinindex;
int numbodyparts;
int bodypartindex;
mstudiobodyparts_t pBodypart[numbodyparts] @ addressof(this) + bodypartindex;
int numlocalattachments;
int localattachmentindex;
mstudioattachment_t pLocalAttachment[numlocalattachments] @ addressof(this) + localattachmentindex;
int numlocalnodes;
int localnodeindex;
int localnodenameindex;
int numflexdesc;
int flexdescindex;
mstudioflexdesc_t pFlexdesc[numflexdesc] @ addressof(this) + flexdescindex;
int numflexcontrollers;
int flexcontrollerindex;
mstudioflexcontroller_t pFlexcontroller[numflexcontrollers] @ addressof(this) + flexcontrollerindex;
int numflexrules;
int flexruleindex;
mstudioflexrule_t pFlexRule[numflexrules] @ addressof(this) + flexruleindex;
int numikchains;
int ikchainindex;
mstudioikchain_t pIKChain[numikchains] @ addressof(this) + ikchainindex;
int nummouths;
int mouthindex;
mstudiomouth_t pMouth[nummouths] @ addressof(this) + mouthindex;
int numlocalposeparameters;
int localposeparamindex;
mstudioposeparamdesc_t pLocalPoseParameter[numlocalposeparameters] @ addressof(this) + localposeparamindex;
int surfacepropindex;
char pszSurfaceProp[] @ addressof(this) + surfacepropindex;
int keyvalueindex;
int keyvaluesize;
char KeyValueText[keyvaluesize] @ addressof(this) + keyvalueindex;
int numlocalikautoplaylocks;
int localikautoplaylockindex;
mstudioiklock_t pLocalIKAutoplayLock[numlocalikautoplaylocks] @ addressof(this) + localikautoplaylockindex;
float mass;
int contents;
int numincludemodels;
int includemodelindex;
mstudiomodelgroup_t pModelGroup[numincludemodels] @ addressof(this) + includemodelindex;
int unused_virtualModel;
int szanimblocknameindex;
char pszAnimBlockName[] @ addressof(this) + szanimblocknameindex;
int numanimblocks;
int animblockindex;
mstudioanimblock_t pAnimBlock[numanimblocks] @ addressof(this) + animblockindex;
int unused_animblockModel;
int bonetablebynameindex;
int unused_pVertexBase;
int unused_pIndexBase;
byte constdirectionallightdot;
byte rootLOD;
byte numAllowedRootLODs;
byte unused[1];
int unused4;
int numflexcontrollerui;
int flexcontrolleruiindex;
mstudioflexcontrollerui_t pFlexControllerUI[numflexcontrollerui] @ addressof(this) + flexcontrolleruiindex;
float flVertAnimFixedPointScale;
int surfacepropLookup;
int studiohdr2index;
studiohdr2_t pStudioHdr2 @ addressof(this) + studiohdr2index;
mstudiosrcbonetransform_t SrcBoneTransform[pStudioHdr2.numsrcbonetransform] @ addressof(this) + pStudioHdr2.srcbonetransformindex;
int unused2[1];
};
studiohdr_t pStudioHdr @ 0x00;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment