// Open SanAndreas
// (c) 2006-2008 Stanislav "listener" Golovin
// 
// game objects

#pragma pack(push,1)

// forward declarations
class CPlaceable;
class CEntity;
class CVehicle;

extern DWORD * currentTime;

// TODO: возможно, стоит вынести в отдельный модуль и все вспомогательные классы
class CPtrNodeSingle {
public:
	CPlaceable * ptr;
	CPtrNodeSingle * next;
};

class CPtrNodeDouble {
public:
	
	void addToList (CPtrNodeDouble ** list);	// >> 5329A0 (2)

	CPlaceable * ptr;
	CPtrNodeDouble * next;
	CPtrNodeDouble * prev;
};

struct Placement {
	D3DVECTOR	pos;	// TODO: Должен ли это быть Quaternion или что-то еще?
	float		angle;

	RwMatrix * toMatrix (RwMatrix * m);

	void transformPoint (D3DVECTOR * out, D3DVECTOR * point) {	// >> 54ECE0  (NOTE: different params)
		out->x = pos.x + cosf (angle)*point->x - sinf (angle)*point->y;
		out->y = pos.y + cosf (angle)*point->y + sinf (angle)*point->x;
		out->z = pos.z + src->z;
	}
};

// TODO: возможно, linked list стоит тоже вынести в отдельную структуру
struct XYZ : public CMatrix {	// size = 76 bytes
	XYZ () { pNext = pPrev = NULL; }	// >> 54F0C0 (1)

	CPlaceable *	ptr;	// _f40
	XYZ	*			pPrev;	// _f44
	XYZ	*			pNext;	// _f48
};

struct XYZStore {	// size = 508 bytes
	XYZ		_l1Head;
	XYZ		_l1Tail;
	XYZ		allocatedListHead;
	XYZ		allocatedListTail;
	XYZ		freeListHead;
	XYZ		freeListTail;
	XYZ *	pool;

	XYZStore () { pool = NULL; }
	XYZ * allocate ();
};

extern DWORD * xyzUsed;	// static int CPlaceable::xyzUsed;
extern XYZ * defaultXYZ;	// NOTE: на самом деле, это CMatrix. TODO: сделать ее XYZ после инжекта конструктора и деструктора CPlaceable
extern XYZStore * xyzStore;	

struct SReference {
	SReference *	m_pNext;
	CEntity **		m_pEntity;
};

#ifndef __IV__
// SanAndreas version: remove ASAP
class CReferences {
public:
	void initialize ();

	SReference		m_refs[3000];
	SReference *	m_pFreeList;
};
extern CReferences*	g_pReferences;	// >> B9B9A8
#else 
// GTA IV version
class CReferences {
public:
	CReferences ();	
	~CReferences ();

	void initialize ();
	void terminate ();

	SReference *	m_pFreeList;	// linked list of the free reference nodes
	SReference *	m_pData;		// array of references
	int				m_nSize;		// size of m_pData 
	int				m_nLock;		// 
};
extern CReferences	g_references;
#endif // __IV__

template<class T> class CAutoReference {
public:
	
	CAutoReference () { m_pEntity = NULL; }
	CAutoReference (T * pEntity) { m_pEntity = pEntity; pEntity->registerReference (&m_pEntity); }
	~CAutoReference () { if (m_pEntity) m_pEntity->unregisterReference (&m_pEntity); } 

	T * operator = (T* p) { 
		if (m_pEntity) 
			m_pEntity->unregisterReference (&m_pEntity); 
		m_pEntity = p;
		if (p)
			p->registerReference (&m_pEntity);
		return m_pEntity;
	}

	__forceinline operator T* () { return m_pEntity; }
	__forceinline T* operator->() const  { return m_pEntity; }

	bool operator == (CAutoReference<T>& p) { return m_pEntity == p.m_pEntity; }
	bool operator != (CAutoReference<T>& p) { return m_pEntity != p.m_pEntity; }
	

	T * m_pEntity;
};

//=============================================================================
// Root of all 3D-objects hierarchy 
// Базовый класс для всех 3D-объектов в системе
// Точка в пространстве. Координаты точки содержатся либо в поле xyz, либо в поле pl (если xyz == NULL)
class CPlaceable {	// size = 24 bytes
public:
	CPlaceable () {	// >> 54F1E0 (2)
		pl.pos.x = pl.pos.y = pl.pos.z = 0.0f;
		pl.angle = 0.0f;
		xyz = NULL;
	}

	virtual ~CPlaceable () { // >> 54F490 (5)
		if (xyz) {
			releaseXYZ ();
			// (*xyzUsed)--;	NOTE: unused
		}
		xyz = defaultXYZ; 
	}

