//--------------------------------------
//--- 010 Editor v3.0.1 Binary Template
//
// File: iv-wft.bt
// Author: Stanislav "listener" Golovin
// Revision: 0.6 (2009/09/08)
// Purpose: Defines a template for parsing  GTA IV frag type resources (PC)
// Changes: 
//--------------------------------------
#include "Data/iv-types.bth"


// === fragType internal objects ===
struct Pair {
    DWORD   _f0;
    DWORD   _f4;
};

struct fragType_obj1 {
    pgArray_DWORD _f0;
    DWORD   _f8;
    pgPtr   _fC;
    pgPtr   m_pEventSet;   // pgPtr<rage::evtSet> (same as fragType::m_pCollisionEvents)
    Pair    _f14[20];
    DWORD   _fB4;
    float   _fB8;
    DWORD   _fBC;
    DWORD   _fC0 <format=hex>;
    DWORD   _fC4 <format=hex>;  // unused
    BYTE    _fC8;
    BYTE    _fC9;
    BYTE    _fCA;
    BYTE    _fCB;
};

struct fragType_obj3 {
    Matrix34        _f0;
    pgPtr           _f40;   // pgPtr<fragType_obj2> m_pParent ?
    DWORD           _f44;
    DWORD           _f48;   // WORD, WORD ?
    DWORD           _f4C;
};

struct fragType_obj2 {
    DWORD   _f0;
    pgPtr   m_pSkeleton;    // pgPtr<rage::crSkeletonData> points to m_pDrawable::m_pSkeleton
    DWORD   _f8;
    // pgPtr   _fC;
    struct {
        int offset: 28  <format=hex>;
        int type: 4;
        if (type == 5) {
            local uint doffset = FTell();
            local DWORD count = ReadUInt (doffset);   // read forward parameter count
            FSeek(offset);   
            fragType_obj3 data[count] <optimize=false>;    
            FSeek(doffset);        
        }
    } _fC;
    DWORD   m_dwBoneCount;
    pgPtr   _f14; // pgPtr<Matrix34>, points to _f18->pData[0]->pData
    pgObjectArray_Matrix34Array   _f18;
    DWORD   _f20;
    pgPtr   _f24;
};

struct pgPtr_fragType_obj2 {
    int offset: 28  <format=hex>;
    int type: 4;
    if (type == 5) {
        local uint doffset = FTell();
        FSeek(offset);   
        fragType_obj2 p;    
        FSeek(doffset);        
    }
};

struct pgPtr_evtSet;
struct fragType_obj4 {
    pgPtr_evtSet    _f0;
    fragType_obj1   _f4;
    Vector4         _fD0;
    Vector4         _fE4;
    DWORD           _F0[4];
    DWORD           _f100;
    DWORD           _f104;  // float or hash
    DWORD           _f108;
    BYTE            _f10C;
    BYTE            _f10D;
    BYTE            _f10E;
    BYTE            _f10F;
    BYTE            _f110;
    WORD            _111;   // unused/uninitialized
    BYTE            _f113;
    float           _f114;
    float           _f118;
    char            _f11C[44];
};

struct pgPtr_fragType_obj4 {
    int offset: 28  <format=hex>;
    int type: 4;
    if (type == 5) {
        local uint doffset = FTell();
        FSeek(offset);   
        fragType_obj4 p;    
        FSeek(doffset);        
    }
};

