// Open SanAndreas
// (c) 2006-2008 Stanislav "listener" Golovin
// 
// Script Engine

#pragma pack(push,1)
struct SFlippedCheck {
	DWORD	hVehicle;
	DWORD	_f4;
};

struct CFlippedCheck {
public:

	SFlippedCheck	data[6];

	void	process ();	// >> 4655E0 (1)
	BYTE	processVehicle (CVehicle * vehicle);	// >> 463830
};
extern CFlippedCheck * flippedCheck;	// TODO: move into CScriptEngine

struct SStuckCheck {
	DWORD	_f0;
	D3DVECTOR	_f4;
	DWORD	_f10;
	DWORD	_f14;
	DWORD	_f18;
	BYTE	_f1C;
	BYTE	_f1D;
	BYTE	_f1E;
	BYTE	_f1F;
	BYTE	_f20;
	BYTE	_f21;
	BYTE	_f22;
	BYTE	_f23;
};

class CStuckCheck {
public:

	SStuckCheck	data[16];

	void	process ();	// >> 465680 (1)
};

extern CStuckCheck * stuckCheck;	// TODO: move into CScriptEngine

struct SMissionCleanup {
	BYTE	type;
	BYTE	__align[3];
	DWORD	handle;
};

class CMissionCleanupList {
public:
	SMissionCleanup	data[0x4B];

	void	process ();	// >> 4652D0 (1)
};

extern CMissionCleanupList * missionCleanupList;	// TODO: move into CScriptEngine

class CTextDrawer {	// size = 0x44
public:

	float	letterWidth;
	float	letterHeight;
	RGBA	color;
	BYTE	_fC;
	BYTE	centered;
	BYTE	withBackground;
	BYTE	_fF;
	float	lineHeight;
	float	lineWidth;
	RGBA	backgroundBoxColor;
	BYTE	proportional;
	RGBA	backgroundColor;
	BYTE	shadowType;
	BYTE	outlineType;
	BYTE	_f23;
	BYTE	alignRight;
	BYTE	__align2[3];
	DWORD	font;
	DWORD	xPosition;
	DWORD	yPosition;
	char	gxtEntry[8];
	DWORD	param1;
	DWORD	param2;
};

class CTextSprite {	// size = 0x3C
public:

	DWORD	type;
	BYTE	_f4;
	BYTE	_f5;
	WORD	textureId;
	DWORD	x1;
	DWORD	y1;
	DWORD	x2;
	DWORD	y2;
	float	angle;
	DWORD	transparentColor;
	char	gxtEntry[8];
	DWORD	_f28;
	DWORD	_f2C;
	DWORD	_f30;
	DWORD	_f34;
	BYTE	textboxStyle;
	BYTE	__align[3];
};

extern CTextDrawer * textDrawers;

union ScriptParam {
	DWORD	dwParam;
	int		nParam;
	float	fParam;
	void *	pParam;
	BYTE *	pbParam;
	char *	szParam;
};

class CScriptThread {	// size = 0xE0
public:

	void parseThread ();	// >> 469F00
	BYTE opcodeHandler00 (WORD opcode);	// >> 465E60

	void getNumberParams (int count);	// >> get integer or float parameters
	ScriptParam * getPointerParam (int type);	// >> 464790 (type ignored in SA)
	ScriptParam * localArrayPtr (WORD off, DWORD idx, int mul);	// >> 463CC0
	void getArrayIndex (int move, WORD * pOff, DWORD * pIdx);	// >> 463CF0
	void setCondResult (BYTE result);	// >> 4859D0 -- set result of boolean operation

	void addToQueue (CScriptThread ** queue);	// >> 464C00
	void removeFromQueue (CScriptThread ** queue);	// >> 464BD0
	void setIP (int addr);	// >> 464DA0 TODO: inline

	void patchCopModelId (int pedType, int * modelId);	// >> 464F50 TODO: это точно метод, но я не уверен, что именно этого объекта

	CScriptThread *	next;
	CScriptThread * prev;
	char			threadName[8];
	BYTE *			baseIp;
	BYTE *			ip;			// instruction pointer
	BYTE *			stack[8];
	WORD			sp;			// stack pointer
	WORD			_f3A;
	ScriptParam		tls[34];	// thread local storage
	BYTE			isActive;
	BYTE			condResult;	// result of the last logical operation
	BYTE			_fC6;
	BYTE			external;
	BYTE			_fC8;
	BYTE			_fC9;
	BYTE			_fCA;
	BYTE			_fCB;
	DWORD			wakeTime;
	WORD			logicalOp;
	BYTE			notFlag;
	BYTE			_fD3;
	BYTE			_fD4;
	BYTE			_fD5;
	WORD			_fD6;
	int				sceneSkip;
	BYTE			_fDC;
	BYTE			_fDD;
	BYTE			_fDE;
	BYTE			_fDF;
};
#pragma pack(pop)

extern BYTE * replayInProgress;

CScriptThread * script_allocThread (BYTE * ip);	// >> 464C20 (6) -- TODO: CScriptEngine::allocThread
void script_process ();	// >> 46A000 (5) -- TODO: CScriptEngine::process