	inline D3DVECTOR * getPos () { return xyz ? &(xyz->m.pos) : &(pl.pos); }
	void setPos (float x, float y, float z) { D3DVECTOR * p = xyz ? &(xyz->m.pos) : &(pl.pos); p->x = x; p->y = y; p->z = z; }

	void transformFromObjectSpace (D3DVECTOR * out, D3DVECTOR * point) {	// >> 5334F0
		if (xyz)	
			transformPoint (out, xyz, point);	// transform by xyz matrix
		else 
			pl.transformPoint (out, point);	// transform by placement
	}

// protected:
	XYZ * allocateXYZ ();	// >> 54F4C0 (4)
	void releaseXYZ ();	// >> 54F3B0(4)

	Placement	pl;		// +04
	XYZ		*	xyz;	// +20

	// TODO: эта переменная пока используется через указатель
	// static DWORD	xyzUsed = 0;
};

//=============================================================================
struct CCam {	// CCamera internal object
	CCam () { init (); }
	~CCam () {}

	void init ();

	BYTE	_f000;
	BYTE	_f001;
	BYTE	_f002;
	BYTE	_f003;
	BYTE	_f004;
	BYTE	_f005;
	BYTE	_f006;
	BYTE	_f007;
	BYTE	_f008;
	BYTE	_f009;
	BYTE	_f00A;
	BYTE	_f00B;
	WORD	_f00C;
	BYTE	_f00E;
	BYTE	_f00F;
	DWORD	_f010;
	DWORD	_f014;
	DWORD	_f018;
	DWORD	_f01C;
	DWORD	_f020;
	DWORD	_f024;
	float	_f028;
	float	_f02C;
	DWORD	_f030;
	DWORD	_f034;
	float	_f038;
	DWORD	_f03C;
	DWORD	_f040;
	DWORD	_f044;
	DWORD	_f048;
	DWORD	_f04C;
	DWORD	_f050;
	DWORD	_f054;
	DWORD	_f058;
	DWORD	_f05C;
	DWORD	_f060;
	DWORD	_f064;
	DWORD	_f068;
	DWORD	_f06C;
	DWORD	_f070;
	DWORD	_f074;
	BYTE	_f078;
	BYTE	_f079;
	BYTE	_f07A;
	BYTE	_f07B;
	DWORD	_f07C;
	float	_f080;
	float	_f084;
	DWORD	_f088;
	DWORD	_f08C;
	DWORD	_f090;
	DWORD	_f094;
	DWORD	_f098;
	DWORD	_f09C;
	DWORD	_f0A0;
	DWORD	_f0A4;
	DWORD	_f0A8;
	DWORD	_f0AC;
	DWORD	_f0B0;
	DWORD	zoomFactor;	// 0B4
	DWORD	_f0B8;
	DWORD	_f0BC;
	DWORD	_f0C0;
	float	_f0C4;
	DWORD	_f0C8;
	DWORD	_f0CC;
	DWORD	_f0D0;
	DWORD	_f0D4;
	float	_f0D8;
	DWORD	_f0DC;
	DWORD	_f0E0;
	DWORD	_f0E4;
	DWORD	_f0E8;
	DWORD	_f0EC;
	DWORD	_f0F0;
	DWORD	_f0F4;
	DWORD	_f0F8;
	DWORD	_f0FC;
	DWORD	_f100;
	DWORD	_f104;
	DWORD	_f108;
	DWORD	_f10C;
	DWORD	_f110;
	DWORD	_f114;
	float	_f118;
	DWORD	_f11C;
	DWORD	_f120;
	DWORD	_f124;
	DWORD	_f128;
	DWORD	_f12C;
	DWORD	_f130;
	DWORD	_f134;
	DWORD	_f138;
	DWORD	_f13C;
	DWORD	_f140;
	DWORD	_f144;
	DWORD	_f148;
	DWORD	_f14C;
	DWORD	_f150;
	DWORD	_f154;
	DWORD	_f158;
	DWORD	_f15C;
	DWORD	_f160;
	DWORD	_f164;
	DWORD	_f168;
	DWORD	_f16C;
	DWORD	_f170;
	DWORD	_f174;
	DWORD	_f178;
	DWORD	_f17C;
	WORD	_f180;
	WORD	_f182;
	DWORD	_f184;
	DWORD	_f188;
	DWORD	_f18C;
	D3DVECTOR	_f190;
	D3DVECTOR	_f19C;
	DWORD	_f1A8;
	DWORD	_f1AC;
	DWORD	_f1B0;
	D3DVECTOR	_f1B4;
	DWORD	_f1C0;
	DWORD	_f1C4;
	DWORD	_f1C8;
	DWORD	_f1CC;
	DWORD	_f1D0;
	DWORD	_f1D4;
	D3DVECTOR	_f1D8[4];
	DWORD	_f208[4];
	DWORD	_f218;
	CEntity *	_f21C;
	DWORD	_f220;
	DWORD	_f224;
	DWORD	_f228;
	DWORD	_f22C;
	DWORD	_f230;
	DWORD	_f234;
};