// ### rage::fragDrawable ###
struct fragDrawable {
    DWORD       __vmt <format=hex>; 
    pgPtr_OffsetMap         m_pOffsetMap;
    // >> pgBase ends here
    pgPtr_grmShaderGroup    m_pShaderGroup;
    // >> rmcDrawableBase ends here
    pgPtr_crSkeletonData    m_pSkeleton;
    grmLodGroup             m_LodGroup;
    // >> rmcDrawable ends here
    Matrix34    _f80;
    pgPtr_phBound   m_pBound; // pgPtr<rage::phBound>
    pgArray_DWORD   _fC4; // pgObjectArray<rage::phBound>
    pgPtr       _fCC;
    WORD        _fD0;
    BYTE        _fD2;
    BYTE        _fD3;
    DWORD       _fD4;
    DWORD       _fD8;
    DWORD       _fDC;
    pgPtr_String       _fE0;
    DWORD       _fE4;
    pgArray_DWORD   _fE8; // pgObjectArray<rage::crAnimation>
};

struct pgPtr_fragDrawable {
    int offset: 28  <format=hex>;
    int type: 4;
    if (type == 5) {
        local uint doffset = FTell();
        FSeek(offset);   
        fragDrawable drawable;    
        FSeek(doffset);        
    }
};

// rage::evtSet
struct evtSet {
    DWORD   __vmt <format=hex>;
    pgObjectArray   _f4;
    DWORD   _fC;
    DWORD   _f10;
    DWORD   _f14;
};

struct pgPtr_evtSet {
    int offset: 28  <format=hex>;
    int type: 4;
    if (type == 5) {
        local uint doffset = FTell();
        FSeek(offset);   
        evtSet eventSet;    
        FSeek(doffset);        
    }
};

// ### rage::crFrameDof and subclasses ###
typedef enum <BYTE> {
    FrameDofVector3 = 0,
    FrameDofQuaternion = 1,
    FrameDofFloat = 2,
    FrameDofInt = 3
} FrameDofType;

struct crFrameDof { // TODO: size (of ane subclass) = 0x20
    DWORD   __vmt<format=hex>;
    FrameDofType    m_eType;
};

struct pgPtr_crFrameDof {
    int offset: 28  <format=hex>;
    int type: 4;
    if (type == 5) {
        local uint doffset = FTell();
        FSeek(offset);   
        crFrameDof dof;
        FSeek(doffset);        
    }
};

struct pgObjectArray_crFrameDof {
    int offset: 28 <format=hex>;
    int type: 4;
    WORD    m_wCount;
    WORD    m_wSize;
    if (type == 5) {
        local uint doffset = FTell();
        FSeek(offset);
        pgPtr_crFrameDof data[m_wSize] <optimize=false>;
        FSeek(doffset);        
    }    
};


// ### rage::crFrame ###
struct crFrame {
    DWORD   __vmt <format=hex>;
    DWORD   _f4;
    DWORD   _f8;
    pgObjectArray_crFrameDof    m_dofs;
};

struct pgPtr_crFrame {
    int offset: 28  <format=hex>;
    int type: 4;
    if (type == 5) {
        local uint doffset = FTell();
        FSeek(offset);   
        crFrame frame;    
        FSeek(doffset);        
    }
};

// ### rage::fragTypeChild
struct fragTypeChild {
    DWORD   __vmt<format=hex>;
    float   _f4;
    float   _f8;
    WORD    _fC;
    WORD    _fE;
    Matrix34    _f10;
    Matrix34    _f50;
    pgPtr_fragDrawable   _f90;
    pgPtr_fragDrawable   _f94; // pgPtr<rage::fragDrawable>
    pgPtr_evtSet    _f98;
    pgPtr_evtSet    _f9C;
    pgPtr_evtSet    _fA0;
    pgPtr_evtSet    _fA4;
    fragType_obj1   _fA8;
    fragType_obj1   _f174;
    fragType_obj1   _f240;
    DWORD           _f310;
};

struct pgPtr_fragTypeChild {
    int offset: 28  <format=hex>;
    int type: 4;
    if (type == 5) {
        local uint doffset = FTell();
        FSeek(offset);   
        fragTypeChild p;    
        FSeek(doffset);        
    }
};

