
enum
{
	BALL_MODE_NORMAL,
	BALL_MODE_BOWLING,
	BALL_MODE_POWER,
	BALL_MODE_BEARING,
	BALL_MODE_BEACH,
	BALL_MODE_SNOW,
	BALL_MODE_CRYSTAL,
	NUM_BALL_MODES
};

typedef struct _BallChange
{
	VECTOR	dimAmbient;
	VECTOR	ambient;
	VECTOR	dimAmount;
	LONG	startRadii;
	LONG	endRadii;
	SHORT	timer;
	SHORT	fromBall;
	short	toBall;
	UBYTE	changeOn;
}BALLCHANGE;

typedef	struct	_BoulderData
{
	VECTOR	pos;
	VECTOR	vel;
	VECTOR	oldPos;
	SHORT	time;
	IQUATERNION	qRot;
	UBYTE	hit;
	UBYTE	firstHit;
}BOULDERDATA;

typedef struct _BallCtrl
{
	VECTOR	squash;
	VECTOR	expand;
	VECTOR	squashUpdate;
	VECTOR	expandUpdate;
	VECTOR	squashDelta;
	VECTOR	expandDelta;
	VECTOR	ballPosWhenHit;
	VECTOR	iceData;
	VECTOR	iceRollData;
	VECTOR	iceRollDataVel;
	VECTOR	slideNormal;
	VECTOR	conveyerNormal;
	VECTOR	cancerPos[2];
	LONG	snowAddition;
	int		waterHeight;
	ULONG	ballSpeed;
	SHORT	type;
	SHORT	lastType;
	SHORT	preSnowType;
	USHORT	ballOnGround;
	USHORT	ballOnCeiling;
	USHORT	ballStopMove;
	USHORT	nextHitCount;
	SHORT	ballBob;
	USHORT  ot_depth;	// used for sorting bugle either side of the ball
	USHORT	boomerangActiveTime;
	USHORT	cancerActiveTime;
	SHORT	boomerangTime;
	UBYTE	inWaterFlag;
	UBYTE	shallowWater;
	UBYTE	hurt;
	UBYTE	health;
//	UBYTE	inside_bugle;
	ENEMYPOS *inside_bugle;

	UBYTE	enabled;	// whether tha ball exists at all (zero if it's waiting inside a hoop, or you've given it to the wizard, etc)
	UBYTE	justHitFlag;
	UBYTE	powerwhack;		// ball was whacked (& was bowling)
	UBYTE	anywhack;
	UBYTE	onSticky;
	UBYTE	onIce;
	UBYTE	onIceFlag;
	UBYTE	onConveyer;
	UBYTE	conveyerTimer;
	UBYTE	onTrampoline;
	UBYTE	onWater;
	UBYTE	onSnow;
	UBYTE	snowTexChange;
	UBYTE	lastHit;
	UBYTE	ballSmashed;
	UBYTE	megaSticky;
	UBYTE	boomerangOn;
	//UBYTE	boomerangTime;
	UBYTE	cancerFlag;
	UBYTE	bounceHoldFlag;
	UBYTE	bounceHoldTime;
	UBYTE	noBounce;
	UBYTE	inWind;
}BALLCTRL;


#define BALL_PRINTF(A);  

#define	BALLTHROWSPEED	(4096*12)
#define	BALLSMASHSPEED	(4096*3)
#define	BALLCHANGERATE	5
#define	BALLDAMPENRATE	3584
#define	DAMPSTOP		256
#define	HITMOVESPEED	(4096*12)
#define	CRYSTALBALLSMASH	40000


#define	WHACKSNOWSPEED	5*4096

#define	SPELLCHANGE		1
#define	SNOWCHANGE		2

#define	START		1
#define	SET			2

extern SPRITEX	*ballTex[8];

extern SPRITEX	*cardTex[8];
extern char ballNextMode[];

extern	NEWMODEL	*pCryFrag,*pSnowFrag;
extern long    ballRadius; 

extern	SHORT	nextBoulderTimer;
extern	SHORT	nextBoulderTimer2;

extern BEHAVIOUR_PHYSICS	BallBehaviour[NUM_BALL_MODES];

extern BEHAVIOUR_PHYSICS	BoulderBallPhysics;
extern BEHAVIOUR_PHYSICS	CannonBallPhysics;

extern	COLLDATA	BoulderColl[10];
extern	BOULDERDATA	BoulderData[10];

extern	BALLCTRL	BallCtrl;
extern	BALLCHANGE	BallChange;
extern	VECTOR		ballOldPos;

extern	char *ballNames[];
void	Load_And_Init_Ball();

void	ChangeBall(NEWOBJECT *world ,SPRITEX *spr);

void	ChangeLscapeTex(NEWOBJECT *world ,SPRITEX *spr);
void	ballHitBySpell(int spell_type,int time);

long	BallCloseToHand(void);
void	moveBall(SHORT upDown,SHORT leftRight);
void	ballRender();
void	pausedBallRender(void);


void	BallApplySquash(void);
void	BallUpdateSquash(void);
void	resetBall(void);

void	UpdateBallPos(void);
void	doBallHurt(void);
void	doBallBurst(void);

void	ballPlaceAt(VECTOR *pos);
void	ballComeOutOfHoop(VECTOR *pos, int ya);
void	ballPowerWhackReturn();

void ballPlayBounceEffect(void);

void ActorStartRoll(NEWMODEL *actor,LONG x,LONG z);
void ActorStartRollSide(NEWMODEL *actor,LONG y);
void ActorRotateByAngle(NEWMODEL *actor,LONG y); // will have to put quat stuff back in for models

void	removeSnow(void);


void	addRampBoulder(BOULDERDATA *data);
void	addVentBoulder(BOULDERDATA *data);
void	addSnowBoulder(BOULDERDATA *data);

void	moveBoulder(BOULDERDATA *data);
void	drawBoulder(BOULDERDATA *data);
void	boulderHitCheck(BOULDERDATA *data);
void	snowBoulderHitCheck(BOULDERDATA *data);
void	standAloneBall(void);
void	setupCancerBall(void);