struct CCamera_obj2 {
	int		_f0;
	float	_f4;
	float	_f8;
	DWORD	_fC;
};

class CCamera : public CPlaceable {
public:
	
	// NOTE: small methods
	void setRwCamera (CRwCamera * rwc);	// >> 50C100 (2)

	void setPositionAndRotation (D3DVECTOR * position, D3DVECTOR * rotation);	// >> 50BEC0 (11)

	void process ();	// >> 52B730 (4)

	void attach (CEntity * target, short mode1, short mode2, int);
	void updateTargetEntity ();	// >> 50C360 (1)

	BYTE	_f18;
	BYTE	_f19;
	BYTE	_f1A;
	BYTE	_f1B;
	BYTE	_f1C;
	BYTE	_f1D;
	BYTE	_f1E;
	BYTE	_f1F;
	BYTE	_f20;
	BYTE	_f21;
	BYTE	_f22;
	BYTE	_f23;
	BYTE	_f24;
	BYTE	_f25;
	BYTE	_f26;
	BYTE	_f27;
	BYTE	_f28;
	BYTE	_f29;
	BYTE	_f2A;
	BYTE	_f2B;
	BYTE	_f2C;
	BYTE	_f2D;
	BYTE	_f2E;
	BYTE	_f2F;
	BYTE	_f30;
	BYTE	_f31;
	BYTE	_f32;
	BYTE	_f33;
	BYTE	_f34;
	BYTE	_f35;
	BYTE	_f36;
	BYTE	_f37;
	BYTE	_f38;
	BYTE	_f39;
	BYTE	_f3A;
	BYTE	_f3B;
	BYTE	_f3C;
	BYTE	_f3D;
	BYTE	_f3E;
	BYTE	_f3F;
	BYTE	_f40;
	BYTE	_f41;
	BYTE	_f42;
	BYTE	twoPlayerMode;	// _f43
	BYTE	_f44;
	BYTE	_f45;
	WORD	_f46;
	WORD	_f48;
	WORD	_f4A;
	WORD	_f4C;
	BYTE	_f4E;
	BYTE	_f4F;
	BYTE	_f50;
	BYTE	isFading;	// _f51
	BYTE	_f52;
	BYTE	_f53;
	BYTE	_f54;
	BYTE	_f55;
	BYTE	_f56;
	BYTE	_f57;
	BYTE	_f58;
	BYTE	activeCam;	// _f59 - index of active CCam object
	BYTE	_f5A;
	BYTE	_f5B;
	DWORD	_f5C;
	DWORD	_f60;
	DWORD	_f64;
	DWORD	_f68;
	DWORD	_f6C;
	DWORD	_f70;
	DWORD	_f74;
	DWORD	_f78;
	DWORD	_f7C;
	DWORD	_f80;
	DWORD	_f84;
	DWORD	_f88;
	DWORD	_f8C;
	DWORD	_f90;
	DWORD	_f94;
	DWORD	_f98;
	DWORD	_f9C;
	DWORD	_fA0;
	DWORD	_fA4;
	DWORD	_fA8;
	DWORD	_fAC;
	DWORD	_fB0;
	DWORD	_fB4;
	float	_fB8;
	float	_fBC;
	float	_fC0;
	float	_fC4;
	DWORD	_fC8;
	DWORD	_fCC;
	DWORD	_fD0;
	DWORD	_fD4;
	DWORD	_fD8;
	DWORD	_fDC;
	DWORD	_fE0;
	DWORD	_fE4;
	DWORD	_fE8;
	DWORD	_fEC;
	DWORD	_fF0;
	DWORD	_fF4;
	DWORD	_fF8;
	DWORD	_fFC;
	DWORD	_f100;
	DWORD	_f104;
	DWORD	_f108;
	DWORD	_f10C;
	DWORD	_f110;
	DWORD	_f114;
	DWORD	_f118;
	DWORD	_f11C;
	DWORD	_f120;
	DWORD	_f124;
	DWORD	_f128;
	DWORD	_f12C;
	DWORD	_f130;
	DWORD	_f134;
	float	nearClipPlane;	// _f138
	DWORD	_f13C;
	DWORD	_f140;
	DWORD	_f144;
	DWORD	_f148;
	DWORD	_f14C;
	DWORD	_f150;
	DWORD	_f154;
	DWORD	_f158;
	DWORD	_f15C;
	DWORD	_f160;
	DWORD	_f164;
	WORD	_f168;
	WORD	_f16A;
	DWORD	_f16C;
	DWORD	_f170;
	CCam	cams[3];	// _f174
	DWORD	_f81C;
	DWORD	_f820;
	DWORD	_f824;
	DWORD	_f828;
	DWORD	_f82C;
	WORD	_f830;
	WORD	_f832;
	DWORD	_f834;
	WORD	_f838;
	WORD	_f83A;
	DWORD	_f83C;
	DWORD	_f840;
	DWORD	_f844;
	D3DVECTOR	_f848;
	D3DVECTOR	_f854;
	D3DVECTOR	_f860;
	D3DVECTOR	cameraPosition;	// _f86C
	D3DVECTOR	cameraRotation;	// _f878
	DWORD	_f884;
	DWORD	_f888;
	DWORD	_f88C;
	DWORD	_f890;
	DWORD	_f894;
	DWORD	_f898;
	DWORD	_f89C;
	DWORD	_f8A0;
	DWORD	_f8A4;
	DWORD	_f8A8;
	DWORD	_f8AC;
	DWORD	_f8B0;
	DWORD	_f8B4;
	DWORD	_f8B8;
	DWORD	_f8BC;
	DWORD	_f8C0;
	DWORD	_f8C4;
	DWORD	_f8C8;
	DWORD	_f8CC;
	DWORD	_f8D0;
	DWORD	_f8D4;
	DWORD	_f8D8;
	DWORD	_f8DC;
	DWORD	_f8E0;
	DWORD	_f8E4;
	DWORD	_f8E8;
	DWORD	_f8EC;
	DWORD	_f8F0;
	DWORD	_f8F4;
	DWORD	_f8F8;
	DWORD	_f8FC;
	DWORD	_f900;
	DWORD	_f904;
	D3DVECTOR	_f908;
	DWORD	_f914;
	DWORD	_f918;
	DWORD	_f91C;
	D3DVECTOR	_f920;
	D3DVECTOR	_f92C;
	D3DVECTOR	_f938;
	D3DVECTOR	_f944;
	DWORD	_f950;
	CRwCamera *	rwCamera;		// _f954
	// CEntity *	targetEntity;	// _f958
	CAutoReference<CEntity>	targetEntity;
	DWORD	_f95C;
	DWORD	_f960[4];
	BYTE	_f970;
	BYTE	_f971;
	BYTE	_f972;
	BYTE	_f973;
	CMatrix	_f974;
	CMatrix	_f9BC;
	CMatrix cameraViewMatrix;	// _fA04
	CMatrix	_fA4C;
	CMatrix	_fA94;
	CMatrix	_fADC;
	float	_fB24;
	float	_fB28;
	DWORD	_fB2C;
	float	_fB30;
	float	_fB34;
	DWORD	_fB38;
	DWORD	_fB3C;
	DWORD	_fB40;
	DWORD	_fB44;
	DWORD	_fB48;
	DWORD	_fB4C;
	DWORD	_fB50;
	DWORD	_fB54;
	DWORD	_fB58;
	DWORD	_fB5C;
	DWORD	_fB60;
	DWORD	_fB64;
	DWORD	_fB68;
	DWORD	_fB6C;
	DWORD	_fB70;
	DWORD	_fB74;
	DWORD	_fB78;
	DWORD	_fB7C;
	DWORD	_fB80;
	DWORD	_fB84;
	DWORD	_fB88;
	DWORD	_fB8C;
	DWORD	_fB90;
	DWORD	_fB94;
	DWORD	_fB98;
	DWORD	_fB9C;
	DWORD	_fBA0;
	DWORD	_fBA4;
	DWORD	_fBA8;
	DWORD	_fBAC;
	DWORD	_fBB0;
	DWORD	_fBB4;
	DWORD	_fBB8;
	DWORD	_fBBC;
	DWORD	_fBC0;
	DWORD	_fBC4;
	DWORD	_fBC8;
	DWORD	_fBCC;
	DWORD	_fBD0;
	DWORD	_fBD4;
	DWORD	_fBD8;
	DWORD	_fBDC;
	DWORD	_fBE0;
	DWORD	_fBE4;
	DWORD	_fBE8;
	DWORD	_fBEC;
	DWORD	_fBF0;
	DWORD	_fBF4;
	DWORD	_fBF8;
	float	fadeAlpha;	// _fBFC
	DWORD	_fC00;
	float	fFadeDuration;	// _fC04
	DWORD	_fC08;
	DWORD	_fC0C;
	DWORD	_fC10;
	DWORD	_fC14;
	float	_fC18;
	DWORD	_fC1C;
	DWORD	_fC20;
	DWORD	_fC24;
	DWORD	_fC28;
	DWORD	_fC2C;
	DWORD	fadeInOutFlag;	// _fC30
	DWORD	_fC34;
	WORD	_fC38;	// camera attachment mode1
	WORD	_fC3A;
	WORD	_fC3C;	// camera attachment mode2
	WORD	_fC3E;
	DWORD	fadeStartTime;	// _fC40
	DWORD	_fC44;
	DWORD	_fC48;
	DWORD	_fC4C;
	DWORD	_fC50;
	DWORD	_fC54;
	DWORD	_fC58;
	float	_fC5C;
	float	_fC60;
	D3DVECTOR	_fC64;
	D3DVECTOR	_fC70;
	BYTE	_fC7C;
	BYTE	_fC7D;
	BYTE	_fC7E;
	BYTE	_fC7F;
	D3DVECTOR	_fC80;
	BYTE	_fC8C;
	BYTE	_fC8D;
	BYTE	_fC8E;
	BYTE	_fC8F;
	DWORD	_fC90;
	float	startJiggleTime;	// _fC94
	float	endJiggleTime;		// _fC98
	DWORD	_fC9C;
	DWORD	_fCA0;
	float	startZoomTime;		// _fCA4
	float	endZoomTime;		// _fCA8
	DWORD	zoomInFactor;		// _fCAC
	DWORD	zoomOutFactor;		// _fCB0
	BYTE	zoomMode;			// _fCB4
	BYTE	_fCB5;
	BYTE	_fCB6;
	BYTE	_fCB7;
	float	_fCB8;
	float	_fCBC;
	float	_fCC0;
	D3DVECTOR	_fCC4;
	D3DVECTOR	_fCD0;
	BYTE	_fCDC;
	BYTE	_fCDD;
	BYTE	_fCDE;
	BYTE	_fCDF;
	D3DVECTOR	_fCE0;
	BYTE	_fCEC;
	BYTE	_fCED;
	BYTE	_fCEE;
	BYTE	_fCEF;
	BYTE	_fCF0;
	BYTE	_fCF1;
	BYTE	_fCF2;
	BYTE	_fCF3;
	CCamera_obj2	_fCF4[5];
	DWORD	_fD44;
	DWORD	_fD48;
	DWORD	_fD4C;
	DWORD	_fD50;
	DWORD	_fD54;
	DWORD	_fD58;
	DWORD	_fD5C;
	DWORD	_fD60;
	DWORD	_fD64;
	DWORD	_fD68;
	DWORD	_fD6C;
	DWORD	_fD70;
	DWORD	_fD74;
};