// ### gtaFragType ###
struct gtaFragType {
    DWORD __vmt<format=hex>;
    pgPtr_OffsetMap m_pOffsetMap;
    // >> rage::pgBase ends here
    float   _f8;
    float   _fC;
    float   _f10;
    float   _f14;
    float   _f18;
    float   _f1C;
    Vector3 _f20;
    Vector3 _f30;
    Vector3 m_vUnbrokenCGOffset;
    Vector3 m_vDampingLinearC;
    Vector3 m_vDampingLinearV;
    Vector3 m_vDampingLinearV2;
    Vector3 m_vDampingAngularC;
    Vector3 m_vDampingAngularV;
    Vector3 m_vDampingAngularV2;
    pgPtr_String        _fB0;   // modelName ? txd name ?
    pgPtr_fragDrawable  m_pDrawable;    // rage::fragDrawable
    pgPtr   _fB8;
    pgPtr   _fBC;
    DWORD   _fC0;
    int     _fC4;
    pgPtr   _fC8;

    local int dcount = ReadByte (FTell()+0x126);
    struct {    // names inside strucutres in _fD0
        int _fCC_offset: 28;
        int _fCC_type: 4;
        if (_fCC_type == 5) {
            local uint doffset = FTell();
            FSeek(_fCC_offset);   
            pgPtr_String   _fCC_p[dcount+1] <optimize=false>;
            FSeek(doffset);                    
        }
    } _fCC;
    struct {
        int _fD0_offset: 28;
        int _fD0_type: 4;
        if (_fD0_type == 5) {
            local uint doffset = FTell();
            FSeek(_fD0_offset);   
            pgPtr_fragType_obj4   _fD0_p[dcount] <optimize=false>;
            FSeek(doffset);                    
        }
    } _fD0;
    struct {
        int _fD4_offset: 28;
        int _fD4_type: 4;
        if (_fD4_type == 5) {
            local uint doffset = FTell();
            dcount = ReadByte (doffset+0x11B);  // _f1F3
            FSeek(_fD4_offset);   
            pgPtr_fragTypeChild   _fD4_p[dcount] <optimize=false>;    // pgPtr<fragTypeChild>
            FSeek(doffset);                    
        }
    } m_ppChildren;
    pgObjectArray   _fD8;
    pgPtr   _fE0;
    pgPtr   _fE4;   // pgPtr<rage::phArchetype>
    pgPtr   _fE8;   // pgPtr<rage::phArchetype>
    pgPtr   _fEC;
    pgPtr   _fF0;
    pgPtr   _fF4;
    pgPtr   _fF8;
    pgPtr   _fFC;
    pgPtr   _f100;
    DWORD   _f104;
    pgPtr_evtSet   m_pCollisionEvents;  // pgPtr<rage::evtSet>
    fragType_obj1   _f10C;
    pgPtr_crFrame   m_pFrame;  // pgPtr<rage::crFrame>
    pgPtr_fragType_obj2   _f1DC;
    pgPtr_fragType_obj2   _f1E0;
    pgPtr   _f1E4;
    DWORD   m_nEstimatedCacheSize;
    DWORD   m_nEstimatedArticulatedCacheSize;
    BYTE    m_nSelfCollisionCount;
    BYTE    _f1F1;
    BYTE    _f1F2;
    BYTE    _f1F3;
    BYTE    _f1F4;
    BYTE    _f1F5;
    BYTE    _f1F6;
    BYTE    _f1F7;
    BYTE    _f1F8;
    BYTE    m_bBecomeRope;
    BYTE    m_artAssetID;
    BYTE    m_bAttachBottomEnd;
    DWORD   _pad_1FC; // unused 
    float   m_fMinForce;
    pgPtr   _f204;
    DWORD   _f208;
    DWORD   _f20C;
    // >> rage::fragType ends here
    pgArray_CLightAttr  m_lightAttrs;
    DWORD   _f218;
    DWORD   _f21C;
};

LittleEndian ();
SetBackColor (0xFFC0C0);
gtaFragType wft;