
#ifndef __CHARACTR_H__
#define __CHARACTR_H__

#ifndef _PLATFORM_H_
#include "platform.h"
#endif

#ifndef _SCENICS_H_
#include "scenics.h"
#endif

#ifndef __ENEMIES_H__
#include "enemies.h"
#endif



// CPW: character states (also used as indices into validity tables)
#define CHAR_STATE_IDLE		(0)
#define CHAR_STATE_WALKING	(1)
#define CHAR_STATE_RUNNING	(2)
#define CHAR_STATE_JUMPING	(3)

#define CHAR_NAME_GINGER	(0)
#define CHAR_NAME_WELLY		(1)
#define CHAR_NAME_ROCKY		(2)
#define CHAR_NAME_NICK		(3)
#define CHAR_NAME_FETCHER	(4)
#define CHAR_NAME_GNOME		(5)

#define CRC_ROCKY		(0xb480cbf0)
#define CRC_GINGER		(0xa32b4489)
#define CRC_NICK		(0xbd400d75)
#define CRC_FETCHER		(0x5fbf4a50)
#define CRC_WELLY		(0xa488c2fa)
#define CRC_GNOME		(0xac874324)	// CPW: is actually "C_GNOME"

// CPW: move these to enemies.h when Fred hasn't got it ...
#define CRC_DOG			(0x8164cdae)
#define CRC_MRSTWEEDY	(0xf4d6e01f)
#define CRC_MRTWEEDY	(0x9c66b05c)





#define SWAP_ANYTHING			(0)
#define SWAP_CHICKENTOCHICKEN	(1)
#define SWAP_RATTORAT			(2)

#define CONTROLLER_ENABLED			(0)
#define CONTROLLER_DISABLED			(1)
#define CONTROLLER_DISABLED_RESET	(2)


#define NUM_CONTROL_MAPS	(4)

typedef struct
{
	unsigned short jump;
	unsigned short chuck;	// CPW: 'throw' may cause trouble with C++ compilers!

	unsigned short swapRats;
	unsigned short action;

	unsigned short inventory;
	unsigned short inventoryStep;

	unsigned short pause;
	unsigned short help;

	unsigned short hide;
	unsigned short creep;

	unsigned short cameraL;
	unsigned short cameraR;
}CONTROLMAP;

typedef struct
{
	DVECTOR joyDir;
	DVECTOR camDir;
}MOVEDATA;

typedef struct tagCHARACTER
{
	struct tagCHARACTER *prev;
	struct tagCHARACTER *next;

	struct tagCHARACTER *pAlt;

	ENEMY *pEnemy;	// CPW: we'll create an enemy, just so the enemy code can be used to print it.
					// CPW: so no putting character specific members in the enemy struct; put them in here.
	char (*pVTable)[STATE_NUMBER];
	int (*pHandler)(struct tagCHARACTER *, MOVEDATA *);

	ENEMYINFO	enemyInfo;

// CPW: 	SfxSampleType **ppSamples;

	struct
	{
		short desiredAngle;
		short stillblending;
		int speed;
		int animspeed;
		int anim;
		int oldanim;
		int animflags;
		short shoulderPush;
		short againstWall;
		short againstWallAng;
		short action;
		SCENIC *pPushButton;
		VECTOR pushDir;
		VECTOR desiredPos;
		int gotThere;
		int hidden;	// CPW: ie welly or gnome
		PLATFORMWORK *pPushPlat;
	}movement;

	struct{
		int			heightAtJumpStart;
		int			timeAtJumpTop;
		int			timeAtDoubleJumpTop;
		int			stage;
		int			singleHeight;
	}jump;

}CHARACTER;


typedef struct tagCHARACTERLIST
{
	CHARACTER head;
	int numEntries;
}CHARACTERLIST;



typedef struct
{
	char *sName;		// CPW: name of character (used to search for PSI)
	char (*pVTable)[STATE_NUMBER];	// CPW: validity table for states
	int (*pHandler)(struct tagCHARACTER *, MOVEDATA *);
	int collRadius;						// CPW: radius of collision sphere
	int collYoffset;					// CPW: Y offset of collision sphere
	int	initialState;
}CHARACTERINFO;

extern CHARACTERINFO charInfo[];
extern CHARACTERLIST characterList;


// Puzzles needs this for "chicken in box" to detect the currently controlled character
typedef struct
{
	CHARACTER *pMainChar;	// CPW: current char that is the main character

	CHARACTER *pNormChar;	// CPW: normal character, (ginger, rocky, nick or fetcher)
	CHARACTER *pHideChar;	// CPW: hidey character (welly or gnome)
}CHARACTERVARSTR;

extern CHARACTERVARSTR characterVars;

extern CONTROLMAP controlMaps[];
extern int controlMap;
extern int characterDisableController;
extern int helpCurrentAction;

CHARACTER *characterCreate(CHARACTERINFO *pCI);
void characterFree(CHARACTER *pC);

void characterChange(CHARACTER *pChange, char *sName);
void characterInitialise(void);
void characterMakeMain(CHARACTER *pC);
int characterDistanceBetween(CHARACTER *pC1, CHARACTER *pC2);
void characterMakeMainCRC(unsigned long crc);
CHARACTER *characterGetCRC(unsigned long crc);
CHARACTER *characterGetMainCharacter(void);
void characterProcess(void);
void characterDraw(CHARACTER *pC);
int characterNickAndFetcherHandler(CHARACTER *pC, MOVEDATA *);
int characterGingerAndRockyHandler(CHARACTER *pC, MOVEDATA *);
void chickenPressingAgainstWall(COLLDATA *pCollData, VECTOR *pNormal);
void chickenPressingAgainstPlatform(COLLDATA *pCollData, PLATFORMWORK *pPlat, COLLBOX *pCollBox, VECTOR *pPushDir);
int chickenReadyToPushPlatform(COLLDATA *pCollData, PLATFORMWORK *pPlat, COLLBOX *pCollBox, VECTOR *pPushDir);
void characterDoSwap(int action);
int characterIsThere(CHARACTERINFO *pCI);
void characterSetHideStatus(int);

#endif