extern CCamera * camera;
extern CRwCamera * gtaCamera;	
//=============================================================================
// 3D-объект. Имеет форму (связан с RwObject). Имеет бесконечную массу. Не модифицируем. Не разрушаем.
class CEntity : public CPlaceable {	// size = 56 bytes
public:
	CEntity () {	// >> 532A90
		rwObject = NULL;
		_f1C = 0x8000080;
		_f20 = rand ();
		modelIndex = -1;
		m_pRef = NULL;
		_f28 = NULL;
		_f2C = 0;
		_f2E = 0;
		interior = 0;
		_f30 = NULL;
		_f34 = 0;
		_f35 = 0;
		type = 0x20;
	}

	virtual ~CEntity ();

	void registerReference		(CEntity ** entity);	// >> 571B70 (427)
	void unregisterReference	(CEntity ** entity);	// >> 571A00 (416)
	void pruneReferences		(); // >> 571A90 (12)
	

	// virtual methods
	virtual void _m04 (CRect * _a0);	
	virtual void add () {	// m08
		CRect	r;
		getBoundRect (&r);
		_m04 (&r);
	}

	virtual void remove ();	// m0C

	virtual void _m10 (DWORD f) {
		_f1C = (f&1) ? _f1C|4 : _f1C&~4;
	}

	virtual void setModelIndex (int modelId) {	// _m14	>> 532AE0 (16)
		setModelIndexNoCreate (modelId);
		createRwObject ();
	}

	virtual void setModelIndexNoCreate (int modelId);	// _m18
	virtual void * createRwObject ();	// _m1C
	virtual void deleteRwObject ();		// _m20
	virtual CRect * getBoundRect (CRect * rect);	// _m24
	virtual void processControl () {}
	virtual void _m2C () {}
	virtual void _m30 () {}
	virtual bool _m34 (DWORD _a0) { return false; }
	virtual void teleport (float x, float y, float z, float f) {}	// 4 params
	virtual void _m3C (DWORD, DWORD, DWORD, DWORD, DWORD, DWORD) {}	// 6 params
	virtual bool _m40 (DWORD, DWORD, DWORD, DWORD) { return true; } // 4 params
	virtual void preRender ();	// _m44
	virtual void render (); // _m48
	virtual void setupLighting (); 
	virtual void removeLighting (DWORD p);
	virtual void flagToDestroyWhenNextProcessing () {}

	void resolveReferences ();

// protected:
	RwObject *	rwObject;
	DWORD		_f1C;	// bit7 - visibility
	WORD		_f20;	
	short		modelIndex;
	SReference *m_pRef;
	void *		_f28;	// еще один связный список или ссылка
	WORD		_f2C;
	BYTE		_f2E;
	BYTE		interior;
	BYTE *		_f30;	// TODO: type!
	BYTE		_f34;
	BYTE		_f35;
	BYTE		type;	// flags. bits 2..0 - entity type (0 - object, 1 - building, 2 - vehicle, ...)
	BYTE		_f37;	
};
//=============================================================================
class CDummy : public CEntity {
public:
	CDummy () : CEntity () { type = (type&~7)|5; }
};

class CDummyObject : public CDummy {
public:

	CDummyObject () : CDummy () {}

	void * operator new (size_t);
	void operator delete (void *);
};

class CBuilding : public CEntity { 
public:
	CBuilding () : CEntity () { 
		type = (type&~7)|1; 
		_f1C |= 1;
	}

	void * operator new (size_t);
	void operator delete (void *);

};

class CTreadable : public CBuilding { 
public:

	CTreadable () : CBuilding () {}

	virtual void processControl () {}
	virtual void _m2C () { _f1C |= 0x20; }
	virtual void preRender ();

	void * operator new (size_t);
	void operator delete (void *);

};

//=============================================================================
// Объект, подчиняющийся физическим законам. Имеет массу. Разрушим.
class CPhysical : public CEntity {	// size = 316 bytes
public:
	CPhysical ();

	virtual ~CPhysical ();	// m00

	virtual void add ();	// m08
	virtual void remove ();	// m0C
	virtual CRect * getBoundRect (CRect * rect);	// m24
	virtual void processControl ();	// m28
	virtual void _m2C ();
	virtual void _m30 ();
	virtual void _m34 ();
	virtual DWORD processEntityCollision (DWORD _a0, DWORD _a4);	// m58 (CEntity *, CColPoint *) 

	float		_f38;
	DWORD		_f3C;	// collision time
	DWORD		_f40;	// flags: bit 28 - collided
	D3DVECTOR	_f44;	// m_vecVelocity;
	D3DVECTOR	_f50;	// m_vecAngularVelocity;	
	D3DVECTOR	_f5C;	// m_vecAcceleration;
	D3DVECTOR	_f68;	// m_vecAngularAcceleration;
	D3DVECTOR	_f74;	// m_vecForce;
	D3DVECTOR	_f80;	// m_vecTorque;
	float		_f8C;	// m_fMass;
	float		_f90;	// m_fAngularMass;
	float		_f94;	// m_fVelocityFrequency;
	float		_f98;	// m_fFriction;
	float		_f9C;	// m_fElasticity;
	DWORD		_fA0;	// m_fBuoyancyConstant;
	D3DVECTOR	_fA4;
	DWORD		_fB0;	// CEntryInfoList
	DWORD		_fB4;
	BYTE		_fB8;
	BYTE		_fB9;	// количество элементов _fBC
	BYTE		_fBA;
	BYTE		_fBB;
	DWORD		_fBC[6];	// collided entities
	DWORD		_fD4;
	DWORD		_fD8;
	DWORD		_fDC;
	D3DVECTOR	_fE0;
	D3DVECTOR	_fEC;
	WORD		_fF8;
	WORD		_fFA;
	DWORD		_fFC;
	DWORD		_f100;
	DWORD		_f104;
	DWORD		_f108;
	DWORD		_f10C;
	DWORD		_f110;
	DWORD		_f114;
	DWORD		_f118;
	DWORD		_f11C;
	DWORD		_f120;
	DWORD		_f124;
	DWORD		_f128;
	float		_f12C;
	DWORD		_f130;
	void *		_f134;	// unknown object pointer (collided object ?)
};

class CPedAcquaintance {
public:
	DWORD	respect;
	DWORD	like;
	DWORD	_f8;
	DWORD	dislike;
	DWORD	hate;
};

class CWeaponSlot {
public:
	DWORD	type;
	DWORD	state;
	int		ammoInClip;
	int		ammoRemaining;
	DWORD	_f10;
	BYTE	_f14;
	BYTE	_f15;
	BYTE	_f16;
	BYTE	_f17;
	DWORD	_f18;
};

class CPed : public CPhysical {
public:

	CPed (int pedType);
	virtual ~CPed ();

	void * operator new (size_t size);
	void operator delete (void * ptr);

	virtual void setModelIndex (int modelId);
	virtual void processControl ();
	virtual void teleport (float x, float y, float z, float f);
	virtual void _m3C (DWORD, DWORD, DWORD, DWORD, DWORD, DWORD);
	virtual bool _m40 (DWORD, DWORD, DWORD, DWORD);
	virtual void preRender ();
	virtual void render ();
	virtual void setupLighting ();
	virtual void removeLighting (DWORD p);
	virtual void flagToDestroyWhenNextProcessing ();
	virtual DWORD processEntityCollision (DWORD _a0, DWORD _a4);
	virtual void _m5C ();
	virtual BYTE _m60 ();	// save ?
	virtual BYTE _m64 ();	// load ?

	BYTE	_f138[348];	//  object_86C2A8
	BYTE	_f294[256];	//	object_85F310 (CPedSound?)
	BYTE	_f394[164];	//	object_86C2AC
	BYTE	__438[40];	// unknown
	BYTE	_f460;
	BYTE	__461[7];	// unknown
	DWORD	_f468;
	DWORD	_f46C;
	DWORD	_f470;
	DWORD	_f474;
	DWORD	_f478;
	void *	intelligence;	// CPedIntelligence *
	DWORD	_f480;
	BYTE	_f484;
	BYTE	__485[83];	// unknown
	DWORD	_f4D8;
	DWORD	_f4DC;
	CPedAcquaintance	acquaintance;
	DWORD	_f4F4;
	DWORD	_f4F8;
	CClump*	_f4FC;
	DWORD	_f500;
	WORD	_f504;
	WORD	_f506;
	WORD	_f508;
	WORD	_f50A;
	BYTE	_f50C[32];	// CPedIK ?
	DWORD	_f52C;
	DWORD	_f530;
	DWORD	_f534;
	DWORD	_f538;
	DWORD	__53C;	// unknown
	DWORD	_f540;
	DWORD	_f544;
	DWORD	_f548;
	DWORD	_f54C;
	DWORD	_f550;
	DWORD	_f554;
	DWORD	_f558;
	DWORD	_f55C;
	DWORD	_f560;
	DWORD	_f564;
	DWORD	_f568;
	D3DVECTOR	_f56C;
	D3DVECTOR	_f578;
	DWORD	_f584;
	DWORD	_f588;
	DWORD	_f58C;
	DWORD	_f590;
	DWORD	_f594;
	DWORD	_f598;
	DWORD	_f59C;	
	CWeaponSlot	weaponSlots[13];
	DWORD	_f70C;
	DWORD	_f710;
	DWORD	__714;	// unknown
	BYTE	_f718;
	BYTE	_f719;
	BYTE	_f71A;
	BYTE	__71B;
	DWORD	_f71C;	
	BYTE	__720[12];	// unknown
	BYTE	_f72C;
	BYTE	_f72D;
	BYTE	_f72E;
	BYTE	_f72F;
	DWORD	_f730;
	DWORD	_f734;
	DWORD	_f738;
	DWORD	_f73C;
	DWORD	_f740;
	DWORD	_f744;
	DWORD	_f748;
	DWORD	_f74C;
	DWORD	_f750;
	BYTE	_f754;
	BYTE	__755;	// unknown
	WORD	_f756;
	DWORD	_f758;
	DWORD	__75C;	// unknown
	BYTE	_f760;
	BYTE	__761[3];	// unknown
	DWORD	_f764;
	DWORD	_f768;
	BYTE	__76C[24];	// unknown
	DWORD	_f784;
	DWORD	_f788;
	DWORD	_f78C;
	float	_f790;
	WORD	_f794;
	WORD	__796;	// unknown
	DWORD	_f798;
};

class CCivilianPed : public CPed {
public:

	CCivilianPed (int pedType, int modelId);
	~CCivilianPed ();

	virtual void processControl ();
};

class CCopPed : public CPed {
public:

	CCopPed (int modelId);
	virtual ~CCopPed ();

	virtual void processControl ();

	DWORD	_f79C;
	DWORD	_f7A0;
	DWORD	_f7A4;
	DWORD	_f7A8;
	DWORD	_f7AC;
	DWORD	_f7B0;
	DWORD	_f7B4;
	DWORD	_f7B8;
	DWORD	_f7BC;
	DWORD	_f7C0;
};

class CEmergencyPed : public CPed {
public:

	CEmergencyPed (int pedType, int modelId);
	virtual ~CEmergencyPed ();

	virtual void processControl ();
};

class CPlayerPed : public CPed {
public:

	DWORD	_f79C;
	DWORD	_f7A0;
};

class CVehicle : public CPhysical {
};

// TODO: move to ogPlayer.h
struct CPlayerData {
	void *	pWanted;	// CWanted *
	void *	pClothesInfo;
	DWORD	_f8;
	DWORD	_fC;
	DWORD	_f10;
	DWORD	_f14;
	DWORD	_f18;
	DWORD	_f1C;
	BYTE	_f20;
	BYTE	_f21;
	WORD	__pad1;	// align
	DWORD	_f24;
	DWORD	_f28;
	DWORD	_f2C;
	DWORD	_f30;
	DWORD	_f34;
	DWORD	_f38;
	DWORD	_f3C;
	BYTE	_f40;
	BYTE	_f41;
	BYTE	_f42;
	BYTE	_f43;
	DWORD	_f44;
	DWORD	_f48;
	DWORD	_f4C;
	DWORD	_f50;
	DWORD	_f54;
	DWORD	_f58;
	DWORD	_f5C;
	DWORD	_f60;
	DWORD	_f64;
	DWORD	_f68;
	DWORD	_f6C;
	DWORD	_f70;
	D3DVECTOR	_f74;
	DWORD	_f80;
	BYTE	_f84;
	BYTE	_f85;
	BYTE	_f86;
	BYTE	_f87;
	WORD	_f88;
	WORD	_f8A;
	BYTE	_f8C;
	BYTE	_f8D;
	BYTE	_f8E;
	BYTE	_f8F;
	DWORD	_f90;
	DWORD	_f94;
	DWORD	_f98;
	DWORD	lastModelShot;
	DWORD	_fA0;
	DWORD	_fA4;
	DWORD	_fA8;
};

class CPlayer { 
public:

	CPed *		pPed;	
	CPlayerData	data;
	CVehicle *	vehicle;
	DWORD		_fB4;
	DWORD		money;
	DWORD		_fBC;
	DWORD		_fC0;
	DWORD		_fC4;
	DWORD		_fC8;
	DWORD		_fCC;
	DWORD		_fD0;
	BYTE		_fD4;
	BYTE		_fD5;
	WORD		__pad1;	// align
	DWORD		_fD8;
	BYTE		isWastedBusted;
	BYTE		_fDD;
	BYTE		_fDE;
	BYTE		_fDF;
	DWORD		_fE0;
	DWORD		_fE4;
	DWORD		_fE8;
	DWORD		_fEC;
	DWORD		_fF0;
	DWORD		_fF4;
	DWORD		_fF8;
	DWORD		_fFC;
	DWORD		_f100;
	DWORD		_f104;
	DWORD		_f108;
	DWORD		_f10C;
	DWORD		_f110;
	DWORD		_f114;
	DWORD		trappedInCar;
	DWORD		_f11C;
	DWORD		_f120;
	DWORD		_f124;
	DWORD		_f128;
	DWORD		_f12C;
	WORD		_f130;
	WORD		__pad2;	// align
	DWORD		_f134;
	DWORD		_f138;
	DWORD		_f13C;
	DWORD		_f140;
	WORD		_f144;
	WORD		__pad3;	// align
	DWORD		_f148;
	BYTE		_f14C;
	BYTE		_f14D;
	BYTE		_f14E;
	BYTE		_f14F;
	BYTE		_f150;
	BYTE		_f151;
	BYTE		_f152;
	BYTE		_f153;
	WORD		_f154;
	WORD		_f156;
	D3DVECTOR	_f158;
	char		skinName[32];
	void *		skinTexture;
	BYTE		_f188;
	BYTE		__pad4[3];	// align
	DWORD		_f18C;
};

extern CPlayer * player;

CPed * getPlayerPed (int __unused__);	// >> 56E210 (691) NOTE: only one player in Open SanAndreas
extern CVehicle * (*getPlayerVehicle)(int __unused__, BYTE _a4);	// >> 056E0D0 (510)
#pragma pack(pop)