#include "glover.h"
//#include "bff_load.h"
//#include "water.h"
//GLOVECTRL	GloveCtrl;
//VECTOR		GloveVel;

char cheat_call_ball = 1;
USHORT	keyMask=0;
USHORT	aHeld=0;
USHORT	bHeld=0;
USHORT	cHeld=0;
USHORT	dHeld=0;
USHORT	eHeld=0;
USHORT	zHeld=0;
UBYTE	aReleased=FALSE;
UBYTE	bReleased=FALSE;
UBYTE	cReleased=FALSE;
UBYTE	dReleased=FALSE;
UBYTE	eReleased=FALSE;
UBYTE	zReleased=FALSE;
UBYTE	zFlipFlop=FALSE;

INPUTSTATE	InputState;

GLOVERSEG	gloveData[5]=
{
	{112,200},
	{66,81},
	{85,94},
	{95,112},
	{201,208}
};


COLLDATA	gloveColl;


BEHAVIOUR_PHYSICS	GloveBehaviour=
{
	10*4096,			// mass;
	GRAVITY,			// gravity;
	0*4096,				// bounce (glove dont bounce)
	(4096-(4096*0.1)),	// drag
	4096*10,			// maxspeed
	(25*4096*NORMAL_SCALE),			// radius
	4096*8,				// accel
	0,
};


#define	NONE	0
#define	LEFT	1
#define	RIGHT	2
#define	UP		4
#define	DOWN	8

#define	BOUNCEFIX

GLOVECTRL	GloveCtrl;
BODGECTRL	BodgeCtrl;
VECTOR		GloveVel,JoinGlovePos,JoinBallPos;

objectSegDataType  	*GloveSeg;
AnimType			GloveAnim;
ACTOR_ANIMATION		Glover;

SHORT				gloveBallDist,gloveBallDistSteps;

int		testframe=0;


char handActionValidityTable[MAX_HAND_ACTIONS][MAX_HAND_ACTIONS] = 
{

//				IDLE | WALK | JUMP | JOIN | THROW | PWHACK | WHACK | SKID | DUCK | REL  | GETUP | T-AIM | T2CUP | FALL | BOUNCE | BNCE2CUP | AIRWHCK | THRWLND | SLAM | SLM2ST | BALLWALK | CRAWL | CART | CLIMBU | CLIMBD | CLING |CLNGUP| DROP | HURT | PUSH | LOB | CATCH | SPELL | ROTOR | SNATCH | SLIDING | HOPPING | FROG_IDLE | FROG_JUMP | FROG_WALK | SWISH | NOTHING | LOCATE | SPIN | FRG_T   nmespell
//				I	W	J	J	T	P	W	S	D	R	G	T	T	F	B	B	A	T	S	S	B	C	C	CU	CD	CL	CLU	D	H	P	L	C	S
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/*IDLE,*/		{0,	1,	1,	1,	0,	0,	0,	1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	1,	0,	1,	1,	0,	0,	0,	1,	0,	1,	1,	0,	1,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	1},	    /*IDLE,*/		 
/*WALK,*/		{1,	0,	1,	1,	0,	0,	0,	1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	1,	0,	1,	1,	0,	0,	0,	1,	0,	1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	1},	    /*WALK,*/		 
/*JUMP,*/		{0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	1,	0,	1,	0,	0,	0,	1,	1,	0,	0,	0,	0,	0,	1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	1},	    /*JUMP,*/		 
/*JOINED,*/		{0,	0,	0,	0,	0,	1,	0,	0,	0,	1,	0,	1,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*JOINED,*/		 
/*THROW,*/		{0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*THROW,*/		 
/*PREWHACK*/	{0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*PREWHACK*/	 
/*WHACK,*/		{0,	1,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*WHACK,*/		 
/*SKIDDING,*/	{1,	1,	1,	1,	0,	0,	0,	0,	1,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	1,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	1},	    /*SKIDDING,*/	 
/*DUCK,*/		{0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*DUCK,*/		 
/*RELEASE*/		{0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*RELEASE*/ 	 
/*GET-UP */		{1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*GET-UP */ 	 
/*throwaim*/	{0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*throwaim*/ 	 
/*thrw2cup*/	{0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*thrw2cup*/ 	 
/*falling*/		{1,	1,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*falling*/ 	 
/*bouncing*/	{0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	1,	0,	0,	0,	1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*bouncing*/ 	 
/*bnc2cup*/		{0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*bnc2cup*/ 	 
/*airwhack*/	{0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*airwhack*/ 	 
/*thrwland*/	{1,	1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*thrwland*/ 	 
/*slam   */		{0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*slam   */ 	 
/*slam2st*/		{1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*slam2st*/ 	 
/*ballwalk	*/	{0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*ballwalk	*/ 	 
/*crawl		*/	{0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*crawl		*/ 	 
/*cartwheel */	{1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*cartwheel */ 	 
/*climb up*/	{1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*climb up*/ 	 
/*climb down*/	{0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*climb down*/ 	 
/*cling*/		{0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*cling*/		 
/*cling-up*/	{1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*cling-up*/		 
/*dropdown*/	{1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*dropdown*/	 
/*hurt		*/	{1,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*hurt		*/	 
/*push*/		{1,	1,  1,	1,	0,	0,	0,	0,	1,	0,  0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*push*/         
/*lob*/			{1,	1,  0,	0,	0,	0,	0,	0,	0,	0,  0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*lob*/         
/*catch*/		{0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*catch*/
/*spell*/		{1,	1,	0,	0,	0,	0,	0,	0,	0,	0,  0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*spell*/
/*rotor*/		{0,	0,  0,	0,	0,	0,	0,	0,	0,	0,  0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*rotor*/   
/*snatch*/		{0,	0,  0,	1,	0,	0,	0,	0,	0,	0,  0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*snatch*/   
/*sliding*/		{1,	1,  0,	0,	0,	0,	0,	0,	0,	0,	0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*sliding*/
/*hopping*/		{0,	0,  0,	0,	0,	0,	0,	0,	0,	0,	0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*hopping*/
/*frog_idle*/	{0,	0,  0,	0,	0,	0,	0,	0,	0,	0,	0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	1,	0,	0,	0,	0,	1,	0},	    /*frog_idle*/
/*frog_jump*/	{0,	0,  0,	0,	0,	0,	0,	0,	0,	0,	0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0},	    /*frog_jump*/
/*frog_walk*/	{0,	0,  0,	0,	0,	0,	0,	0,	0,	0,	0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	1,	0,	0,	0,	0,	0,	0,	0},	    /*frog_walk*/
/*swish*/		{0,	0,  0,	0,	0,	0,	0,	0,	0,	0,	0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*swish*/
/*nothing*/		{1,	1,  0,	0,	0,	0,	0,	0,	0,	0,	0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*nothing*/
/*locate*/		{0,	0,  0,	1,	0,	0,	0,	0,	0,	0,	0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	1,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1},		/*locate*/
/*spin*/		{0,	0,  0,	0,	0,	0,	0,	0,	0,	0,	0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*spin*/
/*frog_tongue*/	{0,	0,  0,	0,	0,	0,	0,	0,	0,	0,	0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0},	    /*frog_tongue*/
/*nmespel*/		{0,	0,  0,	1,	0,	0,	0,	0,	0,	0,	0,  0,  0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	1,	0,	0,	0,	0,	0,	0,	0,	1,	0,	0,	0}		/*nmespell*/
};


//KEYFRAME	rot1,rot2;
//KEYFRAME	scale1,scale2;

//SQKEYFRAME	rot1,rot2;
//SVKEYFRAME	move1,move2;
//SVKEYFRAME	scale1,scale2;

SQKEYFRAME	rot1[2] =
	{
	{{0,0,0,4096},0},
	{{0,0,0,4096},32767}
	};


SVKEYFRAME	move1[2] =
	{
	{{0,0,0},0},
	{{0,0,0},32767}
	};
SVKEYFRAME	scale1[2] =
	{
	{{4096>>2,4096>>2,4096>>2},0},
	{{4096>>2,4096>>2,4096>>2},32767}
	};



/****************************************************/
// Temp stuff for Dennis move to enemies when finished

COLLDATA	DennisColl;

VECTOR		DennisPos,DennisVel;

BEHAVIOUR_PHYSICS	DennisBehaviour=
{
	10*4096,			// mass;
	GRAVITY,			// gravity;
	0*4096,				// bounce (Den don't bounce)
	4096,	// drag
	4096*10,			// maxspeed
	28*4096,			// radius
	4096,				// accel
};

/****************************************************/
// Temp stuff for Swish move to enemies when finished


COLLDATA	SwishColl;

VECTOR		SwishPos,SwishVel;


BEHAVIOUR_PHYSICS	SwishBehaviour=
{
	10*4096,			// mass;
	GRAVITY,			// gravity;
	0*4096,				// bounce (Den don't bounce)
	4096,	// drag
	4096*10,			// maxspeed
	28*4096,			// radius
	4096,				// accel
};

SPRITEX		*GloveTex[2];

/****************************************************/


// Called after loading generic.bff, which is now only done once in main
// Note that the new object is never freed (but neither is the generic bff, now)
void handTidyGloveObject()
{
	NEWOBJECT	*temp;
	pGlovePSA = BFF_IsModelLoaded("LOGLOVE",&GloveSeg);
///////////////////////////////////////////////////////////
// NOTE: This bit of code stops the parent keyframe problem

	temp = (NEWOBJECT*)MALLOC(sizeof(NEWOBJECT),"TEMP NEWOBJECT");
	memcpy(temp,&pGlovePSA->world,sizeof(NEWOBJECT));
	temp->child=pGlovePSA->world.child;	
	
	pGlovePSA->world.child->parent=temp;
	pGlovePSA->world.child->next->parent=temp;
	pGlovePSA->world.child->next->next->parent=temp;

	temp->parent=&pGlovePSA->world;
	pGlovePSA->world.child=temp; 

	pGlovePSA->world.rotatekeys=&rot1[0];
	pGlovePSA->world.movekeys=&move1[0];
	pGlovePSA->world.scalekeys=&scale1[0];
	pGlovePSA->world.numScaleKeys=1;
	pGlovePSA->world.numRotateKeys=1;
	pGlovePSA->world.numMoveKeys=1;

// NB - the segment table is now storing IN THE PSA.
// Hence the "the glove generates an extra segment for itself" has had to be a special
// case in BFF_PSA. Cor.
	objectSetupSegmentSort(pGlovePSA);

	fixBadKeyFrames();
}

SINCOSTABLE	*SinCosTable;

// Called per-level
void	Load_And_Init_Glove()
{
// This is Fred being paranoid about recordkey demos
	keyMask=0;
	aHeld=0;
	bHeld=0;
	cHeld=0;
	dHeld=0;
	eHeld=0;
	zHeld=0;
	aReleased=FALSE;
	bReleased=FALSE;
	cReleased=FALSE;
	dReleased=FALSE;
	eReleased=FALSE;
	zReleased=FALSE;
	zFlipFlop=FALSE;

	//SinCosTable=LoadFile("SINCOS.DAT");
//gloveArmR=pGlovePSA->world.child->child->next->next->child->next->next->next->next->next;

//	pGlovePSA=LoadPSA("WORLDS\\GENERIC\\NME\\LOGLOVE.PSA");
//	GloveSeg=objectLoadSeg("WORLDS\\GENERIC\\NME\\LOGLOVE.SEG");

//	pRotorPSA=LoadPSA("WORLDS\\GENERIC\\NME\\ROTOR.PSA");
	pRotorPSA=BFF_IsModelLoaded("ROTOR",NULL);
	if(pRotorPSA)
	{
		objectSetupSegmentSort(pRotorPSA);
		pRotorPSA->globalscale.vx=(800*NORMAL_SCALE);
		pRotorPSA->globalscale.vy=(800*NORMAL_SCALE);
		pRotorPSA->globalscale.vz=(800*NORMAL_SCALE);
	}

	GloveAnim.segInfo=GloveSeg;
	Glover.animInfo=&GloveAnim;

	GloveTex[0]=FindTexture("WHITE2");	// normal white glove texure
	GloveTex[1]=FindTexture("PLASTER2");// Plaster texture for glove

//////////////////////////////////////////////////////////////

 	pGlovePSA->globalscale.vx=(400*NORMAL_SCALE);
 	pGlovePSA->globalscale.vy=(400*NORMAL_SCALE);
 	pGlovePSA->globalscale.vz=(400*NORMAL_SCALE);

//	glovePos.vx=215363;
//	glovePos.vy=-202752;
//	glovePos.vz=123356;
//	glovePos.vx=GloveStartPos.vx;
//	glovePos.vy=GloveStartPos.vy;
//	glovePos.vz=GloveStartPos.vz;

	pGlovePSA->position.vx=glovePos.vx/4096;
	pGlovePSA->position.vy=glovePos.vy/4096;
	pGlovePSA->position.vz=glovePos.vz/4096;

	pGlovePSA->world.rotate.vx=0;
	pGlovePSA->world.rotate.vy=0;
	pGlovePSA->world.rotate.vz=0;

	GloveCtrl.direction=2048;
	GloveCtrl.radius=GLOVENORMALRADIUS;
	GloveCtrl.speed=0;
	GloveCtrl.oldSpeed=0;
	GloveCtrl.action=HAND_IDLE;
	GloveCtrl.lastAction=HAND_IDLE;
	GloveCtrl.active=TRUE;
	GloveCtrl.onGround=TRUE;
	GloveCtrl.hitBall=FALSE;
	GloveCtrl.flags=GLOVEMOVE;
	GloveCtrl.ballWithHand=FALSE;
	GloveCtrl.disableTimer=0;
	GloveCtrl.padDisableTimer=0;
	GloveCtrl.idleTimer=0;
	GloveCtrl.idleAction=FALSE;
	GloveCtrl.throwDelay=0;
	GloveCtrl.preDelay=0;
	GloveCtrl.idleSelection=0;
	GloveCtrl.clingFlag=FALSE;
	GloveCtrl.pushFlag=FALSE;
	GloveCtrl.hurtFlag=FALSE;
	GloveCtrl.hurtFlagBall=FALSE;
	GloveCtrl.dieCount=FALSE;
	GloveCtrl.flash=FALSE;
	GloveCtrl.ballCollision=TRUE;
	GloveCtrl.dennisJump=FALSE;
	GloveCtrl.dennisJumpHit=FALSE;
	GloveCtrl.lives=3;	// Difficulty dependant?
	GloveCtrl.health=3;
	GloveCtrl.maxHealth=3;
	GloveCtrl.tipFlag=FALSE;
	GloveCtrl.deathType=NULL;
	GloveCtrl.deathTypeBall=NULL;
	GloveCtrl.onIce=FALSE;
	GloveCtrl.onIceFlag=FALSE;
	GloveCtrl.onSnow=FALSE;
	GloveCtrl.insideBubble=FALSE;
	GloveCtrl.forceSlide=FALSE;
	GloveCtrl.forceSlideDelay=0;
	GloveCtrl.blinkTime=10;
	GloveCtrl.garibCollectState=FALSE;
	GloveCtrl.levelFinished=FALSE;
	GloveCtrl.reHealthFlag=FALSE;
	GloveCtrl.allLevelGaribs=TRUE;
	GloveCtrl.cameoDisableDamage=FALSE;
	ClearAnimQueue(&Glover);

	AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,4096);
	
	gloveColl.nBoxes=numCollBoxes;
	gloveColl.radius=(25*4096*NORMAL_SCALE);
	gloveColl.pCollBox=collBox;
	gloveColl.pVel=&gloveVel;
	gloveColl.pPos=&glovePos;


	gloveColl.physics=&GloveBehaviour;
	gloveColl.physicsModel=0;	// only one for glove
	gloveColl.physics->gravity=gravity;

	cameraColl.nBoxes=numCollBoxes; // collision stuff for camera
	cameraColl.radius=20*4096;
	cameraColl.pCollBox=collBox;
	cameraColl.pVel=&cameraVel;
	cameraColl.pPos=&cameraPos;
	cameraColl.pRot=&cameraRot;
	cameraColl.physics=NULL;
	GloveCtrl.handOnBall=FALSE;

	GloveCtrl.enabled = FALSE;	// note - starts in disabled state
	GloveCtrl.padIn = 0;
	GloveCtrl.padOld = 0;
	GloveCtrl.padInDB = 0;
	GloveCtrl.handHurtTime=NULL;
	GloveCtrl.currentDisplayedHealth=3;
	GloveCtrl.healthChange=FALSE;
	handpower_type = 0;
	handpower_timer = 0;

	GloveCtrl.directionSeekSpeed=0;
	GloveCtrl.spellCast=FALSE;

	//gameInfo.keyRecordFlag=RECORD;
	//gameInfo.keyRecordFlag=NULL;
	keyRecordCount=0;

	gloveShinR=pGlovePSA->world.child->child->child;
	gloveShinL=pGlovePSA->world.child->child->next->child;
	gloveArmR=pGlovePSA->world.child->child->next->next->child->next->next->next->next->child;
	gloveArmL=pGlovePSA->world.child->child->next->next->child->next->next->next->child;


	ChangeBall(pGlovePSA->world.child->child->child,GloveTex[0]);
	ChangeBall(pGlovePSA->world.child->child->next->child,GloveTex[0]);
	ChangeBall(pGlovePSA->world.child->child->next->next->child->next->next->next->next->child,GloveTex[0]);
	ChangeBall(pGlovePSA->world.child->child->next->next->child->next->next->next->child,GloveTex[0]);

	BodgeCtrl.carnivalPlat=NULL;
	BodgeCtrl.hitPlat=FALSE;
	GloveBehaviour.accel=4096*8;

}
/********************************************************************************/
void	fixBadKeyFrames(void)
{
NEWOBJECT	*mouth;
SVKEYFRAME	*scalekeys,*movekeys,*temp;
LONG		checkStart,checkEnd;

	mouth=pGlovePSA->world.child->child->next->next->child->next->next->next->next->next;
	movekeys = mouth->movekeys;
	scalekeys = mouth->scalekeys;

	checkStart=680; // fixes fall death
	checkEnd=692;

	while (movekeys->time < checkStart) movekeys++;
	temp=movekeys--;
	while (movekeys->time < checkEnd)
	{
		movekeys->vect.x=temp->vect.x;
		movekeys->vect.y=temp->vect.y;
		movekeys->vect.z=temp->vect.z;	
		movekeys++;
	}

	while (scalekeys->time < checkStart) scalekeys++;
	temp=scalekeys--;
	while (scalekeys->time < checkEnd)
	{
		scalekeys->vect.x=temp->vect.x;
		scalekeys->vect.y=temp->vect.y;
		scalekeys->vect.z=temp->vect.z;	
		scalekeys++;
	}

	checkStart=958;
	checkEnd=971;

	movekeys = mouth->movekeys;
	scalekeys = mouth->scalekeys;

	while (movekeys->time < checkStart) movekeys++;
	temp=movekeys--;
	while (movekeys->time < checkEnd)
	{
		movekeys->vect.x=temp->vect.x;
		movekeys->vect.y=temp->vect.y;
		movekeys->vect.z=temp->vect.z;	
		movekeys++;
	}

	while (scalekeys->time < checkStart) scalekeys++;
	temp=scalekeys;
	while (scalekeys->time < checkEnd)
	{
		scalekeys->vect.x=temp->vect.x;
		scalekeys->vect.y=temp->vect.y;
		scalekeys->vect.z=temp->vect.z;	
		scalekeys++;
	}
}


/********************************************************************************/
void resetGlove(void)
{
NEWOBJECT	*gloveShinR=pGlovePSA->world.child->child->child;
NEWOBJECT	*gloveShinL=pGlovePSA->world.child->child->next->child;
NEWOBJECT	*gloveArmR=pGlovePSA->world.child->child->next->next->child->next->next->next->next->child;
NEWOBJECT	*gloveArmL=pGlovePSA->world.child->child->next->next->child->next->next->next->child;


	DB("reseting glove \n");
 	pGlovePSA->globalscale.vx=(400*NORMAL_SCALE);
 	pGlovePSA->globalscale.vy=(400*NORMAL_SCALE);
 	pGlovePSA->globalscale.vz=(400*NORMAL_SCALE);

	pGlovePSA->position.vx=GloveStartPos.vx/4096;
	pGlovePSA->position.vy=GloveStartPos.vy/4096;
	pGlovePSA->position.vz=GloveStartPos.vz/4096;

	glovePos.vx=GloveStartPos.vx;
	glovePos.vy=GloveStartPos.vy;
	glovePos.vz=GloveStartPos.vz;

	gloveVel.vx=0;
	gloveVel.vy=0;
	gloveVel.vz=0;

	GloveCtrl.direction=2048;
	GloveCtrl.radius=GLOVENORMALRADIUS;
	GloveCtrl.speed=0;
	GloveCtrl.oldSpeed=0;
	GloveCtrl.action=HAND_IDLE;
	GloveCtrl.lastAction=HAND_IDLE;
	GloveCtrl.active=TRUE;
	GloveCtrl.onGround=TRUE;
	GloveCtrl.hitBall=FALSE;
	GloveCtrl.flags=GLOVEMOVE;
	GloveCtrl.ballWithHand=FALSE;
	GloveCtrl.disableTimer=0;
	GloveCtrl.padDisableTimer=0;
	GloveCtrl.idleTimer=0;
	GloveCtrl.idleAction=FALSE;
	GloveCtrl.throwDelay=0;
	GloveCtrl.preDelay=0;
	GloveCtrl.idleSelection=0;
	GloveCtrl.clingFlag=FALSE;
	GloveCtrl.pushFlag=FALSE;
	GloveCtrl.hurtFlag=FALSE;
	GloveCtrl.dieCount=FALSE;
	GloveCtrl.flash=FALSE;
	gloveColl.physics->gravity=gravity;

	GloveCtrl.health=GloveCtrl.maxHealth;

	GloveCtrl.dieCount=0;
	GloveCtrl.hurtFlag=NULL;
	GloveCtrl.deathType=NULL;
	GloveCtrl.hurtFlagBall=NULL;
	GloveCtrl.deathTypeBall=NULL;
	GloveCtrl.insideBubble=FALSE;
	//GloveCtrl.garibCollectState=FALSE;
	GloveCtrl.levelFinished=FALSE;

	GloveCtrl.reHealthFlag=FALSE;

	GloveCtrl.ballCollision=TRUE;
	GloveCtrl.dennisJump=FALSE;
	GloveCtrl.dennisJumpHit=FALSE;
	GloveCtrl.tipFlag=FALSE;

	GloveCtrl.forceSlide=FALSE;
	GloveCtrl.forceSlideDelay=0;
	GloveCtrl.cameoDisableDamage=FALSE;

	GloveCtrl.onIce=FALSE;
	GloveCtrl.onIceFlag=FALSE;
	GloveCtrl.onSnow=FALSE;
	GloveCtrl.blinkTime=10;
	ChangeBall(gloveShinR,GloveTex[0]);
	ChangeBall(gloveShinL,GloveTex[0]);
	ChangeBall(gloveArmR,GloveTex[0]);
	ChangeBall(gloveArmL,GloveTex[0]);

	GloveCtrl.directionSeekSpeed=0;

	GloveCtrl.handHurtTime=NULL;
	GloveCtrl.enabled = FALSE;	// note - starts in disabled state
	GloveCtrl.spellCast=FALSE;

	pGlovePSA->world.rotate.vx =0;
	AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048);
	GloveCtrl.handOnBall=FALSE;
	gloveVel.vx=0;
	gloveVel.vy=0;
	gloveVel.vz=0;

	handpower_timer = 0;
	handpower_duration = 0;
	handpower_type = 0;

	GloveCtrl.pushingPlatform = 0;

	GloveCtrl.onIce=FALSE;
	GloveCtrl.onIceFlag=FALSE;

	ZEROVECTOR(&GloveCtrl.slideData);
	ZEROVECTOR(&GloveCtrl.iceData);
	GloveCtrl.healthChange=TRUE;
	UpdateOverlays();

	GloveBehaviour.accel=4096*8;

	//gameInfo.keyRecordFlag=RECORD;
	//keyRecordCount=0;
}

/********************************************************************************/
void	Control_Glove()
{
	// Now need to do animation

	//ANIM_STARTSPEED(GloveAnim,0,1024);

	GloveCtrl.actionTime++;
	GloveCtrl.spellActionTime++;

	if (CamVars.mode!=ZOOM) moveGlove();
	else
	{
		GloveCtrl.targetSpeed=0;
		GloveCtrl.speed=0;
	}
	MaintainAction();
}
/*********************************************************************************************/
/*************************************************************************************************/
/*************************************************************************************************/
/*************************************************************************************************/
/*	--------------------------------------------------------------------------------
	Function 	: ActionAllowed
	Purpose 	: determine if this action is allowed from the current action
	Parameters 	: hand action, requested action
	Returns 	: bool
	Info 		: looks in a table to determine result
*/
//BOOL	ActionAllowed(int handAction, int requestedAction)
//{
//	return (handActionValidityTable[handAction][requestedAction]);
//}
//changed to a define     ANO.

/*********************************************************************************************/

/*********************************************************************************************/
// Vars for demo ksy record

#if RECORDKEYS == YES
USHORT	keyRecord[16384];
#else
USHORT*	keyRecord;
#endif

USHORT	keyRecordCount=0;
//VECTOR	camRecord;
//CAMERAVARS	camStatus;
//VECTOR	gloveRecord;
//VECTOR	ballRecord;

USHORT		padState;
SHORT		padX,padY;

/*********************************************************************************************/
void	moveGlove(void)
{
	SHORT	leftRight=0,upDown=0;
	LONG	temp;
	VECTOR	tempV;
	USHORT	padIn;

/*
			if((TriggerAtFrame(934.1,&hand)) || (TriggerAtFrame(942,&hand)) || (TriggerAtFrame(950,&hand)) || (TriggerAtFrame(1079.1,&hand)) || (TriggerAtFrame(1084,&hand)) || (TriggerAtFrame(1088,&hand)))
				PlaySample(FX_HAND_FOOTSTEP_LEFT, &hand.pos, 120, 110+Random(40));
			else if((TriggerAtFrame(937,&hand)) || (TriggerAtFrame(946,&hand)) || (TriggerAtFrame(954,&hand)) || (TriggerAtFrame(1082,&hand)) || (TriggerAtFrame(1086,&hand)) || (TriggerAtFrame(1090,&hand)))
				PlaySample(FX_HAND_FOOTSTEP_RIGHT, &hand.pos, 120, 110+Random(40));
*/

#if	(RELEASE==NO)
	if (pad[1]&PAD_R2) gloveVel.vy+=(5*4096);
#endif


	if (GloveCtrl.spellCastTimer) GloveCtrl.spellCastTimer--;

	if (garibscollected && !(garibscollected%10) && GloveCtrl.reHealthFlag)
	{
		if (GloveCtrl.health<GloveCtrl.maxHealth)
		{
			GloveCtrl.health++;
			GloveCtrl.healthChange=TRUE;
		}
		if (BallCtrl.health<4) BallCtrl.health++;
		if (BallCtrl.health==4) BallCtrl.hurt=FALSE;
		GloveCtrl.reHealthFlag=FALSE;
		switch(GloveCtrl.health)
		{
			case 4:
				if (GloveCtrl.maxHealth<4) break;
				ChangeBall(gloveArmL,GloveTex[0]);
				break;
			case 3:	// 1st hit
				ChangeBall(gloveShinR,GloveTex[0]);
				break;
			case 2:
				ChangeBall(gloveArmR,GloveTex[0]);
				break;
			case 1:
				ChangeBall(gloveShinL,GloveTex[0]);
				break;
		}
	}
	
	if (garibscollected%10) GloveCtrl.reHealthFlag=TRUE;

	if(!GloveCtrl.enabled)
		return;

	if ( ((numGaribs-garibscollected)==0) && !GloveCtrl.garibCollectState && numGaribs)
	{
		GloveCtrl.garibCollectState=SET;
		GloveCtrl.lives++;

// I've moved this to the GameState update / check in loadlnd.c, so it only happens once per world ever - Fred
		/*
		switch (level)
		{
			case ATLANTIS3:
			case CARNIVAL3:
			case PIRATES3:
			case PREHISTORIC3:
			case FEAR3:
			case SPACE3:
				if (GloveCtrl.allLevelGaribs == FALSE) break;
				GloveCtrl.maxHealth++;
				GloveCtrl.health++;
				GloveCtrl.healthChange=TRUE;
				DB ("upping max health\n");
				break;
		}
		*/
	}

	//if ( GloveCtrl.forceSlide 

	// TEST CODE ONLY!!!
	//if (pad[1]&PAD_UP) ChangeBall(pGlovePSA->world.child->child->next->next->child->next->next->next->next->child,GloveTex[1]);
	//if (pad[1]&PAD_DOWN) ChangeBall(pGlovePSA->world.child->child->next->next->child->next->next->next->next->child,GloveTex[0]);
	GloveCtrl.active=TRUE;
	GloveCtrl.disableTimer=0;
	GloveCtrl.padDisableTimer=0;


	if ( GloveCtrl.active && GloveCtrl.disableTimer==0 && !GloveCtrl.padDisableTimer)
	{
		padState=padIn=pad[0];
		//GloveCtrl.leftRight=padX=leftRight=(nleftx[0]);
		//GloveCtrl.upDown=padY=upDown=-(nlefty[0]);

		padX=leftRight=(nleftx[0]);
		padY=upDown=-(nlefty[0]);

		if (!CamVars.camChanged)
		{
			GloveCtrl.leftRight=padX;
			GloveCtrl.upDown=padY;
		}


		//if (zFlipFlop)
		//{
		//	if (!(padIn&PAD_L2) ) zFlipFlop=FALSE;
		//	else {zHeld=FALSE;zReleased=FALSE;padIn=padIn^PAD_L2;}
		//}
	}
	else
	{
		padState=padIn=0;
		padX=leftRight=0;
		padY=upDown=0;
	}

	if (GloveCtrl.padDisableTimer)
		GloveCtrl.padDisableTimer--;


	GloveCtrl.padIn = padIn;
	GloveCtrl.padInDB = ((GloveCtrl.padOld) ^ (GloveCtrl.padIn)) & GloveCtrl.padIn;
	GloveCtrl.padOld = GloveCtrl.padIn;

	//if (GloveCtrl.forceSlide) DB ("slide here\n");
	//GloveCtrl.forceSlide=FALSE;

	if (gameInfo.keyRecordFlag==RECORD)
	{
		//DB ("R %d",keyRecordCount);
		temp=padIn;
		leftRight=0;
		upDown=0;
		if (padIn&PAD_LEFT) leftRight=4096;
		if (padIn&PAD_RIGHT) leftRight=-4096;
		if (padIn&PAD_UP) upDown=4096;
		if (padIn&PAD_DOWN) upDown=-4096;

		if (keyRecordCount<16384)
		{
			keyRecord[keyRecordCount]=temp;
			//keyRecordCount++;
		}
	}

	if (gameInfo.keyRecordFlag==PLAYBACK)
	{
		//DB ("P %d",keyRecordCount);
		padIn=keyRecord[keyRecordCount];
		leftRight=0;
		upDown=0;
		if (padIn&PAD_LEFT) leftRight=4096;
		if (padIn&PAD_RIGHT) leftRight=-4096;
		if (padIn&PAD_UP) upDown=4096;
		if (padIn&PAD_DOWN) upDown=-4096;
	}


	if ( GloveCtrl.insideSnowBall )
	{
		if (GloveCtrl.deathType) GloveCtrl.attachedBoulder->time=0;
		if (glovePos.vz<6392400 && GloveCtrl.attachedBoulder->hit) GloveCtrl.attachedBoulder->time=0;
		else if (debounce[0])
		{
			GloveCtrl.attachedBoulder->time-=8;
		}
		return;
	}

	if (GloveCtrl.garibCollectState==SET)
	{
		if (GloveCtrl.onGround && (GloveCtrl.action==HAND_IDLE || GloveCtrl.action==HAND_WALK))
		{
			sfxPlay3D(globalFX,SFX_HAND2_VICTORY1 + (RANDOM256() & 3),&glovePos);
			GloveCtrl.action=HAND_ALLGARIBS;
			AddToQueue(&Glover,HANDANIM_OKAY,NO,NO,4096);
			AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
			GloveCtrl.garibCollectState=255;
		}
	}

	if (GloveCtrl.levelFinished==START)
	{
		sfxPlay3D(globalFX,SFX_HAND2_VICTORY1 + (RANDOM256() & 3),&glovePos);
		GloveCtrl.action=HAND_LEVELCOMPLETE;
		GloveCtrl.actionTime=0;
		AddToQueue(&Glover,HANDANIM_ROLL2SPIN,NO,NO,4096);
		AddToQueue(&Glover,HANDANIM_CELEBRATE,NO,YES,6144);
		AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
		GloveCtrl.levelFinished=SET;

		if (!GloveCtrl.garibCollectState) GloveCtrl.allLevelGaribs = FALSE;
/*
		if (!GloveCtrl.garibCollectState) GloveCtrl.allLevelGaribs = FALSE;
		else
		{
			GloveCtrl.maxHealth++;
			GloveCtrl.health++;
			DB ("upping max health\n");

			switch (level)
			{
				case ATLANTIS3:
				case CARNIVAL3:
				case PIRATES3:
				case PREHISTORIC3:
				case FEAR3:
				case SPACE3:
					GloveCtrl.maxHealth++;
					GloveCtrl.health++;
					DB ("upping max health\n");
					break;

			}
		}
		*/
	}


	if (GloveCtrl.active && GloveCtrl.disableTimer==0)
	{
		if (zFlipFlop)
		{
			if (!(padIn&PAD_L2) ) zFlipFlop=FALSE;
			else {zHeld=FALSE;zReleased=FALSE;padIn=padIn^PAD_L2;}
		}
	}
											    
	aReleased=FALSE;
	bReleased=FALSE;
	cReleased=FALSE;
	dReleased=FALSE;
	eReleased=FALSE;
	zReleased=FALSE;

	if (padIn&PAD_CIRCLE) aHeld++;
	else if (aHeld)
	{
		aHeld=0;
		aReleased=TRUE;
	}

	if (InputState.aStateHoldTime)
	{
		//InputState.cStateHoldTime--;
		if (aHeld)
		{
			aHeld=0;
			aReleased=TRUE;
		}
		else InputState.aStateHoldTime=0;
	}

	if (InputState.aStateChange && GloveCtrl.actionTime==5)
	{
		InputState.aHeld=aHeld;
	}
	if (InputState.aStateChange && GloveCtrl.actionTime>5)
	{
		if (!InputState.aHeld && !aHeld) aHeld=1;
		else if (InputState.aHeld && aHeld) aHeld=1;
		else
		{
			InputState.aStateChange=FALSE;
		}
	}


	if (padIn&PAD_CROSS) bHeld++;
	else if (bHeld)
	{
		bHeld=0;
		bReleased=TRUE;
	}

	if (InputState.bStateHoldTime)
	{
		//InputState.cStateHoldTime--;
		if (bHeld)
		{
			bHeld=0;
			bReleased=TRUE;
		}
		else InputState.bStateHoldTime=0;
	}

	InputState.bHeld=bHeld;


	if (padIn&PAD_SQUARE) cHeld++;
	else if (cHeld)
	{
		cHeld=0;
		cReleased=TRUE;
	}

	if (InputState.cStateHoldTime)
	{
		//InputState.cStateHoldTime--;
		if (cHeld)
		{
			cHeld=0;
			cReleased=TRUE;
		}
		else InputState.cStateHoldTime=0;
	}

	if (InputState.cStateChange && GloveCtrl.actionTime==5)
	{
		InputState.cHeld=cHeld;
	}
	if (InputState.cStateChange && GloveCtrl.actionTime>5)
	{
		if (!InputState.cHeld && !cHeld) cHeld=1;
		else if (InputState.cHeld && cHeld) cHeld=1;
		else
		{
			InputState.cStateChange=FALSE;
		}
	}



	if (padIn&PAD_TRIANGLE) dHeld++;
	else if (dHeld)
	{
		dHeld=0;
		dReleased=TRUE;
	}

	if (padIn&PAD_R2) eHeld++;
	else if (eHeld)
	{
		eHeld=0;
		eReleased=TRUE;
	}

	if (padIn&PAD_L2) zHeld++;
	else if (zHeld)
	{
		zHeld=0;
		zReleased=TRUE;
	}

	if (InputState.zStateHoldTime)
	{
		//InputState.cStateHoldTime--;
		zReleased=0;
		if (zHeld)
		{
			zHeld=0;
			zReleased=0;
		}
		else InputState.zStateHoldTime=0;
	}

	if (keyMask&ABUTTON)
	{
		if ( aReleased ) keyMask=NULL;
		aHeld=0;
		aReleased=0;
		zHeld=0;
		zReleased=0;
	}
	if (keyMask&BBUTTON)
	{
		if ( bReleased ) keyMask=NULL;
		bHeld=0;
		bReleased=0;
		zHeld=0;
		zReleased=0;
	}
//////////////////////////////////////////
/*
	if (gameInfo.keyRecordFlag==RECORD)
	{
		temp=0;

		if (upDown>0) temp+=1<<0;
		else if (upDown<0) temp+=1<<1;

		if (leftRight>0) temp+=1<<2;
		else if (leftRight<0) temp+=1<<3;

		if (aHeld) temp+=1<<4;
		if (bHeld) temp+=1<<5;
		if (cHeld) temp+=1<<6;
		if (dHeld) temp+=1<<7;
		if (eHeld) temp+=1<<8;
		if (zHeld) temp+=1<<9;

		if (aReleased) temp+=1<<10;
		if (bReleased) temp+=1<<11;
		if (cReleased) temp+=1<<12;
		if (dReleased) temp+=1<<13;
		if (eReleased) temp+=1<<14;
		if (zReleased) temp+=1<<15;

		if (keyRecordCount<16384)
		{
			keyRecord[keyRecordCount]=temp;
			keyRecordCount++;
		}
	}

	if (gameInfo.keyRecordFlag==PLAYBACK)
	{
		temp=keyRecord[keyRecordCount];

		if ( temp&(1<<0) ) upDown=4096;
		if ( temp&(1<<1) ) upDown=-4096;

		if ( temp&(1<<2) ) leftRight=4096;
		if ( temp&(1<<3) ) leftRight=-4096;
		
		if ( temp&(1<<4) ) aHeld=1;
		if ( temp&(1<<5) ) bHeld=1;
		if ( temp&(1<<6) ) cHeld=1;
		if ( temp&(1<<7) ) dHeld=1;
		if ( temp&(1<<8) ) eHeld=1;
		if ( temp&(1<<9) ) zHeld=1;

		if ( temp&(1<<10) ) aReleased=1;
		if ( temp&(1<<11) ) bReleased=1;
		if ( temp&(1<<12) ) cReleased=1;
		if ( temp&(1<<13) ) dReleased=1;
		if ( temp&(1<<14) ) eReleased=1;
		if ( temp&(1<<15) ) zReleased=1;
		//keyRecordCount++;
	}
*/
	if (aHeld && GloveCtrl.tipFlag)
	{
		// activate Mr Tip
		gameCtrl.MrTipActive=TRUE;
		gameCtrl.state=FALSE;
		DB ("activating tip\n");
		GloveCtrl.disableTimer=10;
		aHeld=0;
		ActorStartRoll(pBallPSA, 0 , 0 );
	}



	if (GloveCtrl.action==HAND_ROTOR)
	{
		if (bHeld && gloveVel.vy<ROTORMAXYSPEED)
		{
			gloveVel.vy+=(gloveColl.physics->gravity+4096);
			if ( GloveCtrl.rotorSpinSpeed<768 ) GloveCtrl.rotorSpinSpeed+=64;
			if (GloveCtrl.lastAction==HAND_JOINED) ballVel.vy=gloveVel.vy;
		}
		else if (aHeld)
		{
			if (gloveVel.vy<0)
			{
				if (gloveVel.vy<gloveColl.physics->gravity+4096)
					gloveVel.vy+=(gloveColl.physics->gravity+4096);
				else gloveVel.vy=(gloveColl.physics->gravity+4096);
			}
			else if (gloveVel.vy>0)
			{
				if (gloveVel.vy>4096)
					gloveVel.vy-=4096;
				else gloveVel.vy=0;
			}
			if ( GloveCtrl.rotorSpinSpeed > 512 ) GloveCtrl.rotorSpinSpeed-=32;
			else if ( GloveCtrl.rotorSpinSpeed < 512 ) GloveCtrl.rotorSpinSpeed+=32;
			if (GloveCtrl.lastAction==HAND_JOINED) ballVel.vy=gloveVel.vy;
		}
		else if ( GloveCtrl.rotorSpinSpeed > 256 ) GloveCtrl.rotorSpinSpeed-=32;

		if (gloveVel.vy>ROTORMAXYSPEED) gloveVel.vy=ROTORMAXYSPEED;
		else if (gloveVel.vy<-ROTORMAXYSPEED) gloveVel.vy=-ROTORMAXYSPEED;
	}

	if (GloveCtrl.action==HAND_HOPPING)
	{
		if ( bHeld ) GloveCtrl.dennisJumpHit=TRUE;
		else GloveCtrl.dennisJumpHit=FALSE;
		//DB ("setting states %d\n",aHeld);
	}

	GloveCtrl.ballSpellBodge=FALSE;

	if (gloveColl.nHitPlats)
	{
		if ( ((DYNCOLLBOX *)(gloveColl.hitPlats[0].pPlatform))->pPlatDef->head.tag==52 && level==PIRATES1)
		{
			GloveCtrl.ballSpellBodge=TRUE;
			//printf ("on platfrom from hell\n");
		}
	}

	if (ballColl.nHitPlats)
	{
		if ( ((DYNCOLLBOX *)(ballColl.hitPlats[0].pPlatform))->pPlatDef->head.tag==52 && level==PIRATES1)
		{
			GloveCtrl.ballSpellBodge=TRUE;
			//printf ("on platfrom from hell\n");
		}
	}


/*	if (GloveCtrl.action==HAND_SWISH)
	{
		if ( bHeld && GloveCtrl.mount->animinfo.num !=NMEANIM_ACTION1) GloveCtrl.dennisJumpHit=TRUE;
		else GloveCtrl.dennisJumpHit=FALSE;
		//DB ("setting states %d\n",aHeld);
	}
*/
// call ball spell
/*	if(cHeld && cheat_call_ball && (GloveCtrl.action == HAND_IDLE || GloveCtrl.action == HAND_WALK))
	{
		VECTOR pos;
		pos = glovePos;
		pos.vy -= 30<<12;
		ballPlaceAt(&pos);
	}
*/



/*	if ( (zHeld && bHeld) && GloveCtrl.action==HAND_BALLWALK && (GloveCtrl.inWaterFlag!=INWATER && GloveCtrl.inWaterFlag!=BELOWWATER))
	{
		//AddToQueue(&Glover,HANDANIM_THROWAIM,YES,NO,-2048);
		AddToQueue(&Glover,HANDANIM_GRABBALL,NO,NO,8192);
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_JOINED;
		pGlovePSA->world.rotate.vx=0;
		cReleased=FALSE;
		GloveCtrl.move.vx=glovePos.vx;
		GloveCtrl.move.vy=glovePos.vy;
		GloveCtrl.move.vz=glovePos.vz;
		GloveCtrl.actionTime=0;
		GloveCtrl.handOnBall=0;
		pGlovePSA->world.rotate.vz=0;
		InputState.zStateHoldTime=TRUE;
		InputState.bStateHoldTime=TRUE;
		zHeld=0;
		bHeld=0;
	}
*/


	if ( (zHeld && bHeld) && GloveCtrl.action==HAND_JOINED)
	{
		pGlovePSA->world.rotate.vz=0;
		AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048);
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_BALLWALK;
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		//GloveCtrl.disableTimer=4;
		GloveCtrl.ballWithHand=TRUE;

		CamVars.oldTargetmodel=CamVars.targetmodel;
		CamVars.targetChangeTime=0;
		CamVars.targetChangeFlag=TRUE;

		CamVars.targetmodel=pBallPSA;
		GloveCtrl.currentAnim=HANDANIM_IDLE;
		GloveCtrl.handOnBall=TRUE;
		InputState.zStateHoldTime=TRUE;
		InputState.bStateHoldTime=TRUE;
		zHeld=0;
		bHeld=0;
	}

	if (GloveCtrl.disableTimer) GloveCtrl.disableTimer--;
	if (GloveCtrl.action!=HAND_IDLE && GloveCtrl.action!=HAND_JOINED) GloveCtrl.idleTimer=0;

	if ( (GloveCtrl.action==HAND_IDLE) && (/*padIn || */upDown || leftRight) && (GloveCtrl.idleAction) ) 
	{
		switch (GloveCtrl.idleAction)
//		switch (Glover.currentAnimation)
		{
			case HANDANIM_BORED:
				AddToQueue(&Glover,HANDANIM_GETUP,NO,NO,4096);
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				GloveCtrl.preDelay=10;
				GloveCtrl.idleAction=NULL;
				break;

			case HANDANIM_STRETCH:
				AddToQueue(&Glover,HANDANIM_STRETCH2IDLE,NO,NO,4096);
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				GloveCtrl.preDelay=10;
				GloveCtrl.idleAction=NULL;
				break;

			case HANDANIM_WAVE:
				AddToQueue(&Glover,HANDANIM_IDLE2WAVE,NO,NO,-4096);
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				GloveCtrl.preDelay=10;
				GloveCtrl.idleAction=NULL;
				break;
		}
	}

/*	if ( (GloveCtrl.action==HAND_IDLE) && zHeld && !(upDown || leftRight) && !(GloveCtrl.idleAction) )
	{
		GloveCtrl.idleAction=HANDANIM_WAVE;
		AddToQueue(&Glover,HANDANIM_IDLE2WAVE,NO,NO,4096);
		AddToQueue(&Glover,HANDANIM_WAVE,NO,YES,4096);
		AddToQueue(&Glover,HANDANIM_WAVE,NO,YES,4096);
		AddToQueue(&Glover,HANDANIM_IDLE2WAVE,NO,YES,-4096);
		AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,4096);

		GloveCtrl.idleTimer=0;
	}
*/
	if ( CatchBallAllowed() && ActionAllowed(GloveCtrl.action,HAND_CATCH) )
	{
		GloveCtrl.lastAction=GloveCtrl.action;

		GloveCtrl.forceSlide=FALSE;
		GloveCtrl.forceSlideDelay=0;
		GloveCtrl.active=TRUE;			// stop grab from slide lockup
		GloveBehaviour.accel=4096*8;
		//printf ("stopping slide\n");

		GloveCtrl.action=HAND_CATCH;
		AddToQueue(&Glover,HANDANIM_THROWAIM,NO,NO,-1);
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		GloveCtrl.ballWithHand=FALSE;	// was "==" tsk!
		GloveCtrl.actionTime=0;
		GloveCtrl.positionHold=TRUE;
	}


	//if (padIn&PAD_TRIANGLE)
	if (cHeld)
	{
		if(handpower_timer
			&& ActionAllowed(GloveCtrl.action,HAND_NMESPELL)
			&& (handpower_type == SPELL_FROGGY || handpower_type == SPELL_DEATH)
			&& !(padIn&PAD_CIRCLE)	// "find ball key overrides NME spell to BALL spell"
		)
		{
			AddToQueue(&Glover,HANDANIM_NMESPELL,NO,NO,4096);
			AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
			GloveCtrl.lastAction=GloveCtrl.action;
			GloveCtrl.action=HAND_NMESPELL;
			GloveCtrl.disableTimer=44;
			GloveCtrl.speed=0;
			GloveCtrl.targetSpeed=0;
			GloveCtrl.walkType=NULL;
			gloveVel.vx=0;
			gloveVel.vz=0;
			pGlovePSA->world.rotate.vx=0;
			pGlovePSA->world.rotate.vz=0;
			sfxPlay3D(globalFX,SFX_HAND2_SPELL1 + (RANDOM256() & 3),&glovePos);
		}
	}
	if (eHeld)
	{
		if( (ActionAllowed(GloveCtrl.action,HAND_CASTSPELL) || GloveCtrl.action==HAND_BALLWALK) && BallCtrl.enabled && BallChange.changeOn!=SPELLCHANGE && !BallCtrl.cancerFlag)
		{
			//AddToQueue(&Glover,HANDANIM_BALLSPELL,NO,NO,2048);
			AddToQueue(&Glover,HANDANIM_BALLSPELL,NO,NO,4096);
			AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
			GloveCtrl.lastAction=GloveCtrl.action;
			//GloveCtrl.action=HAND_CASTSPELL;
			pGlovePSA->world.rotate.vx=0;
			pGlovePSA->world.rotate.vz=0;
			GloveCtrl.disableTimer=22;
			GloveCtrl.speed=0;
			GloveCtrl.targetSpeed=0;
			GloveCtrl.walkType=NULL;
			sfxPlay3D(globalFX,SFX_HAND2_SPELL1 + (RANDOM256() & 3),&glovePos);
			if (GloveCtrl.action==HAND_BALLWALK)
			{
				GloveCtrl.spellCastOnBall=TRUE;
				GloveCtrl.spellCastTimer=28;
				//GloveCtrl.disableTimer=28;
				//printf ("cast spell on ball\n");
			}
			else
			{
				GloveCtrl.spellCastOnBall=FALSE;
				//printf ("cast spell not on ball \n");
			}
			GloveCtrl.action=HAND_CASTSPELL;
		}
	}

	//if (padIn&PAD_TRIANGLE && GloveCtrl.action==HAND_JOINED && (GloveCtrl.onGround==TRUE || BallCtrl.ballOnGround==TRUE))
	if (eHeld && GloveCtrl.action==HAND_JOINED && (/*GloveCtrl.onGround==TRUE || */BallCtrl.ballOnGround==TRUE) /*&& !BallCtrl.snowAddition*/ && !BallCtrl.cancerFlag && !GloveCtrl.ballSpellBodge)
	{
		//printf ("spell start\n");
		//if (GloveCtrl.onGround) printf ("glove on ground\n");
		//if (BallCtrl.ballOnGround) printf ("ball on ground\n");

		AddToQueue(&Glover,HANDANIM_ROLL2SPIN,NO,NO,11468);
		AddToQueue(&Glover,HANDANIM_SPIN,NO,YES,1152);
		AddToQueue(&Glover,HANDANIM_SPIN2ROLL,NO,YES,4096);

		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_CASTSPELL;
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		GloveCtrl.actionTime=0;
		GloveCtrl.spellActionTime=0;
		//GloveCtrl.spellCast=TRUE;
		GloveCtrl.speed=0;
		GloveCtrl.targetSpeed=0;
		GloveCtrl.walkType=NULL;
		sfxPlay3D(globalFX,SFX_HAND2_SPELL1 + (RANDOM256() & 3),&glovePos);
		GloveCtrl.spellCastOnBall=FALSE;
	}

	if ( (leftRight || upDown) && GloveCtrl.action==HAND_CASTSPELL && GloveCtrl.lastAction==HAND_JOINED && GloveCtrl.actionTime>=22)
	{
		//printf ("spell abort\n");
		GloveCtrl.action=HAND_JOINED;
		AddToQueue(&Glover,HANDANIM_SPIN2ROLL,NO,NO,4096);
		AddToQueue(&Glover,HANDANIM_WHACKAIM,NO,YES,0);
		GloveCtrl.walkType=NULL;
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		GloveCtrl.onGround=FALSE;
		BallCtrl.ballOnGround=FALSE;
		//printf ("setting ball and glove off ground\n");
		GloveCtrl.disableTimer=3;
	}

	//if (padIn&PAD_TRIANGLE && GloveCtrl.action==HAND_CASTSPELL && GloveCtrl.lastAction==HAND_JOINED && GloveCtrl.actionTime>=22 && GloveCtrl.actionTime<=41)
	if (eHeld && GloveCtrl.action==HAND_CASTSPELL && GloveCtrl.lastAction==HAND_JOINED && GloveCtrl.actionTime>=22 && GloveCtrl.actionTime<=41 && !GloveCtrl.ballSpellBodge)
	{
// repeat action on spells
		sfxPlay3D(globalFX,SFX_HAND2_SPELL1 + (RANDOM256() & 3),&glovePos);

		AddToQueue(&Glover,HANDANIM_SPIN,NO,NO,1152);
		AddToQueue(&Glover,HANDANIM_SPIN2ROLL,NO,YES,4096);

		GloveCtrl.disableTimer=8;
		GloveCtrl.actionTime=9;
		GloveCtrl.speed=0;
		GloveCtrl.targetSpeed=0;
		GloveCtrl.walkType=TRUE;
	}

/*	if ( zReleased && ActionAllowed(GloveCtrl.action,HAND_CARTWHEEL) && !GloveCtrl.stopXZ)
	{
		AddToQueue(&Glover,HANDANIM_CARTWHEEL,NO,NO,4096);
		AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_CARTWHEEL;
		GloveCtrl.disableTimer=22;	// Disable controls for 22 ticks
		GloveCtrl.actionTime=0;
		GloveCtrl.speed=0;
		GloveCtrl.targetSpeed=0;
		SFXPlay3D(globalFX,SFX_HAND2_RUNJUMP1 + random(4),64,&glovePos,42, 200);
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
	}
*/
/*	if ( zHeld>=CRAWLSTARTDELAY && !GloveCtrl.stopXZ && ActionAllowed(GloveCtrl.action,HAND_DUCK) && (GloveCtrl.action!=HAND_DUCK && GloveCtrl.action!=HAND_CRAWL) && GloveCtrl.onGround)
	{
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_DUCK;
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		GloveCtrl.speed=0;
		GloveCtrl.targetSpeed=0;
		AddToQueue(&Glover,HANDANIM_DUCK,NO,NO,2048);
		GloveBehaviour.radius=GLOVECRAWLRADIUS;
		//GloveCtrl.disableTimer=8; // 
	}
*/
/*
	if ( zHeld>=CRAWLSTARTDELAY+18 && ActionAllowed(GloveCtrl.action,HAND_CRAWL) && GloveCtrl.action!=HAND_CRAWL)//&& GloveCtrl.action!=HAND_DUCK)
	{
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_CRAWL;
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		GloveCtrl.speed=0;
		GloveCtrl.targetSpeed=0;
		AddToQueue(&Glover,HANDANIM_CRAWL,YES,NO,0);
	}
*/
/*	if ( zHeld==0 && (GloveCtrl.action==HAND_CRAWL || GloveCtrl.action==HAND_DUCK) )
	{
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_IDLE;
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		GloveCtrl.walkType=NULL;
		AddToQueue(&Glover,HANDANIM_DUCK,NO,NO,-2048);
		AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
		GloveCtrl.disableTimer=12; // 
		GloveBehaviour.radius=GLOVENORMALRADIUS;
	}
*/
	if ( cHeld && (GloveCtrl.ballWithHand) && (ActionAllowed(GloveCtrl.action,HAND_PREWHACK) || ActionAllowed(GloveCtrl.action,HAND_AIRBOURNEWHACK)) )
	{
/*		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_PREWHACK;
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;

		GloveCtrl.actionTime=0;
		//InputState.whackWhenAble=TRUE;
	   	InputState.cStateChange=TRUE;

		//oldBallPos.vx=ballPos.vx;
		//oldBallPos.vy=ballPos.vy;
		//oldBallPos.vz=ballPos.vz;
		GloveCtrl.whackAir=FALSE;
		if (GloveCtrl.idleAction)
		{
			GloveCtrl.idleAction=FALSE;
			AddToQueue(&Glover,HANDANIM_WHACKAIM,NO,YES,4096);
			AddToQueue(&Glover,HANDANIM_WHACKIDLE,YES,YES,4096);
		}
		else
		{
			AddToQueue(&Glover,HANDANIM_WHACKAIM,NO,NO,4096);
			AddToQueue(&Glover,HANDANIM_WHACKIDLE,YES,YES,4096);
		}
	}
	else if ( (cHeld || InputState.whackWhenAble) && (GloveCtrl.ballWithHand) && ActionAllowed(GloveCtrl.action,HAND_AIRBOURNEWHACK) )
	{
*/		InputState.whackWhenAble=TRUE;
		InputState.cStateChange=TRUE;
		GloveCtrl.actionTime=0;

		tempV.vx=ballPos.vx-glovePos.vx;
		tempV.vy=ballPos.vy-glovePos.vy;
		tempV.vz=ballPos.vz-glovePos.vz;
		GloveCtrl.whackAir=TRUE;
		temp=Magnitude(&tempV);
		temp-=temp/10;

		if (temp<(BallBehaviour[BallCtrl.type].radius+GloveCtrl.radius) )
		{
			oldBallPos.vx=ballPos.vx;
			oldBallPos.vy=ballPos.vy;
			oldBallPos.vz=ballPos.vz;

			InputState.whackWhenAble=FALSE;
			GloveCtrl.lastAction=GloveCtrl.action;
			GloveCtrl.action=HAND_PREWHACK;
			pGlovePSA->world.rotate.vx=0;
			pGlovePSA->world.rotate.vz=0;
			if (GloveCtrl.idleAction)
			{
				GloveCtrl.idleAction=FALSE;
				AddToQueue(&Glover,HANDANIM_WHACKAIM,NO,YES,4096);
				AddToQueue(&Glover,HANDANIM_WHACKIDLE,YES,YES,4096);
			}
			else
			{
				AddToQueue(&Glover,HANDANIM_WHACKAIM,NO,NO,4096);
				AddToQueue(&Glover,HANDANIM_WHACKIDLE,YES,YES,4096);
			}
		}
	}

	//GloveCtrl.jumpPressed=FALSE;
	//if ( bHeld && !GloveCtrl.stopXZ ) GloveCtrl.jumpPressed=TRUE;

	if ( bHeld && !GloveCtrl.stopXZ && (GloveCtrl.onGround || GloveCtrl.handOnBall || GloveCtrl.onTrampoline) && ActionAllowed(GloveCtrl.action,HAND_JUMP))
	{
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_JUMP;
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		gloveVel.vy+=JUMPHEIGHT;
		GloveCtrl.onGround=FALSE;

		GloveCtrl.onIceFlag=FALSE;

		if(!GloveCtrl.handOnBall)
			gloveColl.oldPos.vy-=gloveVel.vy;

		GloveCtrl.ballWithHand=FALSE;
		GloveCtrl.handOnBall=FALSE;

		CamVars.oldTargetmodel=CamVars.targetmodel;
		CamVars.targetChangeTime=0;
		CamVars.targetChangeFlag=TRUE;

		CamVars.targetmodel=pGlovePSA;
		GloveCtrl.walkType=NULL;
		AddToQueue(&Glover,HANDANIM_JUMP,NO,NO,4096);
		bHeld=2;

		GloveCtrl.ballCollision=TRUE;

		GloveCtrl.slideData.vx=0;
		GloveCtrl.slideData.vy=0;
		GloveCtrl.slideData.vz=0;
		gloveColl.physics->gravity=gravity;
		sfxPlay3D(globalFX,SFX_HAND2_JUMP1 + (RANDOM256() & 3),&glovePos);
	}

	if ( (bHeld==1) && (GloveCtrl.action==HAND_JUMP) && (GloveCtrl.lastAction!=HAND_JUMP) && GloveCtrl.lastAction!=HAND_LOCATE ) // super jump
	{
		GloveCtrl.lastAction=GloveCtrl.action;

		//if (gloveVel.vy<0) gloveVel.vy=0;
		gloveVel.vy=0;
		gloveVel.vy=DOUBLEJUMPHEIGHT;
		GloveCtrl.onGround=FALSE;

		AddToQueue(&Glover,HANDANIM_SUPERJUMP,NO,NO,6144);

		sfxPlay3D(globalFX,SFX_HAND2_RUNJUMP1 + random(4),&glovePos);
	}

	if ( ( (padIn&PAD_L2) && ( aHeld )) && ActionAllowed(GloveCtrl.action,HAND_LOB) )
	{
		//DB ("lob\n");
		gloveVel.vx=0;
		gloveVel.vy=0;
		gloveVel.vz=0;
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_LOB;
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		AddToQueue(&Glover,HANDANIM_LOB,NO,NO,4096);
		AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
		GloveCtrl.disableTimer=16;
		GloveCtrl.throwDelay=TRUE;

		CamVars.oldTargetmodel=CamVars.targetmodel;
		CamVars.targetChangeTime=0;
		CamVars.targetChangeFlag=TRUE;

		CamVars.targetmodel=pGlovePSA;
	}

	//if ( (zHeld) && ActionAllowed(GloveCtrl.action,HAND_SLAM) && (GloveCtrl.lastAction!=NULL || GloveCtrl.actionTime>20) )
	// Final control change
	if ( (cHeld) && ActionAllowed(GloveCtrl.action,HAND_SLAM) && (GloveCtrl.lastAction!=NULL || GloveCtrl.actionTime>20) )
	{
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_SLAM;
		GloveCtrl.onGround=FALSE;
		GloveCtrl.positionHold=FALSE;

		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		GloveCtrl.actionTime=0;
		GloveCtrl.disableTimer=999;
		AddToQueue(&Glover,HANDANIM_SLAM,NO,NO,2048);
		gloveVel.vy=0;	// kill glove vertical speed
		gloveVel.vx=0;
		gloveVel.vz=0;
		GloveCtrl.targetSpeed=0;
		GloveCtrl.speed=0;
	}

	//if (BallCtrl.inWind) DB ("b wind\n");
	//if (GloveCtrl.inWind) DB ("g wind\n");

	if (aHeld && (GloveCtrl.lastAction!=HAND_LOCATE || GloveCtrl.onGround==TRUE) && (GloveCtrl.action!=HAND_SNATCH && GloveCtrl.action!=HAND_JOINED && GloveCtrl.action!=
	HAND_BOUNCE && ActionAllowed(GloveCtrl.action,HAND_LOCATE) && !GloveCtrl.insideBubble))
	{
		tempV.vx=(glovePos.vx-ballPos.vx);
		tempV.vy=(glovePos.vy-ballPos.vy);
		tempV.vz=(glovePos.vz-ballPos.vz);
		temp=Magnitude(&tempV);

		//if (BallCtrl.inWind || GloveCtrl.inWind) temp=temp/3;
		
		if (temp < HAND_SNATCH_RANGE && GrabBallAllowed() && ActionAllowed(GloveCtrl.action,HAND_SNATCH) /*&& GloveCtrl.onGround*/ )
		{
			//DB ("grab from button pressed\n");
			aReleased=FALSE;
			// put grab ball stuff here

			GloveCtrl.forceSlide=FALSE;
			GloveCtrl.forceSlideDelay=0;
			GloveBehaviour.accel=4096*8;
			GloveCtrl.active=TRUE;			// stop grab from slide lockup

			GloveCtrl.lastAction=GloveCtrl.action;
			GloveCtrl.action=HAND_SNATCH;
			//GloveCtrl.flags=STOPGLOVEMOVE;
			GloveCtrl.speed=0;
			GloveCtrl.targetSpeed=0;
			pGlovePSA->world.rotate.vx=0;
			pGlovePSA->world.rotate.vz=0;
			AddToQueue(&Glover,HANDANIM_GRABBALL,NO,NO,6144);
			GloveCtrl.ballWithHand=TRUE;

			CamVars.oldTargetmodel=CamVars.targetmodel;
			CamVars.targetChangeTime=0;
			CamVars.targetChangeFlag=TRUE;

			CamVars.targetmodel=pBallPSA;
			GloveCtrl.disableTimer=12;			// disable controls for 18 ticks
			GloveCtrl.actionTime=0;
			GloveCtrl.onGround=FALSE;
			//return;
		}
		else if (GloveCtrl.action!=HAND_LOCATE && GloveCtrl.lastAction!=HAND_ROTOR)
		{
			aReleased=FALSE;
			//if (GloveCtrl.lastAction==HAND_JUMP || GloveCtrl.action==HAND_JUMP) GloveCtrl.stopXZ=TRUE;
			GloveCtrl.lastAction=GloveCtrl.action;
			GloveCtrl.action=HAND_LOCATE;
			pGlovePSA->world.rotate.vx=0;
			pGlovePSA->world.rotate.vz=0;
			GloveCtrl.speed=0;
			GloveCtrl.targetSpeed=0;
			gloveVel.vy=0;
			gloveVel.vx=0;
			gloveVel.vz=0;
			//GloveCtrl.flags=STOPGLOVEMOVE;
			AddToQueue(&Glover,HANDANIM_POINT,NO,NO,4096);
			AddToQueue(&Glover,HANDANIM_POINTCYCLE,YES,YES,4096);
			GloveCtrl.actionTime=0;
		}
	}

	//if ( BallCloseToHand() && (GloveCtrl.action==HAND_WALK || GloveCtrl.action==HAND_IDLE) && ( (BallCtrl.ballOnGround || BallCtrl.shallowWater) ) && (BallCtrl.type==BALL_MODE_BOWLING || BallCtrl.type==BALL_MODE_BEARING) )
	if ( BallCloseToHand() && !GloveCtrl.insideBubble && (GloveCtrl.action==HAND_WALK || GloveCtrl.action==HAND_IDLE) && (BallCtrl.ballOnGround || BallCtrl.shallowWater))
	{
		DB("grab from in range\n");
		aReleased=FALSE;
		// put grab ball stuff here
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_SNATCH;
		//GloveCtrl.flags=STOPGLOVEMOVE;
		GloveCtrl.speed=0;
		GloveCtrl.targetSpeed=0;
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		AddToQueue(&Glover,HANDANIM_GRABBALL,NO,NO,6144);
		GloveCtrl.ballWithHand=TRUE;

		CamVars.oldTargetmodel=CamVars.targetmodel;
		CamVars.targetChangeTime=0;
		CamVars.targetChangeFlag=TRUE;

		CamVars.targetmodel=pBallPSA;
		GloveCtrl.disableTimer=12;			// disable controls for 18 ticks
		GloveCtrl.actionTime=0;
		GloveCtrl.onGround=FALSE;
		//return;
	}

	if ( BallCloseToHand() && GloveCtrl.inWind && GloveCtrl.action!=HAND_SNATCH && GloveCtrl.action!=HAND_JOINED && GloveCtrl.action!=HAND_BOUNCE && GloveCtrl.action!=HAND_BALLWALK && GloveCtrl.action!=HAND_ROTOR && GloveCtrl.action!=HAND_CASTSPELL)
	{
		//DB ("grab from in wind\n");
		aReleased=FALSE;
		// put grab ball stuff here
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_SNATCH;
		//GloveCtrl.flags=STOPGLOVEMOVE;
		GloveCtrl.speed=0;
		GloveCtrl.targetSpeed=0;
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		AddToQueue(&Glover,HANDANIM_GRABBALL,NO,NO,6144);
		GloveCtrl.ballWithHand=TRUE;

		CamVars.oldTargetmodel=CamVars.targetmodel;
		CamVars.targetChangeTime=0;
		CamVars.targetChangeFlag=TRUE;

		CamVars.targetmodel=pBallPSA;
		GloveCtrl.disableTimer=12;			// disable controls for 18 ticks
		GloveCtrl.actionTime=0;
	}



/*
	if ( BallCloseToHand() && (GloveCtrl.action==HAND_WALK || GloveCtrl.action==HAND_IDLE || GloveCtrl.action==HAND_JUMP) && BallCtrl.inWaterFlag!=NOWHERENEARWATER)
	{
		if (BallCtrl.type!=BALL_MODE_BOWLING && BallCtrl.type!=BALL_MODE_BEARING )
		{
			AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048);
			GloveCtrl.lastAction=GloveCtrl.action;
			GloveCtrl.action=HAND_BALLWALK;
			GloveCtrl.disableTimer=4;
			GloveCtrl.ballWithHand=TRUE;
			CamVars.targetmodel=pBallPSA;
			GloveCtrl.currentAnim=HANDANIM_IDLE;
			GloveCtrl.handOnBall=TRUE;
		}
	}
*/
								
	//if ( !aHeld && GloveCtrl.action==HAND_LOCATE )
	if ( !aHeld && GloveCtrl.action==HAND_LOCATE && GloveCtrl.actionTime>=20)
	{
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_IDLE;
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vz=0;
		if (!GloveCtrl.onGround)
		{
			GloveCtrl.action=HAND_JUMP;
			//GloveCtrl.lastAction=HAND_JUMP;
			GloveCtrl.lastAction=HAND_LOCATE;
		}
		GloveCtrl.walkType=NULL;
		GloveCtrl.flags=GLOVEMOVE;
		AddToQueue(&Glover,HANDANIM_POINT2IDLE,NO,NO,4096);
		AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
	}

	if ((GloveCtrl.action==HAND_JOINED || GloveCtrl.action==HAND_BOUNCE) )// && BallCtrl.ballCloseToHand==TRUE) // bounce ball
	{
// For whatever reason, this used the "ballclosetohand" variable rather than the function
// since it was the only bit of source that did so, I've removed said variable, & moved the calculation here
		tempV.vx=ballPos.vx-glovePos.vx;
		tempV.vy=ballPos.vy-glovePos.vy;
		tempV.vz=ballPos.vz-glovePos.vz;

		temp=Magnitude(&tempV);
		temp-=temp/10;

		//InputState.throwWhenAble=TRUE;
		//InputState.aStateChange=TRUE;
		//GloveCtrl.actionTime=0;
		if (aHeld) InputState.throwWhenAble=TRUE;
		if (temp<(BallBehaviour[BallCtrl.type].radius+GloveCtrl.radius) )
		{

			//if (aReleased)
			if (InputState.throwWhenAble)
			{
				InputState.aStateChange=TRUE;
				GloveCtrl.actionTime=0;
				InputState.throwWhenAble=0;
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_THROWAIM;
				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;
				GloveBehaviour.gravity=gravity;
				oldGlovePos.vx=glovePos.vx;
				oldGlovePos.vy=glovePos.vy;
				oldGlovePos.vz=glovePos.vz;
				oldBallPos.vx=ballPos.vx;
				oldBallPos.vy=ballPos.vy;
				oldBallPos.vz=ballPos.vz;

				aReleased=FALSE;
			}
			//else if (aReleased)
			else if (bHeld)
			{
				aReleased=FALSE;
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_BOUNCE;
				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;
				GloveCtrl.hitBall=TRUE;
				if (GloveCtrl.lastAction!=HAND_BOUNCE)
				{
					AddToQueue(&Glover,HANDANIM_ROLL2BOUNCE,NO,NO,2048);
					AddToQueue(&Glover,HANDANIM_BOUNCE,NO,YES,0);
				}
			}
		}
	}
// Cancle manovers
// ------ --------

	if (zReleased)
	{
		switch(GloveCtrl.action)
		{
			case HAND_JOINED:
			case HAND_BOUNCE:
			//case HAND_BALLWALK:
				GloveCtrl.onIce=FALSE;
				GloveCtrl.slideData.vx=0;
				GloveCtrl.slideData.vy=0;
				GloveCtrl.slideData.vz=0;
				gloveColl.physics->gravity=gravity;
				if (GloveCtrl.disableTimer) break;
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_RELEASE;

				sfxPlay3D(globalFX,SFX_HAND2_JUMP1 + (RANDOM256() & 3),&glovePos);

				GloveCtrl.walkType=NULL;
				AddToQueue(&Glover,HANDANIM_RELEASE,NO,NO,2730);
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;

				glovePos.vy-=4096*10;

				gloveVel.vx=0;
				gloveVel.vy=0;
				gloveVel.vz=0;
				GloveCtrl.disableTimer=9;
				GloveCtrl.handOnBall=FALSE;
				zFlipFlop=TRUE;
				GloveCtrl.positionHold=FALSE;
				GloveCtrl.onGround=FALSE;
				break;

			case HAND_HOPPING:
				GloveCtrl.onIce=FALSE;
				GloveCtrl.slideData.vx=0;
				GloveCtrl.slideData.vy=0;
				GloveCtrl.slideData.vz=0;

				GloveCtrl.speed=0;
				GloveCtrl.targetSpeed=0;

				nmeDismountDenis(GloveCtrl.mount);

				if (GloveCtrl.disableTimer) break;
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_RELEASE;
				GloveCtrl.walkType=NULL;

				sfxPlay3D(globalFX,SFX_HAND2_JUMP1 + (RANDOM256() & 3),&glovePos);

				//AddToQueue(&Glover,HANDANIM_RELEASE,NO,NO,2048);
				AddToQueue(&Glover,HANDANIM_JUMP,NO,NO,4096);
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				GloveCtrl.disableTimer=6;
				GloveCtrl.handOnBall=FALSE;
				zFlipFlop=TRUE;
				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;

				break;

			case HAND_ROTOR:
				GloveCtrl.onIce=FALSE;
				GloveCtrl.slideData.vx=0;
				GloveCtrl.slideData.vy=0;
				GloveCtrl.slideData.vz=0;

				if (GloveCtrl.lastAction!=HAND_JOINED || BallCtrl.ballOnGround) break;
				GloveCtrl.lastAction=HAND_IDLE;
				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;
				CamVars.targetmodel=pGlovePSA;


				BallCtrl.anywhack = POWERWHACK_START;
				if(BallCtrl.type == BALL_MODE_BOWLING || cheat_any_ball_powerwhacks || 
				(BallCtrl.preSnowType == BALL_MODE_BOWLING && BallCtrl.snowAddition ) )
					BallCtrl.powerwhack = POWERWHACK_START;

				break;


/*			case HAND_SWISH:
//				GloveCtrl.mount->doing=51;//SWISH_DISMOUNT;
//				GloveCtrl.mount->ticker=20;
				GloveCtrl.speed=0;
				GloveCtrl.targetSpeed=0;

				nmeDismountSwish(GloveCtrl.mount);

//				glovePos.vy -= 50 * 4096;
				gloveVel.vx = 0;
				gloveVel.vy = 0;
				gloveVel.vz = 0;

				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;
				CamVars.targetmodel=pGlovePSA;
				if (GloveCtrl.disableTimer) break;
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_RELEASE;
				GloveCtrl.walkType=NULL;
				//AddToQueue(&Glover,HANDANIM_RELEASE,NO,NO,2048);
				AddToQueue(&Glover,HANDANIM_JUMP,NO,NO,4096);
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				GloveCtrl.disableTimer=6;
				GloveCtrl.handOnBall=FALSE;
				zFlipFlop=TRUE;
				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;

				break;
*/

				//nmeDismountDenis(GloveCtrl.mount);
			case HAND_BALLWALK:
				if (GloveCtrl.disableTimer) break;

				GloveCtrl.onIce=FALSE;
				GloveCtrl.slideData.vx=0;
				GloveCtrl.slideData.vy=0;
				GloveCtrl.slideData.vz=0;

				//if (GloveCtrl.inWaterFlag==ABOVEWATER)
				if (BallCtrl.inWaterFlag==INWATER && !BallCtrl.shallowWater)
				{
					GloveCtrl.lastAction=GloveCtrl.action;

					sfxPlay3D(globalFX,SFX_HAND2_JUMP1 + (RANDOM256() & 3),&glovePos);

					GloveCtrl.action=HAND_RELEASE;
					GloveCtrl.walkType=NULL;
					AddToQueue(&Glover,HANDANIM_RELEASE,NO,NO,2730);
					AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
					pGlovePSA->world.rotate.vx=0;
					pGlovePSA->world.rotate.vz=0;

					glovePos.vy-=4096*10;

					gloveVel.vx=0;
					gloveVel.vy=0;
					gloveVel.vz=0;
					GloveCtrl.disableTimer=9;
					GloveCtrl.handOnBall=FALSE;
					zFlipFlop=TRUE;
				}
				else
				{
					//AddToQueue(&Glover,HANDANIM_GRABBALL,NO,NO,8192);
					AddToQueue(&Glover,HANDANIM_GRABBALL,NO,NO,12288);
					GloveCtrl.lastAction=GloveCtrl.action;
					GloveCtrl.action=HAND_JOINED;
					pGlovePSA->world.rotate.vx=0;
					cReleased=FALSE;
					GloveCtrl.move.vx=glovePos.vx;
					GloveCtrl.move.vy=glovePos.vy;
					GloveCtrl.move.vz=glovePos.vz;
					GloveCtrl.actionTime=0;
					GloveCtrl.handOnBall=0;
					pGlovePSA->world.rotate.vz=0;
					InputState.zStateHoldTime=TRUE;
					InputState.bStateHoldTime=TRUE;
					//GloveCtrl.disableTimer=3;
					zHeld=0;
					bHeld=0;

					CamVars.oldTargetmodel=CamVars.targetmodel;
					CamVars.targetChangeTime=0;
					CamVars.targetChangeFlag=TRUE;
					CamVars.targetmodel=pBallPSA;
					GloveCtrl.speed=0;
				}
				gloveColl.physics->gravity=gravity;
				break;

/*				if (GloveCtrl.disableTimer) break;
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_RELEASE;
				GloveCtrl.walkType=NULL;
				//AddToQueue(&Glover,HANDANIM_RELEASE,NO,NO,2048);
				AddToQueue(&Glover,HANDANIM_JUMP,NO,NO,2048);
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				GloveCtrl.disableTimer=12;
				GloveCtrl.handOnBall=FALSE;
				zFlipFlop=TRUE;
				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;
				break;
*/

			case HAND_THROWAIM:
				//keyMask=PAD_CIRCLE;
				if (GloveCtrl.disableTimer) break;
				InputState.aStateHoldTime=30;
				InputState.aStateChange=FALSE;
				InputState.throwWhenAble=FALSE;
				//keyMask=ABUTTON;
				zFlipFlop=TRUE;
				//keyMask=BBUTTON;
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_JOINED;
				//AddToQueue(&Glover,HANDANIM_BOUNCE2ROLL,NO,NO,2048);
				AddToQueue(&Glover,HANDANIM_THROWAIM,YES,NO,-4096);
				GloveBehaviour.gravity=gravity;

				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;

				CamVars.targetmodel=pBallPSA;
				//GloveCtrl.disableTimer=10;
				GloveCtrl.throwDelay=FALSE;
				GloveCtrl.flags=GLOVEMOVE;
				BallCtrl.ballStopMove=FALSE;
				aHeld=0;
				aReleased=FALSE;
				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;

				//GloveCtrl.disableTimer=12;
				break;

			case HAND_PREWHACK:
				if (GloveCtrl.disableTimer) break;
				InputState.cStateHoldTime=30;
				InputState.cStateChange=FALSE;
				InputState.whackWhenAble=FALSE;
				//GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.lastAction=NULL;
				GloveCtrl.action=HAND_JOINED;
				AddToQueue(&Glover,HANDANIM_WHACKAIM,NO,NO,-4096);
				AddToQueue(&Glover,HANDANIM_ROLLBLINK,YES,YES,0);
				GloveBehaviour.gravity=gravity;

				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;

				CamVars.targetmodel=pBallPSA;
				GloveCtrl.throwDelay=FALSE;
				GloveCtrl.flags=GLOVEMOVE;
				BallCtrl.ballStopMove=FALSE;
				aHeld=0;
				aReleased=FALSE;
				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;
				GloveCtrl.stopXZ=FALSE;
				break;
			case HAND_IDLE:
				if ( (GloveCtrl.action==HAND_IDLE) && !(upDown || leftRight) && !(GloveCtrl.idleAction) )
				{
					GloveCtrl.idleAction=HANDANIM_WAVE;
					AddToQueue(&Glover,HANDANIM_IDLE2WAVE,NO,NO,4096);
					AddToQueue(&Glover,HANDANIM_WAVE,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_WAVE,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_IDLE2WAVE,NO,YES,-4096);
					AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,4096);
					GloveCtrl.idleTimer=0;
				}
				break;

		}
	}
	if (keyMask&ABUTTON) aHeld=1;
	if (keyMask&BBUTTON) bHeld=1;
}




/*************************************************************************************************/
/*************************************************************************************************/
/*************************************************************************************************/
void	CheckForFistHits(void)
{
//	int x,y,z;
	DYNCOLLBOX *ptr;
	int i;

//	x=glovePos.vx;
//	y=glovePos.vy;
//	z=glovePos.vz;

	{
		VECTOR t;
		t = glovePos;
		t.vy += 10 * 4096;	// stinky bodge. want the floor, not the glove
		effectsStartBlastRing(&t, 5*4096, 80 * 4096,8);
	}

	if (gameInfo.keyRecordFlag!=PLAYBACK) SHOCK_FISTSLAM;
	sfxPlay3D(globalFX, SFX_HAND_FISTSLAM, &glovePos);

/*
	nme = &enemies[0];
	for (i = 0; i < numberofenemies; i++,nme++)
	{
		// First do quick check
		if (x > (nme->pos.vx-BLASTRADIUS) && x < (nme->pos.vx+BLASTRADIUS) )
		{
			if (y > (nme->pos.vy-BLASTRADIUS) && y < (nme->pos.vy+BLASTRADIUS) )
			{// Close now do slow check
				check.vx=x-nme->pos.vx;
				check.vy=y-nme->pos.vy;
				check.vz=z-nme->pos.vz;
				mag=Magnitude(&check);
				if (mag < BLASTRADIUS)
				{	// we have a hit
					//nme->flags |= NMEFLAG_ACTIVE;
					nme->flags&=~NMEFLAG_ACTIVE;
					New_StarRingDebris(&nme->pos, 6);
				}
			}
		}
	}
*/
	// also need to put destructable objects in this routine as well

	// and moving switches & platforms etc.
	for(ptr = dyncollList.head.next; ptr != &dyncollList.head; ptr = ptr->next)
	{
		int wait=ptr->pPlatDef->points[ptr->move.point].wait;

		if(gloveColl.nHitPlats)
		{
// Need to scan down the whole lot, specifically for the child-platformmy one on PR2, which has another non-fistslammy
// platform collision box underneath it.
			for(i = 0; i < gloveColl.nHitPlats;i++)
			{
				if(ptr==gloveColl.hitPlats[i].pPlatform)
				{
					if(wait==WAITFORHANDSLAM)
					{
						platformStartMove(ptr, 4, 0);
					}

					if((ptr->pPlatDef->head.flags)&PLATFLAG_DESTRUCTIBLE) 
					{
						if (gameInfo.keyRecordFlag!=PLAYBACK) SHOCK_SMASHPLATFORM;
						platformSmash(ptr);
					}
				}
			}
		}
	}
}


/*************************************************************************************************/
/*************************************************************************************************/
/*************************************************************************************************/
NEWOBJECT	*gloveShinR;
NEWOBJECT	*gloveShinL;
NEWOBJECT	*gloveArmR;
NEWOBJECT	*gloveArmL;
void	GloveDamage(void)
{
VECTOR		tempVec;

//	gloveShinR=pGlovePSA->world.child->child->child;
//	gloveShinL=pGlovePSA->world.child->child->next->child;
//	gloveArmR=pGlovePSA->world.child->child->next->next->child->next->next->next->next->child;

	if (GloveCtrl.cameoDisableDamage && BallCtrl.type!=BALL_MODE_CRYSTAL)
	{
		//DB("stopping glove damage\n");
		GloveCtrl.cameoDisableDamage--;
		GloveCtrl.deathType=0;
		GloveCtrl.deathTypeBall=0;
		GloveCtrl.hurtFlag=0;
		GloveCtrl.hurtFlagBall=0;
		return;
	}



	if (GloveCtrl.handHurtTime)
	{
		if (GloveCtrl.deathTypeBall!=DEADFROMBALLBURST && GloveCtrl.deathType!=DEADFROMFALL && GloveCtrl.deathType!=DEADFROMPAIN)
		{
			if (GloveCtrl.flash) GloveCtrl.flash=FALSE;
			else GloveCtrl.flash=TRUE;
		}

		GloveCtrl.handHurtTime--;
		if (!GloveCtrl.handHurtTime)
		{
			GloveCtrl.hurtFlag=0;
			GloveCtrl.hurtFlagBall=0;
			GloveCtrl.deathType=0;
			GloveCtrl.deathTypeBall=0;
		}
		return;
	}
	else GloveCtrl.flash=FALSE;

	if (GloveCtrl.hurtFlag==0 && GloveCtrl.hurtFlagBall==0) return;

	gloveColl.physics->gravity=gravity;

	GloveCtrl.lastAction=GloveCtrl.action;

	pGlovePSA->world.rotate.vx=0;
	pGlovePSA->world.rotate.vy=0;
	pGlovePSA->world.rotate.vz=0;

	if (GloveCtrl.deathTypeBall==DEADFROMBALLBURST)
	{
		if (GloveCtrl.hurtFlagBall!=0)
		{
			gloveColl.physics->gravity=gravity;
			GloveBehaviour.accel=8*4096;
			DB ("ball has popped\n");
			GloveCtrl.hurtFlagBall=0;
			if (GloveCtrl.deathType==0)
			{
				AddToQueue(&Glover,HANDANIM_POINT,NO,NO,4096);
				AddToQueue(&Glover,HANDANIM_POINTCYCLE,YES,YES,4096);
		
				if (GloveCtrl.action!=HAND_HURT)
				{
					GloveCtrl.action=HAND_HURT;
					GloveCtrl.dieCount=50;
					gloveVel.vx=0;
					//gloveVel.vy=0;
					gloveVel.vz=0;
					GloveCtrl.speed=0;
					GloveCtrl.targetSpeed=0;

					CamVars.oldTargetmodel=CamVars.targetmodel;
					CamVars.targetChangeTime=0;
					CamVars.targetChangeFlag=TRUE;
					CamVars.targetmodel=pGlovePSA;
				}
			}
		}
	}

	switch(GloveCtrl.deathType)
	{
		case HURTFALL:
			if (GloveCtrl.hurtFlag==0) return;
			gloveColl.physics->gravity=gravity;
			GloveBehaviour.accel=8*4096;
			DB("hurt fall\n");
			AddToQueue(&Glover,HANDANIM_HURT,NO,NO,4096);
			AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
			GloveCtrl.dieCount=20;
			GloveCtrl.disableTimer=20;
			GloveCtrl.handHurtTime=90;

			handHurtGlove(DEADFROMFALL);
			if (GloveCtrl.health!=0)
			{
				GloveCtrl.onGround=FALSE;
				tempVec.vz=HURTJUMPSPEED;
				tempVec.vx=0;
				RotateVector2D(&tempVec, &tempVec,GloveCtrl.direction );
				gloveVel.vx=tempVec.vx;
				gloveVel.vy=HURTJUMPSPEED;
				gloveVel.vz=tempVec.vz;
			}
			
			GloveCtrl.hurtFlag=0;
			GloveCtrl.action=HAND_HURT;
			GloveCtrl.ballCollision=FALSE;

			GloveCtrl.speed=0;
			GloveCtrl.targetSpeed=0;
			GloveCtrl.oldSpeed=0;
			switch(GloveCtrl.health)
			{
				case 3:
					if (GloveCtrl.maxHealth<4) break;
					ChangeBall(gloveArmL,GloveTex[1]);
					break;
				case 2:	// 1st hit
					ChangeBall(gloveShinR,GloveTex[1]);
					break;
				case 1:
					ChangeBall(gloveArmR,GloveTex[1]);
					break;
				case 0:
					ChangeBall(gloveShinL,GloveTex[1]);
					break;
			}
			break;

		case HURTPAIN:
			DB("fail \n");
			ASSERT(0);
/*		case HURTPAIN:
			if (GloveCtrl.hurtFlag==0) return;
			GloveBehaviour.accel=4*4096;
			gloveColl.physics->gravity=gravity;
			AddToQueue(&Glover,HANDANIM_HURT,NO,NO,4096);
			AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
			GloveCtrl.disableTimer=20;
			GloveCtrl.dieCount=20;
			DB ("hurt by object\n");
			ASSERT(0);

			handHurtGlove(DEADFROMPAIN);
			if (GloveCtrl.health!=0)
			{
				if (GloveCtrl.lastAction!=HAND_ROTOR)
				{
					GloveCtrl.onGround=FALSE;
					tempVec.vz=HURTJUMPSPEED;
					tempVec.vx=0;
					RotateVector2D(&tempVec, &tempVec,GloveCtrl.direction );
					gloveVel.vx=tempVec.vx;
					gloveVel.vy=HURTJUMPSPEED;
					gloveVel.vz=tempVec.vz;
				}
				else
				{
					//GloveCtrl.action=HAND_IDLE;
					gloveVel.vx=0;
					gloveVel.vy=0;
					gloveVel.vz=0;
				}
			}
			GloveCtrl.hurtFlag=0;
			GloveCtrl.action=HAND_HURT;
			GloveCtrl.ballCollision=FALSE;
			GloveCtrl.handHurtTime=90;

			break;
*/
		case DEADFROMFALL:
			if (GloveCtrl.hurtFlag==0) return;
			AddToQueue(&Glover,HANDANIM_FALL,YES,NO,4096);
			GloveBehaviour.accel=8*4096;
			gloveColl.physics->gravity=gravity;
			DB("dead from fall\n");
			GloveCtrl.action=HAND_FALLING;
			GloveCtrl.hurtFlag=0;

			GloveCtrl.ballCollision=FALSE;

			GloveCtrl.health=0;
			GloveCtrl.healthChange=TRUE;
			GloveCtrl.dieCount=110;
			GloveCtrl.disableTimer=20;

			gloveVel.vx=0;
			gloveVel.vz=0;

			GloveCtrl.speed=0;
			GloveCtrl.targetSpeed=0;


			break;

		case DEADFROMPAIN:
			if (GloveCtrl.hurtFlag==0) return;
			AddToQueue(&Glover,HANDANIM_CARDIACDEATH,NO,NO,2048);
			AddToQueue(&Glover,HANDANIM_CARDIACDEATH,NO,YES,-1);
			GloveBehaviour.accel=8*4096;
			GloveCtrl.health=0;
			GloveCtrl.healthChange=TRUE;
			GloveCtrl.dieCount=110;
			GloveCtrl.disableTimer=20;
			DB("dead from pain\n");
			GloveCtrl.action=HAND_FALLING;
			GloveCtrl.hurtFlag=0;
			GloveCtrl.ballCollision=FALSE;

			gloveVel.vx=0;
			gloveVel.vz=0;

			GloveCtrl.speed=0;
			GloveCtrl.targetSpeed=0;

			break;


		case DEADFROMFALLOFF:
			if (GloveCtrl.hurtFlag==0) return;
			DB("dead from world fall off\n");
			GloveBehaviour.accel=8*4096;
			CamVars.flags=FIXEDPOSITION;
			GloveCtrl.action=HAND_HURT;

			CamVars.oldTargetmodel=CamVars.targetmodel;
			CamVars.targetChangeTime=0;
			CamVars.targetChangeFlag=TRUE;

			CamVars.targetmodel=pGlovePSA;
			CamVars.fixedPos.vx=CamVars.camera.vpx;
			CamVars.fixedPos.vy=CamVars.camera.vpy;
			CamVars.fixedPos.vz=CamVars.camera.vpz;
			GloveCtrl.hurtFlag=0;
			GloveCtrl.dieCount=40;
			//gloveVel.vy=0;
			//CamVars.targetmodel=pGlovePSA;
			AddToQueue(&Glover,HANDANIM_FALL,YES,NO,4096);
			GloveCtrl.ballCollision=FALSE;
			break;

		case DEADFROMBALLFALLOFF:
			if (GloveCtrl.hurtFlag==0) return;
			GloveBehaviour.accel=8*4096;
			DB("dead from ball world fall off\n");
			AddToQueue(&Glover,HANDANIM_POINT,NO,NO,4096);
			AddToQueue(&Glover,HANDANIM_POINTCYCLE,YES,YES,4096);
			GloveCtrl.hurtFlag=0;
			GloveCtrl.action=HAND_HURT;
			//GloveCtrl.deathType=DEADFROMBALLFALLOFF;
			GloveCtrl.dieCount=40;
			gloveVel.vx=0;
			//gloveVel.vy=0;
			gloveVel.vz=0;
			GloveCtrl.speed=0;
			GloveCtrl.targetSpeed=0;
			break;
	}
	UpdateOverlays();
}



/*************************************************************************************************/
/*************************************************************************************************/
/*************************************************************************************************/

LONG	ballStartRadius,ballEndRadius,spinSpeed;

long	dennisHeight=30;

void	MaintainAction(void)
{
LONG	angle,angle1,targetAngle,dist,temp,temp1;
VECTOR	tempVec;
VECTOR	tempVecS;
VECTOR	tempVect;
MATRIX	mat;

	if(!GloveCtrl.enabled)
		return;


//	printf ("action time %d \n",GloveCtrl.actionTime);
/*
	if (GloveCtrl.hurtFlag==HURT)
	//if (GloveCtrl.deathType=FALL_DEATH
	{
		DB("im hurt\n");
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_HURT;
		GloveCtrl.disableTimer=18; // Must be even number
		AddToQueue(&Glover,HANDANIM_HURT,NO,NO,4096);
		AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
		//GloveCtrl.health--;
		GloveCtrl.hurtFlag=FALSE;
		tempVec.vz=4096*10;
		tempVec.vx=0;
		RotateVector2D(&tempVec, &tempVec,GloveCtrl.direction );
		gloveVel.vx=tempVec.vx;
		gloveVel.vy=4096*10;
		gloveVel.vz=tempVec.vz;
		GloveCtrl.flash=TRUE;
	}

	if (GloveCtrl.deathType==HURT_DEATH)
	{
		DB("im dead 1\n");
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_HURT;
		GloveCtrl.disableTimer=18;
		AddToQueue(&Glover,HANDANIM_CARDIACDEATH,NO,NO,2048);
		//AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
		//GloveCtrl.health--;
		gloveVel.vx=0;
		gloveVel.vy=0;
		gloveVel.vz=0;
		GloveCtrl.hurtFlag=DEAD;
		GloveCtrl.deathType=NULL;
	}


	if (GloveCtrl.deathType==FALL_DEATH && GloveCtrl.action!=HAND_FALLING)
	{
		DB("im dead 2\n");
		AddToQueue(&Glover,HANDANIM_FALL,YES,NO,4096);
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_FALLING;
	}
*/
	GloveDamage();
	if (GloveCtrl.preDelay) return;

	switch (GloveCtrl.action)
	{
		case HAND_LEVELCOMPLETE:

			if (GloveCtrl.actionTime==0)	// stop ball,hand and spin
			{
				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;
				CamVars.targetmodel=pGlovePSA;

				gloveVel.vx=gloveVel.vy=gloveVel.vz=0;
				ballVel.vx=ballVel.vy=ballVel.vz=0;
				ActorStartRoll(pBallPSA,0,0);
				ballRadius=ballStartRadius=BallBehaviour[BallCtrl.type].radius;
			}
			// next need to move ball up and rotate and move hand round
			if (GloveCtrl.actionTime>0 && GloveCtrl.actionTime<6) 
			{
				glovePos.vx=ballPos.vx;
				glovePos.vy=ballPos.vy;
				glovePos.vz=ballPos.vz;

				tempVec.vz = BallBehaviour[BallCtrl.type].radius-GloveBehaviour.radius/3;
				//tempVec.vz = 4096*5;
				tempVec.vy=0;
				tempVec.vx=0;
				RotateVector2DXYZ(&tempVec, &tempVec,GloveCtrl.actionTime*204,0 );

				RotateVector2D(&tempVec, &tempVec,GloveCtrl.direction );
				glovePos.vx+=tempVec.vx;
				glovePos.vy+=tempVec.vy;
				glovePos.vz+=tempVec.vz;

				COPYVECTOR(&GloveCtrl.move,&glovePos);
				HandCollision();

				ballPos.vx-=(GloveCtrl.move.vx-glovePos.vx);	// if hand on ground move ball
				ballPos.vy-=(GloveCtrl.move.vy-glovePos.vy);
				ballPos.vz-=(GloveCtrl.move.vz-glovePos.vz);
			}
			// move ball up to finger position
			if (GloveCtrl.actionTime==32)
			{
				GloveCtrl.direction=(CamVars.angle+2048)&4095;
			}

			if (GloveCtrl.actionTime==32)
			{
				sfxPlay3D(globalFX,SFX_HAND_FINGERCLICK,&glovePos);
			}
			if (GloveCtrl.actionTime==70)
			{
				sfxPlay3D(globalFX,SFX_HAND2_WOW,&glovePos);
			}


			if (GloveCtrl.actionTime==80)
			{
				if(!fadeout && !gameCtrl.dropOutFlag)
				{
					MenuFadeOut();	// immediate fade
				}
			}



			if (GloveCtrl.actionTime>=13 &&  GloveCtrl.actionTime<16)
			{
				ActorStartRollSide(pBallPSA,20000);
				ballPos.vy-=GloveBehaviour.radius/3;
			}
			pBallPSA->position.vx=ballPos.vx/4096;
			pBallPSA->position.vy=ballPos.vy/4096;
			pBallPSA->position.vz=ballPos.vz/4096;

			pGlovePSA->position.vx=glovePos.vx/4096;
			pGlovePSA->position.vy=glovePos.vy/4096;
			pGlovePSA->position.vz=glovePos.vz/4096;
			if (GloveCtrl.actionTime>=25)
			{
				ballPos.vy-=GloveBehaviour.radius/3;
				if (pBallPSA->globalscale.vx>0)
				{
					pBallPSA->globalscale.vx-=30;
					pBallPSA->globalscale.vy-=30;			
					pBallPSA->globalscale.vz-=30;
				}
				if (pBallPSA->globalscale.vx<0)
				{
					pBallPSA->globalscale.vx=0;
					pBallPSA->globalscale.vy=0;			
					pBallPSA->globalscale.vz=0;
				}
			}

			break;

		case HAND_ALLGARIBS:
			//DB("HAND_ALLGRARIBS:\n");
			//AddToQueue(&Glover,HANDANIM_THROWAIM,NO,NO,1);
			GloveCtrl.speed=0;
			GloveCtrl.targetSpeed=0;
			break;

		case HAND_FALLING:
			//DB("falling\n");
			if (GloveCtrl.onGround)
			{
				GloveCtrl.action=HAND_HURT;
				if (GloveCtrl.deathType==HURTFALL)
				{
					AddToQueue(&Glover,HANDANIM_HURT,NO,NO,4096);
					AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
					pGlovePSA->world.rotate.vx=0;
					pGlovePSA->world.rotate.vy=0;
					pGlovePSA->world.rotate.vz=0;
				}
				GloveCtrl.speed=0;
				GloveCtrl.targetSpeed=0;
				//GloveCtrl.dieCount=40;
				//AddToQueue(&Glover,HANDANIM_HURT,NO,NO,4096);
				//AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048);
			}
/*			if (GloveCtrl.dieCount==40)
			{
				DB("setting restart\n");
				gameInfo.mode=GAMEMODE_RESTART;
			}
*/			break;

//		case HAND_SUCTION:
//
//			break;


		case HAND_SWISH:

			gloveVel.vx=0;
			gloveVel.vy=0;
			gloveVel.vz=0;

			SwishVel.vy-=gravity;
			ADDVECTOR(&SwishPos, &SwishPos, &SwishVel);
			SwishPos.vy-=(SwishVel.vy*2);
			//SwishPos.vy-=SwishColl.radius-(20*4096);

			SwishPos.vy -= 16 * 4096;	// not his radius, note
			collboxCheckSphere(&SwishColl);
			SwishPos.vy += 16 * 4096;

			break;


		case HAND_HOPPING:
			//DB("hand on dennis?\n");
			gloveVel.vx=0;
			gloveVel.vy=0;
			gloveVel.vz=0;

			if ( glovePos.vy>=world_base_y && (GloveCtrl.deathType!=DEADFROMFALLOFF && GloveCtrl.deathType!=DEADFROMBALLFALLOFF) )
			{
				nmeDismountDenis(GloveCtrl.mount);
				GloveCtrl.action=HAND_IDLE;
			}



// Fred note - dennis's yvel's +ve downwards
			DennisVel.vy+=gravity;
			ADDVECTOR(&DennisPos, &DennisPos, &DennisVel);

			temp=GloveCtrl.dennisOnGround;

			DennisPos.vy-=DennisColl.radius-(20*4096);
			GloveCtrl.dennisOnGround = GloveCtrl.onGround = collboxCheckSphere(&DennisColl);
			DennisPos.vy+=DennisColl.radius-(20*4096);

// There's a separate "dennis-on-ground" flag now, coz there're some
// calls to handcollision which reset things such that this "landed"
// test" doesn't work
			if (temp==0 && GloveCtrl.dennisOnGround )
			{	
				AddToQueue(&GloveCtrl.mount->anim,NMEANIM_IDLE,YES,NO,2048);
				//GloveCtrl.dennisJumpHit=FALSE;
				GloveCtrl.dennisJump=FALSE;
			}

			if (GloveCtrl.dennisOnGround)
			{
				DennisVel.vx=0;
				DennisVel.vz=0;
			}

			GloveCtrl.mount->pos.vx=DennisPos.vx;
			GloveCtrl.mount->pos.vy=DennisPos.vy;
			GloveCtrl.mount->pos.vz=DennisPos.vz;

			tempVecS.vx=0;
			//tempVecS.vy=GloveCtrl.mount->pos.vy-(DENNISHEIGHT*GloveCtrl.mount->psa->world.scale.vy);//+GloveCtrl.mount->psa->world.matrix.t[1];
			tempVecS.vy=-(DENNISHEIGHT*GloveCtrl.mount->psa->world.scale.vy)-GloveCtrl.mount->psa->world.matrix.t[1];
			tempVecS.vz=0;

			objectSetAnimation(GloveCtrl.mount->psa, animate(&GloveCtrl.mount->anim));
			MatrixNormal(&GloveCtrl.mount->psa->world.matrix,&mat);
			mat.t[0]=0;
			mat.t[1]=0;
			mat.t[2]=0;
			ApplyMatrixLV(&mat,&tempVecS,&tempVec);
			//ApplyMatrixLV(&GloveCtrl.mount->psa->world.matrix,&tempVecS,&tempVec);

			//glovePos.vx=GloveCtrl.mount->pos.vx;
			//glovePos.vy=GloveCtrl.mount->pos.vy-(DENNISHEIGHT*GloveCtrl.mount->psa->world.scale.vy)+GloveCtrl.mount->psa->world.matrix.t[1];
			//glovePos.vz=GloveCtrl.mount->pos.vz;

			glovePos.vx=GloveCtrl.mount->pos.vx+(tempVec.vx);
			glovePos.vy=GloveCtrl.mount->pos.vy+(tempVec.vy);
			//glovePos.vy=(tempVec.vy);
			glovePos.vz=GloveCtrl.mount->pos.vz+(tempVec.vz);

			break;

		
		case HAND_ROTOR:
			if (GloveCtrl.actionTime==1) // first time
			{
				AddToQueue(&Glover,HANDANIM_THROWAIM,NO,NO,1);
				//Glover.animInfo->inc=2;
				pGlovePSA->world.rotate.vx=1024;

				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;
				CamVars.targetmodel=pGlovePSA;
				GloveCtrl.actionTime=2;
				GloveCtrl.handOnBall=FALSE;
			}
			break;


		case HAND_HURT:
			if (GloveCtrl.dieCount) GloveCtrl.dieCount--;
			switch (GloveCtrl.deathType)
			{
				case 0:
						DB("in-cameo-hurt after the deathtype's been zeroed\n");
						if (GloveCtrl.onGround)
						{
							gloveVel.vx=0;
							gloveVel.vy=0;
							gloveVel.vz=0;
						}
						//if (GloveCtrl.flash) GloveCtrl.flash=FALSE;
						//else GloveCtrl.flash=TRUE;
						if (GloveCtrl.dieCount==0)
						{
							GloveCtrl.hurtFlag=NULL;
							GloveCtrl.deathType=NULL;
							GloveCtrl.action=HAND_IDLE;
							GloveCtrl.flash=FALSE;
						}
						CamVars.oldTargetmodel=CamVars.targetmodel;
						CamVars.targetChangeTime=0;
						CamVars.targetChangeFlag=TRUE;

						CamVars.targetmodel=pGlovePSA;
						GloveCtrl.ballCollision=TRUE;
						break;



				case HURTFALL:
				case HURTPAIN:
					//AddToQueue(&Glover,HANDANIM_HURT,NO,NO,4096);
					//AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);

					DB("do hurt \n");
					//tempVec.vz=4096*5;
					//tempVec.vx=0;
					//RotateVector2D(&tempVec, &tempVec,GloveCtrl.direction );
					//gloveVel.vx=tempVec.vx;
					//gloveVel.vz=tempVec.vz;
					// Put health check 
					//GloveCtrl.health--;
					if (GloveCtrl.onGround)
					{
						gloveVel.vx=0;
						gloveVel.vy=0;
						gloveVel.vz=0;
					}
					//if (GloveCtrl.flash) GloveCtrl.flash=FALSE;
					//else GloveCtrl.flash=TRUE;
					if (GloveCtrl.dieCount==0)
					{
						GloveCtrl.hurtFlag=NULL;
						GloveCtrl.deathType=NULL;
						GloveCtrl.action=HAND_IDLE;
						GloveCtrl.flash=FALSE;
					}

					CamVars.oldTargetmodel=CamVars.targetmodel;
					CamVars.targetChangeTime=0;
					CamVars.targetChangeFlag=TRUE;

					CamVars.targetmodel=pGlovePSA;
					GloveCtrl.ballCollision=TRUE;
					break;

				case DEADFROMFALL:
					DB("do fall dead\n");
					gloveVel.vx=0;
					//gloveVel.vy=0;
					gloveVel.vz=0;

					if (!GloveCtrl.onGround/* && Glover.currentAnimation==HANDANIM_FALLDEATH*/)
					{
						GloveCtrl.dieCount++;
						GloveCtrl.disableTimer++;
						GloveCtrl.handHurtTime++;
						//printf ("holding for death cycle diecount %d disableTimer %d \n",GloveCtrl.dieCount,GloveCtrl.disableTimer);
					}
					
					if (GloveCtrl.onGround && Glover.currentAnimation!=HANDANIM_FALLDEATH/*&& GloveCtrl.dieCount==0*/)
					{
						printf ("now on ground\n");
						AddToQueue(&Glover,HANDANIM_FALLDEATH,NO,NO,2048);
						AddToQueue(&Glover,HANDANIM_FALLDEATH,YES,YES,-1);
						GloveCtrl.dieCount=52;
						GloveCtrl.disableTimer=50;
					}

					if (GloveCtrl.dieCount && GloveCtrl.disableTimer==0) handKillGlove();

					//{
					//	// any lives left
					//	GloveCtrl.lives--;
					//	GloveCtrl.dieCount=255;		// nasty but stops chicken and egg problem
					//	if (GloveCtrl.lives>250) // no (ubyte check for overflow)
					//	{
					//		gameCtrl.dropOutFlag=TRUE;
					//	}
					//	else gameInfo.mode=GAMEMODE_RESTART;
					//}
					
					GloveCtrl.ballCollision=TRUE;

					CamVars.oldTargetmodel=CamVars.targetmodel;
					CamVars.targetChangeTime=0;
					CamVars.targetChangeFlag=TRUE;

					CamVars.targetmodel=pGlovePSA;
					break;

				case DEADFROMPAIN:
					DB("do pain dead\n");
					gloveVel.vx=0;
					//gloveVel.vy=0;
					gloveVel.vz=0;

// Specifically, spbonus, hitting the spikes
					if(gameInfo.levelType==BONUS_LEVEL && GloveCtrl.dieCount < 25 )
					{
						if(!gameCtrl.dropOutFlag)
						{
							MenuFadeOut();
							gameCtrl.dropOutFlag=GAME_FAILEDBONUS;
							NextLevelBasics();
						}
					}


					/*if (GloveCtrl.onGround && GloveCtrl.dieCount==0)
					{
						AddToQueue(&Glover,HANDANIM_FALLDEATH,NO,NO,2048);
						AddToQueue(&Glover,HANDANIM_FALLDEATH,NO,YES,-1);
						GloveCtrl.dieCount=52;
						GloveCtrl.disableTimer=50;
					}
					*/
					if (GloveCtrl.dieCount==0) handKillGlove();
					//{
					//	// any lives left
					//	GloveCtrl.lives--;
					//	GloveCtrl.dieCount=255;		// nasty but stops chicken and egg problem
					//	if (GloveCtrl.lives>250) // no (ubyte check for overflow)
					//	{
					//		gameCtrl.dropOutFlag=TRUE;
					//	}
					//	else gameInfo.mode=GAMEMODE_RESTART;
					//}
					GloveCtrl.ballCollision=TRUE;

					CamVars.oldTargetmodel=CamVars.targetmodel;
					CamVars.targetChangeTime=0;
					CamVars.targetChangeFlag=TRUE;

					CamVars.targetmodel=pGlovePSA;
					break;


				case DEADFROMFALLOFF:
					DB("do fall off\n");
					CamVars.flags=FIXEDPOSITION;
					if (GloveCtrl.dieCount==0) handKillGlove();
					//{
					//	/*if (!GloveCtrl.deathTypeBall) */GloveCtrl.lives--;
					//	GloveCtrl.dieCount=255;		// nasty but stops chicken and egg problem
					//	if (GloveCtrl.lives>250) // no (ubyte check for overflow)
					//	{
					//		gameCtrl.dropOutFlag=TRUE;
					//	}
					//	else gameInfo.mode=GAMEMODE_RESTART;
					//}

					CamVars.oldTargetmodel=CamVars.targetmodel;
					CamVars.targetChangeTime=0;
					CamVars.targetChangeFlag=TRUE;

					CamVars.targetmodel=pGlovePSA;
					break;
				case DEADFROMBALLFALLOFF:
					DB("do ball fall off \n");

					angle=calc_angle( (ballPos.vx-glovePos.vx)/4096,(ballPos.vz-glovePos.vz)/4096 );
					angle=(angle+2048)&4095;
					//angle1=GloveCtrl.direction;
					// need to make this smooth
					//angle1=(angle1+2048)&4095;
					//targetAngle = findShortestAngle(angle,angle1);
					//if ( abs(targetAngle)>(ROTATESPEED/2) )
					//{
					//	if (targetAngle>0) GloveCtrl.direction+=(ROTATESPEED/2);
					//	else GloveCtrl.direction-=(ROTATESPEED/2);
					//}
					//else GloveCtrl.direction+=targetAngle;
					pGlovePSA->world.rotate.vy=GloveCtrl.direction=angle;
					// now do point height
					tempVec.vx=(glovePos.vx-ballPos.vx)/4096;
					tempVec.vz=(glovePos.vz-ballPos.vz)/4096;
					tempVec.vy=0;
					dist=Magnitude(&tempVec);
					angle=calc_angle( (ballPos.vy-glovePos.vy)/4096,dist );
					pGlovePSA->world.rotate.vx =(angle&4095);
					if (GloveCtrl.dieCount==0) handKillGlove();
					//{
					//	GloveCtrl.lives--;
					//	GloveCtrl.dieCount=255;		// nasty but stops chicken and egg problem
					//	if (GloveCtrl.lives>250) // no (ubyte check for overflow)
					//	{
					//		gameCtrl.dropOutFlag=TRUE;
					//	}
					//	else gameInfo.mode=GAMEMODE_RESTART;
					//}
					GloveCtrl.ballCollision=TRUE;

					CamVars.oldTargetmodel=CamVars.targetmodel;
					CamVars.targetChangeTime=0;
					CamVars.targetChangeFlag=TRUE;

					CamVars.targetmodel=pGlovePSA;
					break;

				/*case DEADFROMBALLBURST:
					DB("do ball burst off \n");
					angle=calc_angle( (ballPos.vx-glovePos.vx)/4096,(ballPos.vz-glovePos.vz)/4096 );
					angle=(angle+2048)&4095;
					pGlovePSA->world.rotate.vy=GloveCtrl.direction=angle;
					// now do point height
					tempVec.vx=(glovePos.vx-ballPos.vx)/4096;
					tempVec.vz=(glovePos.vz-ballPos.vz)/4096;
					tempVec.vy=0;
					dist=Magnitude(&tempVec);
					angle=calc_angle( (ballPos.vy-glovePos.vy)/4096,dist );
					pGlovePSA->world.rotate.vx =(angle&4095);
					if (GloveCtrl.dieCount==0)
					{
						GloveCtrl.lives--;
						if (GloveCtrl.lives>250) // no (ubyte check for overflow)
						{
							gameCtrl.dropOutFlag=TRUE;
						}
						else gameInfo.mode=GAMEMODE_RESTART;
					}
					GloveCtrl.ballCollision=TRUE;
					doBallBurst();
					UpdateBallPos();

					CamVars.oldTargetmodel=CamVars.targetmodel;
					CamVars.targetChangeTime=0;
					CamVars.targetChangeFlag=TRUE;

					CamVars.targetmodel=pGlovePSA;
					break;
				*/
			}
			if (GloveCtrl.deathTypeBall==DEADFROMBALLBURST)
			{
				//if (GloveCtrl.health==0) 
				if (GloveCtrl.deathType!=DEADFROMPAIN && GloveCtrl.deathType!=DEADFROMFALL && GloveCtrl.health!=0)
				{
					angle=calc_angle( (ballPos.vx-glovePos.vx)/4096,(ballPos.vz-glovePos.vz)/4096 );
					angle=(angle+2048)&4095;
					pGlovePSA->world.rotate.vy=GloveCtrl.direction=angle;
					// now do point height
					tempVec.vx=(glovePos.vx-ballPos.vx)/4096;
					tempVec.vz=(glovePos.vz-ballPos.vz)/4096;
					tempVec.vy=0;
					dist=Magnitude(&tempVec);
					angle=calc_angle( (ballPos.vy-glovePos.vy)/4096,dist );
					pGlovePSA->world.rotate.vx =(angle&4095);
				}
				if (GloveCtrl.dieCount==0) handKillGlove();
				//{
				//	GloveCtrl.lives--;
				//	GloveCtrl.dieCount=255;		// nasty but stops chicken and egg problem
				//
				//	if (GloveCtrl.lives>250) // no (ubyte check for overflow)
				//	{
				//			gameCtrl.dropOutFlag=TRUE;
				//	}
				//	else gameInfo.mode=GAMEMODE_RESTART;
				//}
				GloveCtrl.ballCollision=TRUE;
				doBallBurst();
				UpdateBallPos();
	
				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;
				CamVars.targetmodel=pGlovePSA;
			}
			break;

		case HAND_CLIMBDOWN:

			break;

		case HAND_LOB:
			if (!GloveCtrl.disableTimer)
			{
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_IDLE;
				GloveCtrl.flags=GLOVEMOVE;
				BallCtrl.ballStopMove=FALSE;
				GloveCtrl.ballWithHand=FALSE;

			}
			break;

		case HAND_BALLWALK:
			if (GloveCtrl.disableTimer<=3) 
			{
				glovePos.vx=ballPos.vx;
				glovePos.vz=ballPos.vz;
			}
			glovePos.vx = ballPos.vx;
			glovePos.vz = ballPos.vz;
			
			gloveVel.vx = ballVel.vx;
			gloveVel.vz = ballVel.vz;
			GloveCtrl.speed=0;
			break;

		case HAND_CATCH:

			if (pGlovePSA->world.rotate.vx>-350) pGlovePSA->world.rotate.vx-=50;
			if (pGlovePSA->world.rotate.vx<-350) pGlovePSA->world.rotate.vx=-350;

			if ( !CatchBallAllowed() )
			{
				AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048);
				GloveCtrl.action=HAND_IDLE;
				GloveCtrl.walkType=NULL;
				pGlovePSA->world.rotate.vx=0;
			}

			if ( (glovePos.vy-ballPos.vy<BallBehaviour[BallCtrl.type].radius*4) && !GloveCtrl.ballWithHand)
			{
				ballPos.vx-=(ballPos.vx-glovePos.vx)/4;
				ballPos.vz-=(ballPos.vz-glovePos.vz)/4;				
			}

			if ( !GloveCtrl.ballWithHand )
			{
				if (BallCtrl.justHitFlag)
				{
					if ( (glovePos.vy-BallCtrl.ballPosWhenHit.vy<BallBehaviour[BallCtrl.type].radius/2) )
					{
						ballPos.vx=glovePos.vx;
						ballPos.vz=glovePos.vz;
						ballPos.vy=glovePos.vy-BallBehaviour[BallCtrl.type].radius/2;
						GloveCtrl.actionTime=0;

						CamVars.oldTargetmodel=CamVars.targetmodel;
						CamVars.targetChangeTime=0;
						CamVars.targetChangeFlag=TRUE;

						GloveCtrl.speed=0;
						GloveCtrl.targetSpeed=0;
						GloveCtrl.ballWithHand=TRUE;
						CamVars.targetmodel=pBallPSA;
						GloveCtrl.disableTimer=18;			// disable controls for 18 ticks
						aReleased=FALSE;
						ballVel.vy=ballVel.vx=ballVel.vz=0;
						//removeSnow();
					}
				}
				else if ( (glovePos.vy-ballPos.vy<BallBehaviour[BallCtrl.type].radius/2) )
				{
					ballPos.vx=glovePos.vx;
					ballPos.vz=glovePos.vz;
					ballPos.vy=glovePos.vy-BallBehaviour[BallCtrl.type].radius/2;
					GloveCtrl.actionTime=0;

					CamVars.oldTargetmodel=CamVars.targetmodel;
					CamVars.targetChangeTime=0;
					CamVars.targetChangeFlag=TRUE;

					CamVars.targetmodel=pBallPSA;
					GloveCtrl.speed=0;
					GloveCtrl.targetSpeed=0;
					GloveCtrl.ballWithHand=TRUE;
					GloveCtrl.disableTimer=18;			// disable controls for 18 ticks
					aReleased=FALSE;
					ballVel.vy=ballVel.vx=ballVel.vz=0;
				}
			}

			if (GloveCtrl.ballWithHand)
			{
				if (GloveCtrl.actionTime<10)
				{
					ballPos.vy=glovePos.vy-BallBehaviour[BallCtrl.type].radius/2;
					ballVel.vy=ballVel.vx=ballVel.vz=0;
					//removeSnow();
				}
				else
				{
					AddToQueue(&Glover,HANDANIM_THROWAIM,YES,NO,-6144);
					GloveCtrl.lastAction=GloveCtrl.action;
					GloveCtrl.action=HAND_JOINED;
					pGlovePSA->world.rotate.vx=0;
					//removeSnow();
				}
			}
			break;

		case HAND_CASTSPELL:

			if (BallCtrl.snowAddition)
			{
				BallCtrl.snowAddition=0;
				BallChange.changeOn=NULL;
				BallCtrl.type=BallCtrl.preSnowType;
				ChangeBall(&pBallPSA->world,ballTex[BallCtrl.type]);
				BallCtrl.snowTexChange=FALSE;
				ballColl.physicsModel=BallCtrl.type;
				ballColl.radius=BallBehaviour[BallCtrl.preSnowType].radius=BallBehaviour[BallCtrl.type].radius;
				BallBehaviour[BallCtrl.preSnowType].mass=BallBehaviour[BallCtrl.type].mass;
				BallBehaviour[BallCtrl.preSnowType].drag=BallBehaviour[BallCtrl.type].drag;
				BallBehaviour[BallCtrl.preSnowType].bounce=BallBehaviour[BallCtrl.type].bounce;
				BallBehaviour[BallCtrl.preSnowType].accel=BallBehaviour[BallCtrl.type].accel;

				platformGenerateShrapnel(&ballPos, 10, 2, pBallPSA, pSnowFrag);
			}

			if (GloveCtrl.lastAction!=HAND_JOINED)
			{
				angle=calc_angle( (ballPos.vx-glovePos.vx)/4096,(ballPos.vz-glovePos.vz)/4096 );
				angle=angle&4095;
				angle1=GloveCtrl.direction;
				// need to make this smooth
				angle1=(angle1+2048)&4095;
				targetAngle = findShortestAngle(angle,angle1);
				if ( abs(targetAngle)>(ROTATESPEED/2) )
				{
					if (targetAngle>0) GloveCtrl.direction+=(ROTATESPEED/2);
					else GloveCtrl.direction-=(ROTATESPEED/2);
				}
				else GloveCtrl.direction+=targetAngle;

				if (GloveCtrl.disableTimer==15)
				{
					int type;
					//if (!BallChange.changeOn)
					//{
						//BallCtrl.lastType=BallCtrl.type;
						if (BallCtrl.type==BALL_MODE_BEACH)
						{
							type=BALL_MODE_NORMAL;
							handpower_timer=0;
						}
						else type = ballNextMode[BallCtrl.type];
					//}
					//else type=BallCtrl.lastType;

					pickupFireGloveSpell(type - BALL_MODE_NORMAL + SPELL_BALL_NORMAL);

				}
				if (GloveCtrl.disableTimer==0)
				{
					GloveCtrl.action=HAND_IDLE;
					BallBehaviour[0].radius=(19*4096*NORMAL_SCALE)*1;
					BallBehaviour[1].radius=1*(19*4096*NORMAL_SCALE)*1.4;
					BallBehaviour[2].radius=(19*4096*NORMAL_SCALE)*0.6;
					BallBehaviour[3].radius=(19*4096*NORMAL_SCALE)*0.6;
					BallBehaviour[4].radius=(19*4096*NORMAL_SCALE)*2.5;
					BallBehaviour[5].radius=(19*4096*NORMAL_SCALE)*0.9;
					BallBehaviour[6].radius=(19*4096*NORMAL_SCALE)*1;
// This "Glovemove" line added by Fred at the same time as making "locate <-> spell" allowed,
// coz otherwise spell-whilst-aiming left you unable to move
					GloveCtrl.flags=GLOVEMOVE;
					pGlovePSA->world.rotate.vx =0;
					GloveCtrl.lastAction=HAND_CASTSPELL;
					GloveCtrl.onGround=FALSE;
					GloveCtrl.positionHold=FALSE;

					GloveCtrl.ballWithHand=FALSE;
					if (GloveCtrl.spellCastOnBall) GloveCtrl.disableTimer=8;
					GloveCtrl.handOnBall=FALSE;

					glovePos.vy-=gloveVel.vy;
					gloveColl.oldPos.vy-=gloveVel.vy;

					CamVars.oldTargetmodel=CamVars.targetmodel;
					CamVars.targetChangeTime=0;
					CamVars.targetChangeFlag=TRUE;

					CamVars.targetmodel=pGlovePSA;
					GloveCtrl.walkType=NULL;
				}
				pGlovePSA->position.vx=glovePos.vx/4096;
				pGlovePSA->position.vy=glovePos.vy/4096;
				pGlovePSA->position.vz=glovePos.vz/4096;

			}
			else	// hand holding ball
			{
				if (GloveCtrl.actionTime==0)	// stop ball,hand and spin
				{
					gloveVel.vx=gloveVel.vy=gloveVel.vz=0;
					ballVel.vx=ballVel.vy=ballVel.vz=0;
					ActorStartRoll(pBallPSA,0,0);
					ballRadius=ballStartRadius=BallBehaviour[BallCtrl.type].radius;
					GloveCtrl.onGround=FALSE;
					//printf ("setting to off ground\n");
				}
				// next need to move ball up and rotate and move hand round
				if (GloveCtrl.actionTime>0 && GloveCtrl.actionTime<6) 
				{
					glovePos.vx=ballPos.vx;
					glovePos.vy=ballPos.vy;
					glovePos.vz=ballPos.vz;

					tempVec.vz = BallBehaviour[BallCtrl.type].radius-GloveBehaviour.radius/3;
					//tempVec.vz = 4096*5;
					tempVec.vy=0;
					tempVec.vx=0;
					RotateVector2DXYZ(&tempVec, &tempVec,GloveCtrl.actionTime*204,0 );

					RotateVector2D(&tempVec, &tempVec,GloveCtrl.direction );
					glovePos.vx+=tempVec.vx;
					glovePos.vy+=tempVec.vy;
					glovePos.vz+=tempVec.vz;

					COPYVECTOR(&GloveCtrl.move,&glovePos);
					HandCollision();

					ballPos.vx-=(GloveCtrl.move.vx-glovePos.vx);	// if hand on ground move ball
					ballPos.vy-=(GloveCtrl.move.vy-glovePos.vy);
					ballPos.vz-=(GloveCtrl.move.vz-glovePos.vz);
				}
				// move ball up to finger position
				if (GloveCtrl.actionTime>=6 &&  GloveCtrl.actionTime<9)
				{
					ballPos.vy-=GloveBehaviour.radius/3;
					//ballPos.vy=glovePos.vy-(GloveBehaviour.radius/(9-GloveCtrl.actionTime));
				}

				// now need to do change
				if (GloveCtrl.actionTime==9)
				{
					int dest;
					ballStartRadius=BallBehaviour[BallCtrl.type].radius;
					BallChange.fromBall=BallCtrl.type;

					sfxPlay3D(globalFX,SFX_CAST_SPELL_3,&ballPos);

					//dest = ballNextMode[BallCtrl.type];

					if (BallCtrl.type==BALL_MODE_BEACH)
					{
						dest=BallChange.toBall=BALL_MODE_NORMAL;
						handpower_timer=0;
					}
					else dest=BallChange.toBall=ballNextMode[BallCtrl.type];

					ballEndRadius=BallBehaviour[dest].radius;

					spinSpeed=60000;
					GloveCtrl.move.vy=(ballStartRadius-ballEndRadius);
				}
				// change ball size and texture
				//if (GloveCtrl.actionTime<=9 && BallChange.changeOn==SPELLCHANGE )
				//	GloveCtrl.actionTime=22;

				if (GloveCtrl.actionTime>9 && GloveCtrl.actionTime<21/* && BallChange.changeOn!=SPELLCHANGE*/)
				{
					BallChange.changeOn=SPELLCHANGE;
					GloveCtrl.spellCast=TRUE;
					GloveCtrl.spellActionTime=GloveCtrl.actionTime;


/*					temp=GloveCtrl.actionTime-9;
					BallChange.timer=11-temp;
					temp1=21-GloveCtrl.actionTime;
					ballColl.radius=ballRadius=BallBehaviour[BallCtrl.type].radius=((ballStartRadius*temp1)/12)+ ((ballEndRadius*temp)/12);
					ActorStartRollSide(pBallPSA,spinSpeed);
					spinSpeed-=spinSpeed/20;
					ballPos.vy+=GloveCtrl.move.vy/10;

					if (GloveCtrl.actionTime==15)
					{
						BallBehaviour[BallCtrl.type].radius=ballStartRadius;
						BallCtrl.lastType=BallCtrl.type;
						if (BallCtrl.type==BALL_MODE_BEACH)
						{
							BallCtrl.type=BALL_MODE_NORMAL;
							handpower_timer=0;
						}
						else BallCtrl.type=ballNextMode[BallCtrl.type];

						if (BallCtrl.type==BALL_MODE_CRYSTAL) pBallPSA=pCballPSA;
						if (BallCtrl.lastType==BALL_MODE_CRYSTAL) pBallPSA=pOldBall;

						CamVars.oldTargetmodel=CamVars.targetmodel;
						CamVars.targetChangeTime=0;
						CamVars.targetChangeFlag=TRUE;

						CamVars.targetmodel=pBallPSA;
						ballColl.physicsModel=BallCtrl.type;
						New_StarRingDebris(&ballPos, 5);
					}
*/				}

				if (GloveCtrl.actionTime==21)
				{
					ballColl.radius=ballRadius=BallBehaviour[BallCtrl.type].radius=ballEndRadius;
					ActorStartRollSide(pBallPSA,spinSpeed);
					spinSpeed-=spinSpeed/20;
					//GloveCtrl.onGround=FALSE;
				}

				// (can repeat or interupt at this point)
				if (GloveCtrl.action>21 && GloveCtrl.action<42)
				{
					ActorStartRollSide(pBallPSA,spinSpeed);
					spinSpeed-=spinSpeed/20;

					tempVec.vx = (ballPos.vx) + rsin((sinewave1>>16) & 4095) * 20;
					tempVec.vz = (ballPos.vz) + rcos((sinewave1>>16) & 4095) * 20;
					tempVec.vy = (ballPos.vy) + rsin((sinewave2>>16) & 4095) * 6;
					New_Debris(DEBRIS_LIFEGLOW,&tempVec,0);
				}

				// put ball back on ground 
				if (GloveCtrl.actionTime==42)
				{
					//GloveCtrl.spellCast=FALSE;
					GloveCtrl.freeVar=(ballPos.vy-glovePos.vy)+(BallBehaviour[BallCtrl.type].radius-GloveBehaviour.radius);
					tempVec.vz = BallBehaviour[BallCtrl.type].radius-GloveBehaviour.radius/3;
					tempVec.vy=0;
					tempVec.vx=0;
					RotateVector2D(&tempVec, &tempVec,GloveCtrl.direction );
					GloveCtrl.move.vy=BallBehaviour[BallCtrl.type].radius-GloveBehaviour.radius;
					GloveCtrl.move.vx=tempVec.vx;
					GloveCtrl.move.vz=tempVec.vz;
				}
				
				if (GloveCtrl.actionTime>=42 && GloveCtrl.actionTime<=46)
				{
					ballPos.vy-=GloveCtrl.freeVar/5;
					glovePos.vy-=GloveCtrl.move.vy/5;
					glovePos.vx+=GloveCtrl.move.vx/5;
					glovePos.vz+=GloveCtrl.move.vz/5;

					//gloveColl.oldPos.vy-=GloveCtrl.move.vy/5;
					//gloveColl.oldPos.vx+=GloveCtrl.move.vx/5;
					//gloveColl.oldPos.vz+=GloveCtrl.move.vz/5;
				}

				if (GloveCtrl.actionTime==53)
				{
					GloveCtrl.action=HAND_JOINED;
					AddToQueue(&Glover,HANDANIM_WHACKAIM,NO,NO,0);
					GloveCtrl.walkType=NULL;
//					BallBehaviour[0].radius=(19*4096*NORMAL_SCALE)*1;
//					BallBehaviour[1].radius=(19*4096*NORMAL_SCALE)*1.4;
//					BallBehaviour[2].radius=(19*4096*NORMAL_SCALE)*0.6;
//					BallBehaviour[3].radius=(19*4096*NORMAL_SCALE)*0.6;
//					BallBehaviour[4].radius=(19*4096*NORMAL_SCALE)*2.5;
//					BallBehaviour[5].radius=(19*4096*NORMAL_SCALE)*0.9;
//					BallBehaviour[6].radius=(19*4096*NORMAL_SCALE)*1;
//					ChangeBall(&pBallPSA->world,ballTex[BallCtrl.type]);
					//DB ("from %d to %d \n",BallChange.fromBall,BallChange.toBall);
				}

			

/*
				if (GloveCtrl.actionTime==23)
				{
					GloveCtrl.move.vx=0;
					GloveCtrl.move.vz=0;
					//GloveCtrl.move.vy
					 (ballPos.vy-glovePos.vy) - (ballPos.vy-(glovePos.vy-(BallBehaviour[BallCtrl.type].radius+GloveBehaviour.radius)));
					GloveCtrl.move.vy= -(BallBehaviour[BallCtrl.type].radius+GloveBehaviour.radius);
					GloveCtrl.move.vy/=5;
					
					ballStartRadius=BallBehaviour[BallCtrl.type].radius;
					BallCtrl.type++;
					if (BallCtrl.type==NUM_BALL_MODES) BallCtrl.type=BALL_MODE_NORMAL;
					//if (BallCtrl.type==BALL_MODE_CRYSTAL) pBallPSA=pCballPSA;
					//if (BallCtrl.lastType==BALL_MODE_CRYSTAL) pBallPSA=pOldBall;
					ballEndRadius=BallBehaviour[BallCtrl.type].radius;
					BallCtrl.type--;
					if (BallCtrl.type<0) BallCtrl.type=BALL_MODE_CRYSTAL;
					spinSpeed=60000;
				}
				
				if (GloveCtrl.actionTime>=24 && GloveCtrl.actionTime<=28 && GloveCtrl.walkType==NULL)
				{
					ballPos.vy+=GloveCtrl.move.vy;
				}

				if (GloveCtrl.actionTime==29)
				{
					BallCtrl.lastType=BallCtrl.type;
					BallCtrl.type++;
					if (BallCtrl.type==NUM_BALL_MODES) BallCtrl.type=BALL_MODE_NORMAL;
					if (BallCtrl.type==BALL_MODE_CRYSTAL) pBallPSA=pCballPSA;
					if (BallCtrl.lastType==BALL_MODE_CRYSTAL) pBallPSA=pOldBall;
					CamVars.targetmodel=pBallPSA;
					ballRadius=BallBehaviour[BallCtrl.type].radius;
					ballColl.physicsModel=BallCtrl.type;
					ChangeBall(&pBallPSA->world,ballTex[BallCtrl.type]);
					New_StarRingDebris(&ballPos, 5);
				}

				if (GloveCtrl.actionTime>=29 && GloveCtrl.actionTime<=40)
				{
					temp=GloveCtrl.actionTime-29;
					temp1=40-GloveCtrl.actionTime;
					ballRadius=BallBehaviour[BallCtrl.type].radius=((ballStartRadius*temp1)/11)+ ((ballEndRadius*temp)/11);
				}

				if (GloveCtrl.actionTime>=30 && GloveCtrl.actionTime<=82)
				{
					ballPos.vx=glovePos.vx;	
					ballPos.vz=glovePos.vz;	
					ballPos.vy=glovePos.vy-(BallBehaviour[BallCtrl.type].radius+(GloveBehaviour.radius-(GloveBehaviour.radius/4)));
					ActorStartRollSide(pBallPSA,spinSpeed);
					spinSpeed-=spinSpeed/20;

					tempVec.vx = (ballPos.vx) + rsin((sinewave1>>16) & 4095) * 20;
					tempVec.vz = (ballPos.vz) + rcos((sinewave1>>16) & 4095) * 20;
					tempVec.vy = (ballPos.vy) + rsin((sinewave2>>16) & 4095) * 6;
					New_Debris(DEBRIS_LIFEGLOW,&tempVec,0);
					//DB ("effects");
				}

				if (GloveCtrl.actionTime==83)
				{
					GloveCtrl.move.vx=0;
					GloveCtrl.move.vz=0;
					//GloveCtrl.move.vy= glovePos.vy-ballPos.vy; 

					GloveCtrl.move.vy=getHeightAt( ballPos.vx, ballPos.vy, ballPos.vz);
					GloveCtrl.move.vy-=BallBehaviour[BallCtrl.type].radius;

					GloveCtrl.move.vy/=10;
				}
				if (GloveCtrl.actionTime>=83)
				{
					ballPos.vy+=GloveCtrl.move.vy;
				}
								
				if (GloveCtrl.actionTime==93)
				{
					GloveCtrl.action=HAND_JOINED;
					AddToQueue(&Glover,HANDANIM_WHACKAIM,NO,NO,0);
					GloveCtrl.walkType=NULL;
				}
*/				pBallPSA->position.vx=ballPos.vx/4096;
				pBallPSA->position.vy=ballPos.vy/4096;
				pBallPSA->position.vz=ballPos.vz/4096;

				pGlovePSA->position.vx=glovePos.vx/4096;
				pGlovePSA->position.vy=glovePos.vy/4096;
				pGlovePSA->position.vz=glovePos.vz/4096;
			}
			break;

		case HAND_NMESPELL:
			if (GloveCtrl.disableTimer==30)
			{
				pickupFireGloveSpell(handpower_type);

			}

			if (GloveCtrl.disableTimer==0)
			{
				GloveCtrl.action=HAND_IDLE;
			}
			break;

		case HAND_DUCK:
		case HAND_CRAWL:
			break;

//		case HAND_CARTWHEEL:
//			if (!GloveCtrl.disableTimer)
//			{
//				GloveCtrl.lastAction=GloveCtrl.action;
//				GloveCtrl.action=HAND_IDLE;
//			}
//			break;

		case HAND_PREWHACK:
			if (!cHeld && GloveCtrl.actionTime>5)
			{
				AddToQueue(&Glover,HANDANIM_WHACK,NO,NO,5120);
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				GloveCtrl.action=HAND_WHACK;
				GloveCtrl.actionTime=0;
				GloveCtrl.disableTimer=8;

				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;
				GloveCtrl.ballWithHand=FALSE;
				CamVars.targetmodel=pGlovePSA;
				gloveVel.vx=0;
				gloveVel.vz=0;
				GloveCtrl.targetSpeed=0;
				GloveCtrl.speed=0;
				GloveCtrl.positionHold=FALSE;
			}
			else
			{
				if (GloveCtrl.whackAir)	// Hold the hand and ball in the air
				{
					ActorStartRoll(pBallPSA,0,0);
					ballVel.vx=ballVel.vy=ballVel.vz=0;
					gloveVel.vy=0;
					ballPos.vx=oldBallPos.vx;
					if (ballPos.vy<oldBallPos.vy) oldBallPos.vy=ballPos.vy;
					glovePos.vy=ballPos.vy=oldBallPos.vy;
					ballPos.vz=oldBallPos.vz;
					//GloveCtrl.actionTime=0;
				}
				gloveVel.vx=ballVel.vx;
				gloveVel.vz=ballVel.vz;
			}
			GloveCtrl.onGround=FALSE;
			break;

		case HAND_WHACK:
			GloveCtrl.ballWithHand=FALSE;
			if (!GloveCtrl.disableTimer)
			{
				GloveCtrl.action=HAND_IDLE;
				GloveCtrl.onGround=FALSE;
			}
			break;

		case HAND_THROWAIM:
			// Is ball in hand ?
			// This line is causing problems

			if ( ((glovePos.vy+GloveBehaviour.radius)>ballPos.vy || (glovePos.vy-GloveBehaviour.radius)<ballPos.vy) && GloveCtrl.throwDelay==0) 
			{
				ballPos.vy=glovePos.vy-(BallBehaviour[BallCtrl.type].radius/2);

				//ballPos.vy=((oldBallPos.vy*(6-Glover.animInfo->frame)) + (ballPos.vy*Glover.animInfo->frame))/6;

				AddToQueue(&Glover,HANDANIM_THROWAIM,YES,NO,4096);
				GloveCtrl.throwDelay=TRUE;
				BallCtrl.ballStopMove=TRUE;
				ActorStartRoll(pBallPSA,0,0);
				gloveVel.vx=0;
				gloveVel.vz=0;

				ballVel.vx=ballVel.vy=ballVel.vz=0;

				GloveCtrl.speed=0;
				GloveCtrl.targetSpeed=0;
			}
			if (GloveCtrl.throwDelay && Glover.animInfo->frame>=6)
			{
				ANIM_SPEED(Glover,0 );
			}

			ballPos.vy=glovePos.vy-(BallBehaviour[BallCtrl.type].radius/2);
			ballPos.vy=((oldBallPos.vy*(6-Glover.animInfo->frame)) + (ballPos.vy*Glover.animInfo->frame))/6;

			if (!aHeld && GloveCtrl.actionTime>5)
			{
				AddToQueue(&Glover,HANDANIM_THROW,NO,NO,4096);
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				GloveCtrl.action=HAND_THROW;
				GloveCtrl.flags=GLOVEMOVE;

				BallCtrl.ballStopMove=FALSE;
				GloveCtrl.ballWithHand=FALSE;
				InputState.throwWhenAble=FALSE;
				InputState.aStateChange=FALSE;
				InputState.aStateHoldTime=FALSE;
				GloveCtrl.actionTime=0;
				GloveCtrl.positionHold=FALSE;
			}
			GloveCtrl.onGround=FALSE;
			break;

		case HAND_THROW:

			CamVars.oldTargetmodel=CamVars.targetmodel;
			CamVars.targetChangeTime=0;
			CamVars.targetChangeFlag=TRUE;

			CamVars.targetmodel=pGlovePSA;
			pGlovePSA->world.rotate.vy=GloveCtrl.direction;
			if (GloveCtrl.onGround || Glover.currentAnimation==HANDANIM_IDLE) GloveCtrl.action=HAND_IDLE;
			break;

		case HAND_SLAM:
			if (Glover.animInfo->frame>=14) ANIM_SPEED(Glover,0 );
			gloveVel.vx=0;
			gloveVel.vz=0;
			if (GloveCtrl.ballHit)
			{
				gloveVel.vy=(20*BallBehaviour[BallCtrl.type].bounce);
				ballVel.vy-=(10*4096);
				GloveCtrl.disableTimer=0;
				//GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.lastAction=NULL;
				GloveCtrl.action=HAND_JUMP;
				GloveCtrl.actionTime=0;
				GloveCtrl.onGround=FALSE;
				GloveCtrl.positionHold=FALSE;
				GloveCtrl.ballWithHand=FALSE;
				GloveCtrl.handOnBall=FALSE;
				GloveCtrl.hitBall=TRUE;

				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;

				CamVars.targetmodel=pGlovePSA;
				GloveCtrl.walkType=NULL;
				if (GloveCtrl.idleAction)
				{
					AddToQueue(&Glover,HANDANIM_JUMP,YES,YES,4096);
					GloveCtrl.idleAction=FALSE;
				}
				else AddToQueue(&Glover,HANDANIM_JUMP,YES,NO,4096);
				break;
			}

			if (GloveCtrl.onGround)
			{
				AddToQueue(&Glover,HANDANIM_SLAM2STAND,NO,NO,4096); // half speed	
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048); // half speed
				GloveCtrl.action=HAND_SLAM2ST;
				GloveCtrl.disableTimer=19;
				CheckForFistHits();
				break;
			}
			break;

		case HAND_SLAM2ST:
			gloveVel.vx=0;
			gloveVel.vz=0;

			if (GloveCtrl.disableTimer || Glover.currentAnimation!=HANDANIM_IDLE) break;
			else GloveCtrl.action=HAND_IDLE;
			break;

		case HAND_JUMP:
			if ( HandOnBall() && gloveVel.vy<0 )
			{
				GloveCtrl.stopXZ=FALSE;
				ballVel.vy-=(10*4096);
				//DB("going stand on ball \n");
				AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048);
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_BALLWALK;
				GloveCtrl.disableTimer=4;
				GloveCtrl.ballWithHand=TRUE;

				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;

				CamVars.targetmodel=pBallPSA;
				GloveCtrl.currentAnim=HANDANIM_IDLE;
				GloveCtrl.handOnBall=TRUE;
				break;
			}			
			if ( GloveCtrl.onGround )
			{
				// NOTE can not implement cling until find height works
				/*if (GloveCtrl.clingFlag)
				{
					GloveCtrl.lastAction=GloveCtrl.action;
					GloveCtrl.action=HAND_CLING;
					AddToQueue(&Glover,HANDANIM_CLING,NO,NO,2048); // half speed
					AddToQueue(&Glover,HANDANIM_CLINGIDLE,YES,YES,2048); // half speed
					GloveCtrl.clingFlag=FALSE;
					GloveCtrl.disableTimer=9;

				}				
				else*/ if (GloveCtrl.speed)
				{
					GloveCtrl.action=HAND_WALK;
					GloveCtrl.walkType=NULL;
				}
				else
				{
					GloveCtrl.action=HAND_IDLE;
					GloveCtrl.walkType=NULL;
					GloveCtrl.lastAction=GloveCtrl.action;
					AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048); // half speed
				}
			}
			else
			{
				if (Glover.animInfo->frame>=6 && GloveCtrl.lastAction!=HAND_JUMP && Glover.currentAnimation==HANDANIM_JUMP) ANIM_SPEED(Glover,0 );
				if (Glover.animInfo->frame>=21 && GloveCtrl.lastAction==HAND_JUMP && Glover.currentAnimation==HANDANIM_SUPERJUMP)
				{
					ANIM_SPEED(Glover,0 );
				}
			}
			break;

		case HAND_PUSH:
			pGlovePSA->world.rotate.vx=0;

			if(!(activeframe & 7) && RANDOM256() > 192)
			{
//				sfxPlay3D(globalFX,SFX_HAND_PUSH_1 + (RANDOM256() & 1),&glovePos);
				sfxPlay3D(globalFX,SFX_HAND2_PUSH1 + (RANDOM256() & 1),&glovePos);
			}
			if (GloveCtrl.actionTime>20)
			{
				if (GloveCtrl.action==HAND_PUSH && GloveCtrl.pushFlag==FALSE)
				{
					AddToQueue(&Glover,HANDANIM_PUSH2IDLE,NO,NO,4096);
					AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
					GloveCtrl.lastAction=GloveCtrl.action;
					//GloveCtrl.action=HAND_IDLE;
					GloveCtrl.disableTimer=10;
					GloveCtrl.actionTime=0;
					GloveCtrl.speed=0;
					GloveCtrl.targetSpeed=0;
				}
			}
			//if (GloveCtrl.disableTimer==1) GloveCtrl.action=HAND_IDLE;
			if (GloveCtrl.actionTime==10)
			{
				GloveCtrl.action=HAND_IDLE;
				//GloveCtrl.speed=0;
				//GloveCtrl.targetSpeed=0;
			}
			break;

		case HAND_WALK:
			// get on ball
			GloveCtrl.ballCollision=TRUE;
			if ( HandOnBall() && gloveVel.vy<0 && !GloveCtrl.onGround)
			{
				GloveCtrl.stopXZ=FALSE;
				ballVel.vy-=(10*4096);
				//DB("going stand on ball \n");
				AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048);
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_BALLWALK;
				GloveCtrl.disableTimer=4;
				GloveCtrl.ballWithHand=TRUE;

				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;

				CamVars.targetmodel=pBallPSA;
				GloveCtrl.currentAnim=HANDANIM_IDLE;
				GloveCtrl.handOnBall=TRUE;
				break;
			}			


			// PUSH ADDED
			if ( GloveCtrl.pushFlag && ActionAllowed(GloveCtrl.action,HAND_PUSH) && !fadeout)
			{
				AddToQueue(&Glover,HANDANIM_IDLE2PUSH,NO,NO,4096);
				AddToQueue(&Glover,HANDANIM_PUSH,YES,YES,4096);
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_PUSH;
			}
			else
			{
				//pGlovePSA->world.rotate.vx=GloveCtrl.speed*3;
				//DB("Glove speed %d \n",GloveCtrl.speed);
				if ( GloveCtrl.speed==0 && GloveCtrl.action!=HAND_IDLE)
				{
					AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048);
					//AddToQueue(&Glover,HANDANIM_GRABBALL,YES,NO,2048);
					GloveCtrl.walkType=FALSE;
					GloveCtrl.lastAction=GloveCtrl.action;
					GloveCtrl.action=HAND_IDLE;
					break;
				}		





				{
					int f;
					static int oldf = 10000;

					f =  Glover.animInfo->frame;
					f += Glover.animInfo->segInfo[Glover.currentAnimation].segStart;

					if(    (oldf < 29 && f >= 29)
						|| (oldf < 76 && f >= 76)
						|| (oldf < 89 && f >= 89)
						)
						sfxPlay3D(globalFX,SFX_HAND_FOOTSTEP_LEFT,&glovePos);
			//			sfxPlay3D(globalFX,SFX_HAND2_HURT1,&glovePos);
					if(    (oldf < 57 && f >= 57)
						|| (oldf < 83 && f >= 83)
						|| (oldf < 95 && f >= 95)
						)

						sfxPlay3D(globalFX,SFX_HAND_FOOTSTEP_RIGHT,&glovePos);
					oldf = f;
				}





				if (GloveCtrl.walkType==HANDWALK_TIPTOE && GloveCtrl.speed < (WALKSPEED+5) ) break;
				if (GloveCtrl.walkType==HANDWALK_WALK && GloveCtrl.speed < (RUNSPEED+5) && GloveCtrl.speed > (WALKSPEED)) break;

				//if ( GloveCtrl.speed<WALKSPEED && (GloveCtrl.action!=HAND_WALK || GloveCtrl.walkType!=HANDWALK_TIPTOE) )
				if ( GloveCtrl.speed<WALKSPEED && GloveCtrl.walkType!=HANDWALK_TIPTOE )
				{
					AddToQueue(&Glover,HANDANIM_TIPTOE,YES,NO,2048);
					GloveCtrl.walkType=HANDWALK_TIPTOE;
//					DB ("tippy toe\n");
//					DB ("Glove speed %d \n",GloveCtrl.speed);
					GloveCtrl.lastAction=GloveCtrl.action;
					GloveCtrl.action=HAND_WALK;
					break;
				}
				//else if ( GloveCtrl.speed<RUNSPEED && GloveCtrl.speed>=WALKSPEED && (GloveCtrl.action!=HAND_WALK || GloveCtrl.walkType!=HANDWALK_WALK) )
				else if ( GloveCtrl.speed<RUNSPEED && GloveCtrl.speed>=WALKSPEED && GloveCtrl.walkType!=HANDWALK_WALK )
				{
					AddToQueue(&Glover,HANDANIM_JOG,YES,NO,2048);
					GloveCtrl.walkType=HANDWALK_WALK;
//					DB ("walk\n");
//					DB ("Glove speed %d \n",GloveCtrl.speed);
					GloveCtrl.lastAction=GloveCtrl.action;
					GloveCtrl.action=HAND_WALK;
					break;
				}
				else if ( GloveCtrl.speed>=RUNSPEED && (GloveCtrl.action!=HAND_WALK || GloveCtrl.walkType!=HANDWALK_RUN) )
				{
					AddToQueue(&Glover,HANDANIM_RUN,YES,NO,2048);
					GloveCtrl.walkType=HANDWALK_RUN;
//					DB ("run\n");
//					DB ("Glove speed %d \n",GloveCtrl.speed);
					GloveCtrl.lastAction=GloveCtrl.action;
					GloveCtrl.action=HAND_WALK;
					break;
				}
			}
			break;
		
		case HAND_SKIDDING:
			pGlovePSA->world.rotate.vx=-GloveCtrl.speed*3;
			//if (GloveCtrl.forceSlide)
			if (GloveCtrl.forceSlideDelay)
			{
				//AddToQueue(&Glover,HANDANIM_SKID,NO,NO,4096);
				if (Glover.animInfo->frame>=4) Glover.animInfo->frame=2;
			}
			//if (Glover.animInfo->num!=HAND_SKIDDING)
			if (Glover.animInfo->num!=HANDANIM_SKID)
			{
				GloveCtrl.lastAction=HAND_SKIDDING;
				AddToQueue(&Glover,HANDANIM_SKID,NO,NO,4096);
				tempVec = glovePos;
				sfxPlay3D(globalFX,SFX_HAND_SKID,&glovePos);
			}

			if (GloveCtrl.speed==0)
			{
				GloveCtrl.action=HAND_IDLE;
				GloveBehaviour.accel=4096*8;
				AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048);
				GloveCtrl.active=TRUE;
			}
			tempVec.vy += 10 * 4096;
			tempVec.vx -= 16 * 4096;
			New_Debris(DEBRIS_DUST,&tempVec,0x201810);

//			if(!(activeframe & 7)
//				sfxPlay3D(globalFX,SFX_HAND_SKID_LOOP,&glovePos);

			break;			 
		
		case HAND_IDLE:

			if ( HandOnBall() && gloveVel.vy<=0 && !GloveCtrl.onGround)
			{
				DB ("idle to ballwalk\n");
				GloveCtrl.stopXZ=FALSE;

				//ballVel.vy-=(10*4096);
				
				ballVel.vy+=(gloveVel.vy);

				//DB("going stand on ball \n");
				AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048);
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_BALLWALK;
				GloveCtrl.disableTimer=4;
				GloveCtrl.ballWithHand=TRUE;

				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;

				CamVars.targetmodel=pBallPSA;
				GloveCtrl.currentAnim=HANDANIM_IDLE;
				GloveCtrl.handOnBall=TRUE;
				break;
			}			


			if (GloveCtrl.speed) 
			{
				GloveCtrl.action=HAND_WALK;
				GloveCtrl.idleTimer=0;
			}
			else GloveCtrl.idleTimer++;
			//if (GloveCtrl.idleTimer==-20 && GloveCtrl.idleSelection==1) GloveCtrl.idleAction=NULL;
			//if (GloveCtrl.idleTimer==-10 && GloveCtrl.idleSelection==2) GloveCtrl.idleAction=NULL;
			//if (GloveCtrl.idleTimer==-70 && GloveCtrl.idleSelection==0) GloveCtrl.idleAction=NULL;

			if ( Glover.currentAnimation==HANDANIM_IDLE ) GloveCtrl.idleAction=NULL;

			if (GloveCtrl.idleTimer==120)
			{
				if (GloveCtrl.idleSelection==0)
				{
					GloveCtrl.idleAction=HANDANIM_BORED;
					AddToQueue(&Glover,HANDANIM_GETDOWN,NO,NO,4096);
					AddToQueue(&Glover,HANDANIM_BORED,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_BORED,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_BORED,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_BORED,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_GETUP,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,4096);
				}
				else if (GloveCtrl.idleSelection==1)
				{
					GloveCtrl.idleAction=HANDANIM_STRETCH;
					AddToQueue(&Glover,HANDANIM_IDLE2STRETCH,NO,NO,4096);
					AddToQueue(&Glover,HANDANIM_STRETCH,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_STRETCH,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_STRETCH,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_STRETCH2IDLE,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,4096);
					//AddToQueue(&Glover,HANDANIM_RIDEDENNIS,YES,YES,1024);
				}
				else if (GloveCtrl.idleSelection==2)
				{
					GloveCtrl.idleAction=HANDANIM_WAVE;
					AddToQueue(&Glover,HANDANIM_IDLE2WAVE,NO,NO,4096);
					AddToQueue(&Glover,HANDANIM_WAVE,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_WAVE,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_IDLE2WAVE,NO,YES,-4096);
					AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,4096);
					//AddToQueue(&Glover,HANDANIM_RIDEDENNIS,YES,YES,1024);
				}
				GloveCtrl.idleSelection++;
				if (GloveCtrl.idleSelection==3) GloveCtrl.idleSelection=0;
				GloveCtrl.idleTimer=0;
			}
			break;

		case HAND_LOCATE:
			// do point direction
			angle=calc_angle( (ballPos.vx-glovePos.vx)/4096,(ballPos.vz-glovePos.vz)/4096 );
			angle=angle&4095;
			angle1=GloveCtrl.direction;
			// need to make this smooth
			angle1=(angle1+2048)&4095;
			targetAngle = findShortestAngle(angle,angle1);
			if ( abs(targetAngle)>(ROTATESPEED/2) )
			{
				if (targetAngle>0) GloveCtrl.direction+=(ROTATESPEED/2);
				else GloveCtrl.direction-=(ROTATESPEED/2);
			}
			else GloveCtrl.direction+=targetAngle;
			// now do point height
			tempVec.vx=(glovePos.vx-ballPos.vx)/4096;
			tempVec.vz=(glovePos.vz-ballPos.vz)/4096;
			tempVec.vy=0;
			dist=Magnitude(&tempVec);
			angle=calc_angle( (ballPos.vy-glovePos.vy)/4096,dist );
			pGlovePSA->world.rotate.vx =(angle&4095);

			if (Glover.currentAnimation==HANDANIM_POINTCYCLE)
			{
				dist/=5;
				if (dist<=25) temp1=6144;
				else if (dist>200) temp1=3072;
				else
				{
					dist=dist-50;
					dist=dist*20;
					temp1=6144-dist;
				}
				ANIM_SPEED( Glover,temp1 );
			}
			break;

		case HAND_JOINED:
			GloveCtrl.idleTimer++;
			if (GloveCtrl.idleTimer>=GloveCtrl.blinkTime && !GloveCtrl.ballIdleAction)
			{
				GloveCtrl.idleTimer=0;
				GloveCtrl.blinkTime=RANDOM256();
				AddToQueue(&Glover,HANDANIM_ROLLBLINK,NO,NO,4096);
				AddToQueue(&Glover,HANDANIM_ROLLBLINK,YES,YES,0);
			}
			if (BallCtrl.ballSpeed>2048)
			{
				GloveCtrl.actionTime=20;
				if (GloveCtrl.ballIdleAction==BALLPEDDLE)
				{
					GloveCtrl.ballIdleAction=BALLPEDDLESTOP;
					AddToQueue(&Glover,HANDANIM_ROLL2PEDDLE,NO,NO,-2048);
					AddToQueue(&Glover,HANDANIM_ROLLBLINK,YES,YES,0);
				}
				if (GloveCtrl.ballIdleAction==BALLONFINGER)
				{
					GloveCtrl.ballIdleAction=BALLONFINGERSTOP;
					AddToQueue(&Glover,HANDANIM_ROLL2PEDDLE,NO,NO,-4096);
					AddToQueue(&Glover,HANDANIM_ROLLBLINK,YES,YES,0);
				}
			}

			if ( GloveCtrl.actionTime>200 && BallCtrl.ballOnGround )
			{
				if (GloveCtrl.ballIdleAction==BALLONFINGERSTOP)
				{
					GloveCtrl.ballIdleAction=BALLPEDDLE;
					GloveCtrl.actionTime=20;
					AddToQueue(&Glover,HANDANIM_ROLL2PEDDLE,NO,NO,4096);
					AddToQueue(&Glover,HANDANIM_PEDDLE,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_PEDDLE,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_PEDDLE,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_PEDDLE,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_PEDDLE,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_PEDDLE,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_ROLL2PEDDLE,NO,YES,-4096);
					AddToQueue(&Glover,HANDANIM_ROLLBLINK,YES,YES,0);
				}
				else
				{
					GloveCtrl.ballIdleAction=BALLONFINGER;
					GloveCtrl.actionTime=20;

					AddToQueue(&Glover,HANDANIM_ROLL2SPIN,NO,NO,4096);
					AddToQueue(&Glover,HANDANIM_SPIN,NO,YES,1024);
					//AddToQueue(&Glover,HANDANIM_SPIN2ROLL,NO,YES,4096);
					AddToQueue(&Glover,HANDANIM_ROLL2SPIN,NO,YES,-4096);
					AddToQueue(&Glover,HANDANIM_ROLLBLINK,YES,YES,0);
				}
			}

			if ( (GloveCtrl.lastAction==HAND_PREWHACK) && (Glover.animInfo->frame==1) ) 
			{
				//AddToQueue(&Glover,HANDANIM_WHACKAIM,NO,NO,0);
				AddToQueue(&Glover,HANDANIM_ROLLBLINK,NO,NO,0);
			}
			if (Glover.animInfo->frame>=18) ANIM_SPEED( Glover,0 );
			if (Glover.animInfo->length==5 && Glover.animInfo->frame>=4) ANIM_SPEED( Glover,0 );
			
			if (ballVel.vy<JOINEDFALLRATE)
			{
				AddToQueue(&Glover,HANDANIM_ROLL2BOUNCE,NO,NO,2048);
				AddToQueue(&Glover,HANDANIM_BOUNCE,NO,YES,0);
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_BOUNCE;
			}

			break;

		case HAND_SNATCH:
			// stop ball 

			//removeSnow();
			gloveVel.vx=0;
			gloveVel.vy=0;
			gloveVel.vz=0;
			GloveCtrl.targetSpeed=0;
			GloveCtrl.speed=0;
			if (GloveCtrl.disableTimer==12) // first frame 
			{
				ballVel.vx=0;
				ballVel.vy=0;
				ballVel.vz=0;
				// point hand at ball
				angle=calc_angle( (ballPos.vx-glovePos.vx)/4096,(ballPos.vz-glovePos.vz)/4096 );
				angle=angle&4095;
				angle1=GloveCtrl.direction;
				angle1=(angle1+2048)&4095;	
				targetAngle = findShortestAngle(angle,angle1);
				GloveCtrl.direction+=targetAngle;
				//GloveCtrl.action=HAND_JOINED;
				GloveCtrl.flags=GLOVEMOVE;
				COPYVECTOR(&JoinGlovePos, &glovePos);
				COPYVECTOR(&JoinBallPos, &ballPos);
				DB("first grab frame\n");
			}
			else if (GloveCtrl.disableTimer)
			{
				if (GloveCtrl.disableTimer >6) // move to ball cycle
				{
//					DB ("move out frame\n");
					temp=(4096*(17-GloveCtrl.disableTimer)+6)/12;	// get percentage of distance
					tempVec.vx=( (JoinGlovePos.vx-ballPos.vx) *temp)/4096;
					tempVec.vy=( (JoinGlovePos.vy-ballPos.vy) *temp)/4096;
					tempVec.vz=( (JoinGlovePos.vz-ballPos.vz) *temp)/4096;
					glovePos.vx=JoinGlovePos.vx-(tempVec.vx);
					glovePos.vy=JoinGlovePos.vy-(tempVec.vy);
					glovePos.vz=JoinGlovePos.vz-(tempVec.vz);
				}
				else 
				{
//					Db ("move in frame\n");
					//CamVars.targetmodel=pBallPSA;

					temp=(4096*(GloveCtrl.disableTimer)+6)/12;	// get percentage of distance
					tempVec.vx=( (JoinBallPos.vx-JoinGlovePos.vx) *temp)/4096;
					tempVec.vy=( (JoinBallPos.vy-JoinGlovePos.vy) *temp)/4096;
					tempVec.vz=( (JoinBallPos.vz-JoinGlovePos.vz) *temp)/4096;

					glovePos.vx=JoinGlovePos.vx+(tempVec.vx);
					glovePos.vy=JoinGlovePos.vy+(tempVec.vy);
					glovePos.vz=JoinGlovePos.vz+(tempVec.vz);

					//tempVec.vz=4096*10;
					tempVec.vz = BallBehaviour[BallCtrl.type].radius/2;
					tempVec.vy=0;
					tempVec.vx=0;
					RotateVector2D(&tempVec, &tempVec,GloveCtrl.direction );

					ballPos.vx=glovePos.vx - tempVec.vx;//+gloveVel.vx;
					ballPos.vy=glovePos.vy;
					ballPos.vz=glovePos.vz - tempVec.vz;//+gloveVel.vz;
				}
			}
			else
			{
				GloveCtrl.action=HAND_JOINED;

				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;

				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;

				CamVars.targetmodel=pBallPSA;
				ANIM_SPEED( Glover,0 );
				GloveCtrl.onGround=FALSE;
				GloveCtrl.positionHold=FALSE;
			}
			break;
		case HAND_RELEASE:
			CamVars.oldTargetmodel=CamVars.targetmodel;
			CamVars.targetChangeTime=0;
			CamVars.targetChangeFlag=TRUE;

			CamVars.targetmodel=pGlovePSA;
			if (GloveCtrl.disableTimer)
			{
				tempVec.vz = 4096*5;
				tempVec.vy=0;
				tempVec.vx=0;
				RotateVector2D(&tempVec, &tempVec,GloveCtrl.direction );
				glovePos.vx += tempVec.vx;//+gloveVel.vx;
				glovePos.vz += tempVec.vz;//+gloveVel.vz;
			}
			else
			{
				GloveCtrl.action=HAND_IDLE;
				GloveCtrl.walkType=NULL;
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.ballWithHand=FALSE;
				AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048); // half speed
			}
			break;
		case HAND_BOUNCE:

			CamVars.oldTargetmodel=CamVars.targetmodel;
			CamVars.targetChangeTime=0;
			CamVars.targetChangeFlag=TRUE;

			CamVars.targetmodel=pGlovePSA;
			gloveVel.vy=(gloveVel.vy*(BallBehaviour[BallCtrl.type].drag+3500)/2)/4096;

			if (GloveCtrl.hitBall==TRUE && abs(ballVel.vy)<RESTSPEED && !BallCtrl.ballOnCeiling)
			{
				BallCtrl.bounceHoldFlag=FALSE;
				GloveCtrl.onGround=FALSE;
				GloveCtrl.positionHold=FALSE;
				if (BallCtrl.ballOnGround)
				{
					//ballVel.vy+=(8*gravity*BallBehaviour[BallCtrl.type].bounce)/4096;
					ballVel.vy+=(8*GRAVITY*BallBehaviour[BallCtrl.type].bounce)/4096;
					GloveCtrl.hitBall=FALSE;
					GloveCtrl.disableTimer=2;
					ANIM_SPEED( Glover,4096 );
					AddToQueue(&Glover,HANDANIM_BOUNCE,NO,YES,0);
				}
				else
				{
					//ballVel.vy-=15*gravity;
					ballVel.vy-=15*GRAVITY;
					GloveCtrl.hitBall=FALSE;
					ANIM_SPEED( Glover,4096 );
					AddToQueue(&Glover,HANDANIM_BOUNCE,NO,YES,0);
				}

				sfxPlay3D(globalFX,SFX_HAND_BOUNCETAP_1,&glovePos);
			}

			// this bit below not right
			//ballPos.vy+=ballVel.vy;
			//if (ballVel.vy>0) ballPos.vy-=ballVel.vy;
			//else ballPos.vy+=ballVel.vy;

			COPYVECTOR(&tempVec, &ballPos);
			COPYVECTOR(&tempVecS, &ballVel);

			//ballVel.vy-=BallBehaviour[BallCtrl.type].gravity;
			//ADDVECTOR(&ballPos, &ballPos, &ballVel);
			//ballPos.vy-=(ballVel.vy*2);

			//collboxCheckSphere(&ballColl);
			UpdateBallPos();
			//if (ballVel.vy>0) ballPos.vy-=ballVel.vy;
			//else ballPos.vy+=ballVel.vy;

			//if ( (ballVel.vy>0 && (glovePos.vy >= (ballPos.vy- (BallBehaviour[BallCtrl.type].radius-GloveBehaviour.radius/3 )  ) )) || GloveCtrl.onGround)
			if ( ( (glovePos.vy >= (ballPos.vy- (BallBehaviour[BallCtrl.type].radius-GloveBehaviour.radius/3 )  ) )) || GloveCtrl.onGround)
			{
				if (gloveVel.vy>0) gloveVel.vy=0;
				if(GloveCtrl.shockFlag==1)
				{
					DB("SHOCK_BOUNCEBALL ");
					if (gameInfo.keyRecordFlag!=PLAYBACK) SHOCK_BOUNCEBALL;
					GloveCtrl.shockFlag++;
				}

				if (BallCtrl.ballOnGround && abs(ballVel.vy)<RESTSPEED )
				{
					tempVect.vx=glovePos.vx-ballPos.vx;
					tempVect.vy=glovePos.vy-ballPos.vy;
					tempVect.vz=glovePos.vz-ballPos.vz;
					
					GloveCtrl.lastAction=GloveCtrl.action;
					GloveCtrl.actionTime=0;
					GloveCtrl.action=HAND_JOINED;
					AddToQueue(&Glover,HANDANIM_BOUNCE2ROLL,NO,NO,2048);

					CamVars.oldTargetmodel=CamVars.targetmodel;
					CamVars.targetChangeTime=0;
					CamVars.targetChangeFlag=TRUE;

					CamVars.targetmodel=pBallPSA;

					COPYVECTOR(&GloveCtrl.move, &tempVect);
				}
				else
				{
					glovePos.vy=ballPos.vy-(((BallBehaviour[BallCtrl.type].radius-GloveBehaviour.radius/3 )) );
					if (ballVel.vy>0) gloveVel.vy=ballVel.vy;
					GloveCtrl.shockFlag++;
				}
			}
			else
				GloveCtrl.shockFlag=0;


			if (glovePos.vy>(ballPos.vy+(10*4096)))
			{
				DB ("hand below ball ?\n");
				CRASH;
			}

			COPYVECTOR(&ballPos, &tempVec );
			COPYVECTOR(&ballVel, &tempVecS );

			//ballPos.vy-=ballVel.vy;
			//if (ballVel.vy>0) ballPos.vy+=ballVel.vy;
			//else ballPos.vy-=ballVel.vy;

			glovePos.vx = ballPos.vx;
			glovePos.vz = ballPos.vz;

			gloveVel.vx = ballVel.vx;
			gloveVel.vz = ballVel.vz;

			break;
	}
}


/*************************************************************************************************/
/*************************************************************************************************/
/*************************************************************************************************/

int		GrabBallAllowed()
{
	// Will need lots more checks when ball control finished
	//DB ("grab routine\n");
	//if (BallCtrl.inWind) DB ("ball in wind\n");
	//if (GloveCtrl.inWind) DB ("hand in wind\n");
	//if (GloveCtrl.action==HAND_ROTOR) return(FALSE);

	//if (GloveCtrl.lastAction==HAND_CASTSPELL){printf ("test test\n"); return(FALSE);}

	//if ( (BallCtrl.inWind || BallCtrl.shallowWater) && GloveCtrl.action!=HAND_THROW && GloveCtrl.action!=HAND_WHACK) return (TRUE);

	//printf ("action time %d\n",GloveCtrl.actionTime);

	if (!BallCtrl.enabled || GloveCtrl.action==HAND_CATCH)  return(FALSE);

	//if ( (BallCtrl.inWind || BallCtrl.shallowWater) /*&& GloveCtrl.actionTime>10*/ ) return (TRUE);

	if ( !GloveCtrl.onGround || BallCtrl.onConveyer) return(FALSE);

	if (!BallCtrl.ballOnGround && !BallCtrl.shallowWater) return(FALSE);

	if(GloveCtrl.insideBubble)
		return FALSE;

	if ( (BallCtrl.inWind || BallCtrl.shallowWater) /*&& GloveCtrl.actionTime>10*/ ) return (TRUE);

	if ( (GloveCtrl.inWaterFlag!=NOWHERENEARWATER && !BallCtrl.shallowWater) || BallCtrl.inside_bugle || !BallCtrl.enabled || !GloveCtrl.enabled)
		return FALSE;	// you grab it & mount it in one movement, I think

	if (enemy_has_ball) return FALSE;
	if (GloveCtrl.onGround/* && GloveCtrl.actionTime>10*/) return TRUE;

	else return FALSE;
}

/*************************************************************************************************/
/*************************************************************************************************/
/*************************************************************************************************/

int		CatchBallAllowed()
{

	VECTOR	tempVec;
	LONG	temp,ydist;

	if (level==CARNIVALBOSS) return(FALSE);

	if (enemy_has_ball || !BallCtrl.enabled || !GloveCtrl.enabled || BallCtrl.onConveyer || GloveCtrl.action==HAND_SNATCH)
		return FALSE;

	if (BallCtrl.ballOnGround && abs(glovePos.vy-ballPos.vy) > (10*4096) ) // are the ball and glove on different platforms?
	{
		//DB ("no catch?\n");
		return (FALSE);
	}

	if(GloveCtrl.insideBubble)
		return FALSE;

	if ( (ballPos.vy-(5*4096)) >glovePos.vy) return (FALSE);

	if (BallCtrl.inWaterFlag==INWATER || BallCtrl.inWaterFlag==BELOWWATER)
	{
		if (BallCtrl.type==BALL_MODE_BOWLING || BallCtrl.type==BALL_MODE_BEARING) ;
		else return(FALSE);
	}
	tempVec.vx=ballPos.vx-glovePos.vx;
	//tempVec.vy=ballPos.vy-glovePos.vy;
	tempVec.vy=0;
	tempVec.vz=ballPos.vz-glovePos.vz;
	temp=Magnitude(&tempVec);

	if	(GloveCtrl.onGround)// && !BallCtrl.ballOnGround)
	{
		if ( BallCtrl.justHitFlag ) 
		{
			tempVec.vx=BallCtrl.ballPosWhenHit.vx-glovePos.vx;
			tempVec.vy=0;
			tempVec.vz=BallCtrl.ballPosWhenHit.vz-glovePos.vz;
			temp=Magnitude(&tempVec);
			if ( temp< GloveBehaviour.radius )return(TRUE);
		}
		ydist=abs(ballPos.vy-glovePos.vy);
		if ( (temp< (GloveBehaviour.radius+BallBehaviour[BallCtrl.type].radius) ) && (ydist<(20*4096) || ballVel.vy<0) )return(TRUE);
	}
	return(FALSE);
}

/*************************************************************************************************/
/*************************************************************************************************/
/*************************************************************************************************/

int		HandOnBall()
{
VECTOR	tempV;
LONG	temp;

	if (enemy_has_ball || !BallCtrl.enabled || !GloveCtrl.enabled)
		return FALSE;	// don't let glover walk on the ball if it's inside bugle

	if (GloveCtrl.ballHit && BallCtrl.inWaterFlag==INWATER) return (TRUE);

	tempV.vx=abs (glovePos.vx-ballPos.vx);
	tempV.vz=abs (glovePos.vz-ballPos.vz);
	tempV.vy=abs ( (glovePos.vy+GloveBehaviour.radius)-ballPos.vy );

//		glovePos.vy=ballPos.vy-(( (GloveBehaviour.radius+BallBehaviour[BallCtrl.type].radius)*4000)/4296);

	temp=BallBehaviour[BallCtrl.type].radius;

	if ( (tempV.vx<temp) && (tempV.vy<temp) && (tempV.vz<temp) ) return (TRUE);
	else return (FALSE);
}

/*************************************************************************************************/
/*************************************************************************************************/
/*************************************************************************************************/

//	Also handles glove taking damage (falling getting hit ect)

COLLDATA	handFrontProbe;
VECTOR		handFrontProbePos;

	
void	HandCollision()
{
VECTOR	tempVec,tempVec1;
LONG	temp,temp1,temp2,temp3,trampoline,test;
LONG	gloveHeight,preVel,postVel;

	if(!GloveCtrl.enabled)
		return;

	//GloveCtrl.onLava=FALSE;

	handFrontProbe.pPos=&handFrontProbePos;
	handFrontProbe.physics=&GloveBehaviour;

	// work out position of probe		

	GloveCtrl.direction&=4095;
	handFrontProbePos.vx=glovePos.vx;
	handFrontProbePos.vy=glovePos.vy;
	handFrontProbePos.vz=glovePos.vz;

	handFrontProbePos.vz-=(rcos(GloveCtrl.direction)*FRONTPROBEDIST);
	handFrontProbePos.vx-=(rsin(GloveCtrl.direction)*FRONTPROBEDIST);

	temp1=gloveVel.vy;

	TIMER_START(TIMER_COLLISION);

	//if (!GloveCtrl.spellCastOnBall) GloveCtrl.ballHit=HandToBallCollision();
	//else if (GloveCtrl.action!=HAND_CASTSPELL) GloveCtrl.spellCastOnBall=FALSE;

	GloveCtrl.ballHit=HandToBallCollision();
	if (GloveCtrl.action!=HAND_CASTSPELL) GloveCtrl.spellCastOnBall=FALSE;

	tempVec.vx=gloveVel.vx;
	tempVec.vy=0;
	tempVec.vz=gloveVel.vz;

	if (!GloveCtrl.hurtFlag && !GloveCtrl.deathType && GloveCtrl.action!=HAND_SLAM)
		CheckForNmeHitsGlove();

	// Check for fall too fast 
	// removed cos it caused zombiefication to glove in wind vents
	/*
	if (temp1<DIEVEL && (GloveCtrl.deathType!=DEADFROMFALL && GloveCtrl.deathType!=DEADFROMFALLOFF) && level!=PIRATESBONUS)
	{
		GloveCtrl.hurtFlag=TRUE;
		GloveCtrl.deathType=DEADFROMFALL;
		DB("setting for die from fall\n");

	}
	*/
	// Check for fall off level
	if ( glovePos.vy>=world_base_y && (GloveCtrl.deathType!=DEADFROMFALLOFF && GloveCtrl.deathType!=DEADFROMBALLFALLOFF) )
	{
		//gameInfo.mode=GAMEMODE_RESTART;
		GloveCtrl.hurtFlag=TRUE;
		GloveCtrl.deathType=DEADFROMFALLOFF;
		DB("glove fell off world\n");
		sfxPlay(globalFX,SFX_HAND_DIE_1);

// It works better here that at "HandKillGlove"
		if(gameInfo.levelType==BONUS_LEVEL)
		{
			if(!gameCtrl.dropOutFlag)
			{
				MenuFadeOut();
				gameCtrl.dropOutFlag=GAME_FAILEDBONUS;
				NextLevelBasics();
			}
		}


	}
	if ( ballPos.vy>=world_base_y && (GloveCtrl.deathType!=DEADFROMFALLOFF && GloveCtrl.deathType!=DEADFROMBALLFALLOFF && GloveCtrl.deathTypeBall!=DEADFROMBALLBURST) )
	{
		//if (GloveCtrl.action!=SPECIALACTION && BallCtrl.health>1 && !GloveCtrl.onGround)
		//{
		//	ballVel.vy=0;
		//	ballPos.vy=world_base_y;
		//}

		if (GloveCtrl.action!=SPECIALACTION && BallCtrl.health>1 && GloveCtrl.onGround)
		{
			GloveCtrl.actionTime=0;
			GloveCtrl.action=SPECIALACTION;
			GloveCtrl.preDelay=16;
			gloveVel.vx=0;
			gloveVel.vy=0;
			gloveVel.vz=0;
			AddToQueue(&Glover,HANDANIM_CLICKFINGER,NO,NO,4096);

			//removeSnow();
			BallChange.changeOn=0;
			BallCtrl.onSnow=0;
			BallCtrl.snowTexChange=0;
			BallCtrl.snowAddition=0;


			BallCtrl.type=BALL_MODE_NORMAL;
			pBallPSA=pOldBall;
			BallBehaviour[0].radius=(19*4096*NORMAL_SCALE)*1;
			BallBehaviour[1].radius=(19*4096*NORMAL_SCALE)*1.4;
			BallBehaviour[2].radius=(19*4096*NORMAL_SCALE)*0.6;
			BallBehaviour[3].radius=(19*4096*NORMAL_SCALE)*0.6;
			BallBehaviour[4].radius=(19*4096*NORMAL_SCALE)*2.5;
			BallBehaviour[5].radius=(19*4096*NORMAL_SCALE)*0.9;
			BallBehaviour[6].radius=(19*4096*NORMAL_SCALE)*1;
			ChangeBall(&pBallPSA->world,ballTex[BallCtrl.type]);
			ballColl.physics=&BallBehaviour[0];
			ballColl.physicsModel=BALL_MODE_NORMAL;
		}
		//else if (GloveCtrl.action!=SPECIALACTION)
		else if (BallCtrl.health<=1)
		{
			GloveCtrl.hurtFlagBall=TRUE;
			GloveCtrl.deathTypeBall=DEADFROMBALLBURST;
		}

/*		if (GloveCtrl.actionTime==17)
		{
			VECTOR pos;
			GloveCtrl.action=HAND_IDLE;
			pos = glovePos;
			pos.vy -= 50<<12;
			BallCtrl.health--;
			BallCtrl.hurt=TRUE;
			if (BallCtrl.health==0)
			{
				GloveCtrl.hurtFlagBall=TRUE;
				GloveCtrl.deathTypeBall=DEADFROMBALLBURST;
			}
			//BallCtrl.type=BALL_MODE_NORMAL;
			ballPlaceAt(&pos);
		}
*/
	}
	if (GloveCtrl.action==SPECIALACTION && GloveCtrl.actionTime==17)
	{
		VECTOR pos;
		GloveCtrl.action=HAND_IDLE;
		pos = glovePos;
		pos.vy -= 50<<12;
		BallCtrl.health--;
		BallCtrl.hurt=TRUE;
		if (BallCtrl.health==0)
		{
			GloveCtrl.hurtFlagBall=TRUE;
			GloveCtrl.deathTypeBall=DEADFROMBALLBURST;
		}
		//BallCtrl.type=BALL_MODE_NORMAL;
		ballPlaceAt(&pos);
	}


	temp3=abs(gloveVel.vy);

	gloveVel.vy=(gloveVel.vy*990)/1000;

	trampoline=gloveVel.vy;
	gloveVel.vy=-gloveVel.vy;
	
	GloveCtrl.onCeiling=FALSE;
	preVel=gloveVel.vy;
	test=temp=collboxCheckSphere(&gloveColl);
	postVel=gloveVel.vy;
	//printf ("pre vel %d post vel %d \n",preVel,postVel);
	if ( (preVel<0 && postVel>=0) || GloveCtrl.onCeiling )
	{
		GloveCtrl.onCeiling=TRUE;
		if (postVel<=0) gloveVel.vy=gravity;
		//printf ("glove hit ceiling\n");
	}


	//if (GloveCtrl.onLava) GloveCtrl.positionHold=FALSE;

	//if (level==CARNIVALBOSS)
	//{
/*		if (gloveColl.nHitPlats && !BodgeCtrl.hitPlat)
		{
			BodgeCtrl.carnivalPlat=gloveColl.hitPlats[0].pPlatform;
			BodgeCtrl.hitPlat=TRUE;
		}
		else if (!gloveColl.nHitPlats && BodgeCtrl.hitPlat && (GloveCtrl.action==HAND_SNATCH || (GloveCtrl.action==HAND_RELEASE && GloveCtrl.lastAction==HAND_JOINED) || GloveCtrl.action==HAND_CASTSPELL) )
		{
			gloveColl.nHitPlats=1;
			gloveColl.hitPlats[0].pPlatform=BodgeCtrl.carnivalPlat;
		}
		else if (!gloveColl.nHitPlats)
		{
			gloveColl.hitPlats[0].pPlatform=NULL;
		}
*/	//}

	if ( (GloveCtrl.action==HAND_CASTSPELL && GloveCtrl.lastAction==HAND_JOINED) || GloveCtrl.action==HAND_SNATCH || GloveCtrl.action==HAND_RELEASE || GloveCtrl.action==HAND_CATCH)
	{
		if (gloveColl.nHitPlats && !BodgeCtrl.hitPlat)
		{
			BodgeCtrl.carnivalPlat=gloveColl.hitPlats[0].pPlatform;
			BodgeCtrl.hitPlat=TRUE;
		}
		else if (BodgeCtrl.hitPlat && !gloveColl.nHitPlats)
		{
			gloveColl.nHitPlats=1;
			gloveColl.hitPlats[0].pPlatform=BodgeCtrl.carnivalPlat;
		}
	}
	else
	{
		BodgeCtrl.carnivalPlat=NULL;
		BodgeCtrl.hitPlat=FALSE;
	}


		//(DYNCOLLBOX *)(ballColl.hitPlats[0].pPlatform)=ptr;

	gloveVel.vy=-gloveVel.vy;

	if (GloveCtrl.onTrampoline && temp)
	{
		gloveVel.vy=-trampoline;

		if (gloveVel.vy>(3*4096) && GloveCtrl.action!=HAND_SLAM && GloveCtrl.action!=HAND_JOINED && GloveCtrl.action!=HAND_BOUNCE)
		{
			//glovePos.vy-=gloveVel.vy;

			GloveCtrl.lastAction=NULL;
			GloveCtrl.action=HAND_JUMP;
			//GloveCtrl.onGround=FALSE;
			//GloveCtrl.ballWithHand=FALSE;
			//GloveCtrl.handOnBall=FALSE;
			//GloveCtrl.walkType=NULL;
			GloveCtrl.onTrampoline=FALSE;
			GloveCtrl.onGround=TRUE;
			AddToQueue(&Glover,HANDANIM_JUMP,NO,NO,4096);
			sfxPlay3D(globalFX,SFX_HAND2_JUMP1 + (RANDOM256() & 3),&glovePos);

			//if (InputState.bHeld) DB ("jump you little twat\n");

			if (InputState.bHeld)
			{
				GloveCtrl.lastAction=NULL;
				GloveCtrl.action=HAND_JUMP;
				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;
				//DB ("glove vel %d\n",gloveVel.vy);
				//gloveVel.vy+=(JUMPHEIGHT+JUMPHEIGHT/2);
				gloveVel.vy+=JUMPHEIGHT/2;
				GloveCtrl.onTrampoline=FALSE;
				//DB ("glove vel %d\n",gloveVel.vy);
				//GloveCtrl.onGround=FALSE;
				GloveCtrl.ballWithHand=FALSE;
				GloveCtrl.handOnBall=FALSE;
				temp=test=0;
			}
		}
	}

	//DB ("glove vel %d\n",gloveVel.vy);

	if ( GloveCtrl.action==HAND_ROTOR )
	{
		if (trampoline!=gloveVel.vy)
		{
			if (trampoline>0)
				gloveVel.vy=-4096*7;
			else if (trampoline<0)
				gloveVel.vy=0;
		}	
	}


	if ( temp && GloveCtrl.onGround ) objectPush ( temp );
	else GloveCtrl.pushFlag=FALSE;

	if ( temp )
	{
		temp2=abs(gloveVel.vy);
		temp=temp2/10;

		if ( (temp3>=(temp2-temp)) && (temp3<=(temp2+temp)) ) GloveCtrl.onGround=FALSE;
		else if ( getHeightAt(glovePos.vx,glovePos.vy,glovePos.vz) > gloveColl.radius*2)  GloveCtrl.onGround=FALSE;
		else
		{
			tempVec1.vx=-gloveVel.vx;
			tempVec1.vz=-gloveVel.vz;
			// Fall hurt
			/*
			if (temp3<(HURTVEL) && GloveCtrl.deathType==NULL && GloveCtrl.action!=HAND_SLAM && GloveCtrl.onTrampoline==FALSE)
			{
				GloveCtrl.hurtFlag=TRUE;
				GloveCtrl.deathType=HURTFALL;
				DB ("setting for hurt from fall\n");
			}
			*/
			if ( GloveCtrl.action!=HAND_ROTOR ) gloveVel.vy=0;
			gloveHeight=getHeightAt( glovePos.vx,glovePos.vy,glovePos.vz);
			// Put cling check here
			if ( (GloveCtrl.frontProbeHeight< (GloveBehaviour.radius+GloveBehaviour.radius/2 )) && (gloveHeight>GloveBehaviour.radius*2) )
			{			
				//DB ("cling here but first some fundemental routines have to work\n");
				GloveCtrl.clingFlag=TRUE;
			}
			GloveCtrl.onGround=TRUE;
			GloveCtrl.stopXZ=FALSE;
		}
		//else GloveCtrl.onGround=FALSE;
	}
 	else GloveCtrl.onGround=FALSE;

	if (GloveCtrl.onTrampoline && test) GloveCtrl.onGround=TRUE;

	tempVec.vx=glovePos.vx/4096;
	tempVec.vy=glovePos.vy/4096;
	tempVec.vz=glovePos.vz/4096;

//	GloveCtrl.inWaterFlag=loadlndGetWaterInfo(&tempVec, gloveColl.physics->radius/4096, &GloveCtrl.waterHeight);
	{
		int flags;
		if(gloveVel.vx > 4096 || gloveVel.vx <-4096 || gloveVel.vz >4096 || gloveVel.vz <-4096)
			flags = GloveCtrl.inWaterFlag + SPLASHY_MOVING;
		else
			flags = GloveCtrl.inWaterFlag;

		if(GloveCtrl.onWater)
			flags |= SPLASHY_WATERY;

		if(GloveCtrl.ballWithHand)
				flags |= SPLASHY_JUSTINFO;

		flags |= SPLASHY_BUBBLES;

		GloveCtrl.inWaterFlag = waterDoSplashiness(&tempVec,gloveColl.physics->radius/4096, flags, &GloveCtrl.waterHeight);
	}

	if (GloveCtrl.positionHold) GloveCtrl.onGround=TRUE;

#ifdef	BOUNCEFIX
	if (GloveCtrl.onGround && GloveCtrl.action==HAND_BOUNCE)
	{
		GloveCtrl.onIce=FALSE;
		GloveCtrl.slideData.vx=0;
		GloveCtrl.slideData.vy=0;
		GloveCtrl.slideData.vz=0;
		gloveColl.physics->gravity=gravity;
		GloveCtrl.lastAction=GloveCtrl.action;
		GloveCtrl.action=HAND_IDLE;

		//sfxPlay3D(globalFX,SFX_HAND2_JUMP1 + (RANDOM256() & 3),&glovePos);
		GloveCtrl.walkType=NULL;
		//AddToQueue(&Glover,HANDANIM_RELEASE,NO,NO,2730);
		AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,2048);
		pGlovePSA->world.rotate.vx=0;
		pGlovePSA->world.rotate.vy=0;
		pGlovePSA->world.rotate.vz=0;

		//glovePos.vy-=4096*10;

		gloveVel.vx=0;
		gloveVel.vy=0;
		gloveVel.vz=0;
		//GloveCtrl.disableTimer=9;
		GloveCtrl.handOnBall=FALSE;
		GloveCtrl.ballWithHand=FALSE;
		zFlipFlop=TRUE;
		GloveCtrl.positionHold=FALSE;
		GloveCtrl.onGround=FALSE;
	}
#endif

	TIMER_STOP(TIMER_COLLISION);
}

/*************************************************************************************************/
/*************************************************************************************************/
/*************************************************************************************************/

void	objectPush(long nHits )
{
VECTOR	gloveMove,actualMove;
long	result,test,test1;

	if (GloveCtrl.onIce || GloveCtrl.onConveyer || !GloveCtrl.onGround || GloveCtrl.speed<20 || GloveCtrl.onConveyer || GloveCtrl.inWind)
	{
		GloveCtrl.pushFlag=FALSE;
		return;
	}

	gloveMove.vz=-(rcos(GloveCtrl.direction)*GloveCtrl.speed)/16;
	gloveMove.vx=-(rsin(GloveCtrl.direction)*GloveCtrl.speed)/16;
	gloveMove.vy=0;

	test=Magnitude(&gloveMove);
	if ( abs(oldGlovePos.vy-glovePos.vy) > test/5 )	// stop him entering push mode on steep slops
	{
		GloveCtrl.pushFlag=FALSE;
		return;
	}


	actualMove.vx=oldGlovePos.vx-glovePos.vx;
	actualMove.vz=oldGlovePos.vz-glovePos.vz;
	actualMove.vy=0;

	test1=Magnitude(&actualMove);

	if (test1<10) test1=10;
	result=(test/(test1/10));

	if ( GloveCtrl.pushFlag==FALSE && result>=45 )	// over push threshold
	{
		GloveCtrl.pushFlag=TRUE;
		// need to work out facing
		gloveMove.vx+=actualMove.vx;
		gloveMove.vz+=actualMove.vz;
	
		GloveCtrl.pushDirection=calc_angle( gloveMove.vx,gloveMove.vz );
		//GloveCtrl.pushDirection=calc_angle( gloveMove.vz,gloveMove.vx );

		GloveCtrl.pushDirection=(GloveCtrl.pushDirection+2048)&4095;

		test= findShortestAngle(GloveCtrl.pushDirection,GloveCtrl.direction);
		if ( abs(test) > 300 ) GloveCtrl.pushFlag=FALSE;
		//angle=calc_angle( (ballPos.vx-glovePos.vx)/4096,(ballPos.vz-glovePos.vz)/4096 );
		//angle=(angle+2048)&4095;
	}

	if ( GloveCtrl.pushFlag==TRUE && result<30 )		// under push threshold
		GloveCtrl.pushFlag=FALSE;

}


/*************************************************************************************************/
/*************************************************************************************************/
/*************************************************************************************************/

ULONG	HandToBallCollision(void)
{
LONG	handBallDist;
LONG	distCheck;
VECTOR	temp;

	if (GloveCtrl.ballWithHand || GloveCtrl.handOnBall || !GloveCtrl.ballCollision || !BallCtrl.enabled || !GloveCtrl.enabled/* || BallCtrl.inWaterFlag==INWATER*/)
		return FALSE;

	distCheck=ballColl.radius+gloveColl.radius;
	temp.vx=glovePos.vx-ballPos.vx;
	temp.vy=glovePos.vy-ballPos.vy;
	temp.vz=glovePos.vz-ballPos.vz;

	handBallDist=Magnitude(&temp);

	//if (BallCtrl.inWaterFlag==INWATER)
	//{
	//	distCheck=distCheck*2;	// make easyer to get on ball in water
	//}



	if (distCheck>handBallDist) // hand and ball have collided
	{
		if (GloveCtrl.spellCastTimer) // do the hand instead
		{
			MakeUnit(&temp);
			SCALEVECTOR( &temp , (distCheck-handBallDist)+4096 );

			glovePos.vx+=temp.vx;
			glovePos.vy+=temp.vy;
			glovePos.vz+=temp.vz;
			//printf ("move hand\n");
			return(TRUE);
		}
		else
		{
			//printf ("move ball\n");
			if (BallCtrl.inWaterFlag==INWATER)
			{
				MakeUnit(&temp);
				SCALEVECTOR( &temp , (distCheck-handBallDist) );

				ballPos.vx-=temp.vx;
				ballPos.vy-=temp.vy;
				ballPos.vz-=temp.vz;

				return(TRUE);
			}
			else
			{
				if (GloveCtrl.action==HAND_SLAM || GloveCtrl.action==HAND_JUMP)
				{
					ballColl.preVel.vx=ballColl.pVel->vx;
					ballColl.preVel.vy=ballColl.pVel->vy-(4096*16);
					ballColl.preVel.vz=ballColl.pVel->vz;
					BallApplySquash();
					return(TRUE);
				}

				MakeUnit(&temp);
				SCALEVECTOR(&temp,(handBallDist-distCheck));
				ballVel.vx+=temp.vx;
				ballVel.vy+=temp.vy;
				ballVel.vz+=temp.vz;
				return(TRUE);
			}
		}
	}
	return(FALSE);
}
/**************************************************************************************/


void handRender()
{
long	restore;	// something in here desroys glove rotations an it did'nt use to
	if(!GloveCtrl.enabled)
		return;

	if (!CamVars.showGlove)
		return;
	if (GloveCtrl.insideSnowBall==TRUE)
	{
		glovePos.vx=GloveCtrl.attachedBoulder->pos.vx;
		glovePos.vy=GloveCtrl.attachedBoulder->pos.vy;
		glovePos.vz=GloveCtrl.attachedBoulder->pos.vz;
		if (GloveCtrl.attachedBoulder->time<=1)
		{
			GloveCtrl.insideSnowBall=FALSE;
			GloveCtrl.attachedBoulder=NULL;
			GloveCtrl.onGround=FALSE;
			GloveCtrl.positionHold=FALSE;
		}
		return;
	}
	restore=pGlovePSA->world.rotate.vy;

  	gte_SetRotMatrix(&GsWSMATRIX);
  	gte_SetTransMatrix(&GsWSMATRIX);
	if(!RadiusCheck4096(&glovePos,gloveColl.radius,3000))
	{
		animate(&Glover);
		return;
	}

	if (GloveCtrl.action==HAND_ROTOR && pRotorPSA)
	{
		pRotorPSA->world.rotate.vx=0;//pGlovePSA->world.rotate.vx;
		//pRotorPSA->world.rotate.vy=pGlovePSA->world.rotate.vy;
		pRotorPSA->world.rotate.vy=(pRotorPSA->world.rotate.vy+GloveCtrl.rotorSpinSpeed)&4095;

		pRotorPSA->world.rotate.vz=0;//pGlovePSA->world.rotate.vz;

		pRotorPSA->position.vx=pGlovePSA->position.vx;
		pRotorPSA->position.vy=pGlovePSA->position.vy;
		pRotorPSA->position.vz=pGlovePSA->position.vz;

		pGlovePSA->position.vy+=GloveBehaviour.radius/4096;

		objectSetAnimation(pRotorPSA, 0);
		objectDraw(pRotorPSA);

		pGlovePSA->world.rotate.vy-=1024;
	}

	if (!GloveCtrl.flash)
	{
		int frame;
		frame = animate(&Glover);
		//DB ("frame = %d \n",frame);

		if(GloveCtrl.ballWithHand)
		{
			objectSetAnimation(pGlovePSA, frame);
			objectDraw(pGlovePSA);
		}
		else
		{
			objectSetAnimation(pGlovePSA, frame);
			objectDrawWithShadow(pGlovePSA, 8,6,0);
		}
	}
	else animate(&Glover); // Stop glove dropping frames

	if (GloveCtrl.action==HAND_ROTOR)
	{
		pGlovePSA->world.rotate.vy+=1024;
		pGlovePSA->position.vy-=GloveBehaviour.radius/4096;
	}
	pGlovePSA->world.rotate.vy=restore;
}




// ========================= Hand powerups ==================================
// (printing stuff is now back in effects)

// type is an "enemy" type

int handpower_duration = 0;
int handpower_timer = 0;
int handpower_type = 0;

// called from the pickup handling code on collision

void handGivePlayerPower(int type, int time)
{
// Get rid of any existing power nicely
	if(handpower_timer!=0 && handpower_type != type)
	{
		handpower_timer = 1;
		handPowerUpdate();
	}

// Because gaining the rotorblades snaps you out of whatever you're doing
	if(GloveCtrl.deathType && type == SPELL_ROTORBLADES)
		return;


// start the test-tube going
	handpower_timer = time;
	handpower_duration = time;
	handpower_type = type;

	switch(type)
	{
		case SPELL_DEATH:
		case SPELL_FROGGY:
			DB ("hand frogged\n");
			break;
		case SPELL_SUCTION:
//			DB ("sticky fingers\n");
//			if (GloveCtrl.action!=HAND_SUCTION) GloveCtrl.lastAction=GloveCtrl.action;
//			GloveCtrl.action=HAND_SUCTION;
			break;
			
		case SPELL_HERCULES:
		case SPELL_SPEEDUP:
			break;
		case SPELL_ROTORBLADES:
			DB ("rotor spell 1\n");
			GloveCtrl.rotorSpinSpeed=256;
			if (GloveCtrl.action!=HAND_ROTOR) GloveCtrl.lastAction=GloveCtrl.action;
			GloveCtrl.actionTime=0;
			GloveCtrl.action=HAND_ROTOR;
			GloveCtrl.ballCollision=FALSE;
			gloveColl.physics->gravity=gravity/8;
			break;

		case SPELL_BALL_BOWLING:
		case SPELL_BALL_POWER:
		case SPELL_BALL_BEARING:
		case SPELL_BALL_BEACH:
		case SPELL_BALL_SNOW:
		case SPELL_BALL_CRYSTAL:
			break;
		case SPELL_BOOMERANG:
			break;

		case SPELL_VANISH:
			if (GloveCtrl.action==HAND_ROTOR)
			{
				//GloveCtrl.lastAction=GloveCtrl.action;
				//GloveCtrl.action=HAND_IDLE;		// Will have to deal with hand joined as some point (like now)
				if (GloveCtrl.lastAction==HAND_JOINED && !enemy_has_ball)
				{
					GloveCtrl.action=HAND_JOINED;
					GloveCtrl.disableTimer=10;
					//DB ("setting for joined\n");
				}
				else
				{
					GloveCtrl.action=HAND_IDLE;
					AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
					//DB ("setting for idle\n");
				}
				//AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				gloveColl.physics->gravity=gravity;
			}
			break;
		case SPELL_FROGGIFY:
			if (!BallCtrl.cancerFlag)
			{
				BallCtrl.cancerFlag=START;
				BallCtrl.cancerActiveTime=300;
			}
			break;
	}
}


/*************************************************************************************/
void handPowerUpdate()
{
	if(!handpower_timer)
		return;
	handpower_timer--;
	if(!handpower_timer)
	{
		if (handpower_type==SPELL_BOOMERANG)
		{
			BallCtrl.boomerangOn=FALSE;
			handpower_timer = 0;
			handpower_duration = 0;
			handpower_type = 0;
		}


		handpower_type = 0;	// because the platform code, for eg, just checks spell type rather than the timer too

		if (GloveCtrl.action==HAND_ROTOR)
		{
			pGlovePSA->world.rotate.vx=0;
			pGlovePSA->world.rotate.vy=0;
			pGlovePSA->world.rotate.vz=0;

			if (GloveCtrl.lastAction==HAND_JOINED && !enemy_has_ball)
			{
				GloveCtrl.action=HAND_JOINED;
				DB ("setting for joined 1\n");
				gloveColl.physics->gravity=gravity;
				GloveCtrl.actionTime=20;
				GloveCtrl.action=HAND_JOINED;
				AddToQueue(&Glover,HANDANIM_SPIN2ROLL,NO,NO,4096);
				AddToQueue(&Glover,HANDANIM_WHACKAIM,NO,YES,0);
				GloveCtrl.walkType=NULL;
				GloveCtrl.ballWithHand=TRUE;
				GloveCtrl.ballCollision=TRUE;
				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;
			}
			else
			{	
				GloveCtrl.action=HAND_IDLE;
				//AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				DB ("setting for idle 2\n");
				gloveColl.physics->gravity=gravity;
				GloveCtrl.ballCollision=TRUE;
				CamVars.targetmodel=pGlovePSA;
				AddToQueue(&Glover,HANDANIM_GETUP,YES,NO,4096);
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
			}
		}
// remove the power
	}
	//AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
// update the orbiter, & have it drop sparkly things

}


/******************************************************************************************/
void handMountDenis(ENEMYPOS *nme)
{
//	DB ("nothing yet\n");
	if ( GloveCtrl.action==HAND_HOPPING ) return;

	DennisVel.vx=0;
	DennisVel.vy=0;
	DennisVel.vz=0;

	GloveCtrl.mount=nme;

	DennisColl.nBoxes=numCollBoxes;
	//gloveColl.bounce=0;//4096;
	DennisColl.radius=(60*4096*NORMAL_SCALE);
	DennisColl.pCollBox=collBox;
	DennisColl.pVel=&DennisVel;
	DennisColl.pPos=&DennisPos;

	DennisPos.vx=GloveCtrl.mount->pos.vx;
	DennisPos.vy=GloveCtrl.mount->pos.vy;
	DennisPos.vz=GloveCtrl.mount->pos.vz;

	DennisColl.oldPos = DennisPos;

	//DennisPos.vy-=170*4096;

	DennisColl.physics=&DennisBehaviour;
	GloveCtrl.dennisBounceCount=0;

	GloveCtrl.lastAction=GloveCtrl.action;
	GloveCtrl.action=HAND_HOPPING;	//?
	GloveCtrl.mount->psa->world.rotate.vy=GloveCtrl.direction;
	AddToQueue(&Glover,HANDANIM_RIDEDENNIS,YES,NO,2048);

	AddToQueue(&nme->anim,NMEANIM_IDLE,YES,YES,2048);	// anim,numberloop,queue,speed
	//objectSetAnimation(psa, animate(&enemy->anim));
}

/******************************************************************************************/

//void handMountSwish(ENEMYPOS *nme)
//{
//	DB ("nothing yet\n");#
/*	if ( GloveCtrl.action==HAND_SWISH ) return;

	DB ("Start of mount swish\n");
	SwishVel.vx=0;
	SwishVel.vy=0;
	SwishVel.vz=0;

	//SwishPos.vy-=50*4096;

	GloveCtrl.mount=nme;

	GloveVel.vx=GloveVel.vy=GloveVel.vz=0;

	SwishColl.nBoxes=numCollBoxes;
	//gloveColl.bounce=0;//4096;
	SwishColl.radius=(60*4096*NORMAL_SCALE);
	SwishColl.pCollBox=collBox;
	SwishColl.pVel=&SwishVel;
	SwishColl.pPos=&SwishPos;
	SwishColl.physics=&SwishBehaviour;

	GloveCtrl.lastAction=GloveCtrl.action;
	GloveCtrl.action=HAND_SWISH;
	GloveCtrl.mount->psa->world.rotate.vy=GloveCtrl.direction;
	AddToQueue(&Glover,HANDANIM_GRABSWISH,NO,NO,2048);
	AddToQueue(&Glover,HANDANIM_GRABSWISH,NO,YES,-1);

	AddToQueue(&GloveCtrl.mount->anim,NMEANIM_WALK,YES,NO,4096);

	CamVars.oldTargetmodel=CamVars.targetmodel;
	CamVars.targetChangeTime=0;
	CamVars.targetChangeFlag=TRUE;


	CamVars.targetmodel=GloveCtrl.mount->psa;
	GloveCtrl.mount->pos.vy-=10*4096;

	SwishPos = nme->pos;
	SwishColl.oldPos = SwishPos;

	//pGlovePSA->globalscale.vy=-pGlovePSA->globalscale.vy;
	//SwishPos.vx=GloveCtrl.mount->psa->position.vx*4096;
	//SwishPos.vy=GloveCtrl.mount->psa->position.vy*4096;
	//SwishPos.vz=GloveCtrl.mount->psa->position.vz*4096;
	*/
//}

/****************************************************************************************/
// if the glove's pushing or bouncing the ball, disconnect it
void DisconnectGloveFromBall(int when)
{
	VECTOR tempVec;

	InputState.aStateHoldTime=FALSE;
	InputState.aStateChange=FALSE;

	InputState.bStateHoldTime=FALSE;
	InputState.bStateChange=FALSE;

	InputState.cStateHoldTime=FALSE;
	InputState.cStateChange=FALSE;

	GloveCtrl.flags=GLOVEMOVE;
	BallCtrl.ballStopMove=FALSE;
	GloveCtrl.ballWithHand=FALSE;
	InputState.throwWhenAble=FALSE;
	GloveCtrl.throwDelay=0;

	//printf ("disconecting hand from ball \n");

	switch(GloveCtrl.action)
	{
		case HAND_JOINED:
			if(!(when & DISCONNECT_WHEN_JOINED))
				return;
			break;

		case HAND_BOUNCE:
			if(!(when & DISCONNECT_WHEN_BOUNCING))
				return;
			break;

		case HAND_BALLWALK:
			if(!(when & DISCONNECT_WHEN_WALKINGON))
				return;
			break;
	}

	sfxPlay3D(globalFX,SFX_HAND_HURT_1 + (RANDOM256() % 3),&glovePos);	// "hand" hurts are the "oof" ones

	if(when & DISCONNECT_GENTLY)
	{
		switch(GloveCtrl.action)
		{
			case HAND_ROTOR:
				DB ("disconnect when in rotor mode\n");
				GloveCtrl.onIce=FALSE;
				GloveCtrl.slideData.vx=0;
				GloveCtrl.slideData.vy=0;
				GloveCtrl.slideData.vz=0;
				GloveCtrl.ballCollision=TRUE;
				if (GloveCtrl.lastAction!=HAND_JOINED) break;
				GloveCtrl.lastAction=HAND_IDLE;
				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;
				CamVars.targetmodel=pGlovePSA;
				break;


			case HAND_JOINED:
			case HAND_BOUNCE:

				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_RELEASE;
				GloveCtrl.walkType=NULL;
				AddToQueue(&Glover,HANDANIM_RELEASE,NO,NO,2048);
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;

				glovePos.vy-=4096*10;

				gloveVel.vx=0;
				gloveVel.vy=0;
				gloveVel.vz=0;
				GloveCtrl.disableTimer=12;
				GloveCtrl.handOnBall=FALSE;

				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;
				CamVars.targetmodel=pGlovePSA;

				break;

			case HAND_BALLWALK:
				if (GloveCtrl.disableTimer) break;
				GloveCtrl.lastAction=GloveCtrl.action;
				GloveCtrl.action=HAND_RELEASE;
				GloveCtrl.walkType=NULL;
				//AddToQueue(&Glover,HANDANIM_RELEASE,NO,NO,2048);
				AddToQueue(&Glover,HANDANIM_JUMP,NO,NO,2048);
				AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
				GloveCtrl.disableTimer=12;
				GloveCtrl.handOnBall=FALSE;
				pGlovePSA->world.rotate.vx=0;
				pGlovePSA->world.rotate.vz=0;
				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;
				CamVars.targetmodel=pGlovePSA;

				break;
			default:
				GloveCtrl.handOnBall=FALSE;
				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;
				CamVars.targetmodel=pGlovePSA;

				break;
		}
		GloveCtrl.ballWithHand = FALSE;
	}
	else
	{
		if (GloveCtrl.action==HAND_ROTOR)
		{
			DB ("disconnect when in rotor mode\n");
			GloveCtrl.onIce=FALSE;
			GloveCtrl.slideData.vx=0;
			GloveCtrl.slideData.vy=0;
			GloveCtrl.slideData.vz=0;
			GloveCtrl.ballCollision=TRUE;
			if (GloveCtrl.lastAction==HAND_JOINED)
			{
				GloveCtrl.lastAction=HAND_IDLE;
				CamVars.oldTargetmodel=CamVars.targetmodel;
				CamVars.targetChangeTime=0;
				CamVars.targetChangeFlag=TRUE;
				CamVars.targetmodel=pGlovePSA;
			}
		}
		else
		{
			pGlovePSA->world.rotate.vx=0;
			pGlovePSA->world.rotate.vy=0;
			pGlovePSA->world.rotate.vz=0;

			CamVars.targetmodel=pGlovePSA;

			tempVec.vz=HURTJUMPSPEED;
			tempVec.vx=0;
			tempVec.vy=0;
			RotateVector2D(&tempVec, &tempVec,GloveCtrl.direction );
			gloveVel.vx=tempVec.vx;
			gloveVel.vy=HURTJUMPSPEED;
			gloveVel.vz=tempVec.vz;

			GloveCtrl.disableTimer=12;

			GloveCtrl.handOnBall=FALSE;
			GloveCtrl.ballWithHand=FALSE;
		//			zFlipFlop=TRUE;
			GloveCtrl.action=HAND_FALLING;
			GloveCtrl.onGround=FALSE;	// coz otherwise he won't even start to go upwards
			GloveCtrl.deathType=HURTFALL;
			GloveCtrl.hurtFlag=0;
			//AddToQueue(&Glover,HANDANIM_FALL,YES,NO,4096);
			AddToQueue(&Glover,HANDANIM_HURT,NO,NO,4096);
			AddToQueue(&Glover,HANDANIM_IDLE,YES,YES,2048);
		}
	}
}
/***************************************************************************************/
void handComeOutOfHoop(VECTOR *pos, int ya)
{
	handpower_timer = 0;
	handpower_type = 0;

	gloveVel.vx = 0;
	gloveVel.vy = HURTJUMPSPEED;
	gloveVel.vz = 0;

	GloveCtrl.direction = ya;
	GloveCtrl.disableTimer=12;

	GloveCtrl.handOnBall=FALSE;
	GloveCtrl.ballWithHand=FALSE;

	GloveCtrl.action=HAND_IDLE;
	GloveCtrl.lastAction=HAND_IDLE;
	GloveCtrl.onGround=FALSE;	// coz otherwise he won't even start to go upwards
	AddToQueue(&Glover,HANDANIM_IDLE,YES,NO,4096);

	glovePos = gloveColl.oldPos = *pos;

	GloveCtrl.enabled = TRUE;
	GloveCtrl.stopXZ=FALSE;

	InputState.aStateHoldTime=FALSE;
	InputState.aStateChange=FALSE;

	InputState.bStateHoldTime=FALSE;
	InputState.bStateChange=FALSE;

	InputState.cStateHoldTime=FALSE;
	InputState.cStateChange=FALSE;

	GloveCtrl.flags=GLOVEMOVE;
	BallCtrl.ballStopMove=FALSE;
	GloveCtrl.ballWithHand=FALSE;
	InputState.throwWhenAble=FALSE;
	GloveCtrl.throwDelay=0;
	GloveCtrl.disableTimer=30;

	GloveCtrl.onIce=FALSE;
	GloveCtrl.onIceFlag=FALSE;

	ZEROVECTOR(&GloveCtrl.slideData);
	ZEROVECTOR(&GloveCtrl.iceData);

	if(GloveCtrl.attachedBoulder)
	{
		GloveCtrl.attachedBoulder->time=0;
	}
	GloveCtrl.insideSnowBall=FALSE;
	GloveCtrl.positionHold=FALSE;

	GloveBehaviour.accel=4096*8;

	if (GloveCtrl.health==0)
	{
		GloveCtrl.health=GloveCtrl.maxHealth;
		GloveCtrl.healthChange=TRUE;
	}
}

/****************************************************************************************/
// it's assumed that your "connected-to-ball" status is preserved
void handGoThroughTeleport(VECTOR *pos, int ya)
{
	if(GloveCtrl.handOnBall || GloveCtrl.ballWithHand)
	{
		VECTOR dvec;

		BallCtrl.ballOnGround=FALSE;

		dvec.vx = pos->vx - ballPos.vx;
		dvec.vy = pos->vy - ballColl.radius - ballPos.vy;
		dvec.vz = pos->vz - ballPos.vz;

		BallCtrl.enabled = TRUE;

		glovePos.vx += dvec.vx;
		glovePos.vy += dvec.vy;
		glovePos.vz += dvec.vz;
		gloveColl.oldPos = glovePos;

		ballPos.vx += dvec.vx;
		ballPos.vy += dvec.vy;
		ballPos.vz += dvec.vz;

		ballPlaceAt(&ballPos);


		JoinGlovePos.vx += dvec.vx;
		JoinGlovePos.vy += dvec.vy;
		JoinGlovePos.vz += dvec.vz;
		JoinBallPos.vx  += dvec.vx;
		JoinBallPos.vy  += dvec.vy;
		JoinBallPos.vz  += dvec.vz;

		GloveCtrl.enabled = TRUE;
		GloveCtrl.padDisableTimer = 10;	// prevent problems in the event of sudden camera reversal
	}
	else
	{
		gloveVel.vx = 0;
		gloveVel.vy = 0;
		gloveVel.vz = 0;

		GloveCtrl.direction = ya;
		GloveCtrl.disableTimer=12;

		GloveCtrl.onGround=FALSE;
		glovePos = gloveColl.oldPos = *pos;
	}
	GloveCtrl.stopXZ=FALSE;
	GloveBehaviour.accel=4096*8;
}
/*****************************************************************************************/
/*
void handGoThroughTeleport(VECTOR *pos, int ya)
{
	if(GloveCtrl.handOnBall || GloveCtrl.ballWithHand)
	{
		VECTOR dvec;

		BallCtrl.ballOnGround=FALSE;

		dvec.vx = pos->vx - ballPos.vx;
		dvec.vy = pos->vy - ballColl.radius - ballPos.vy;
		dvec.vz = pos->vz - ballPos.vz;

		ballVel.vx = 0;
		ballVel.vy = 0;
		ballVel.vz = 0;

		ballColl.oldPos = ballPos;
		BallCtrl.enabled = TRUE;

		glovePos.vx += dvec.vx;
		glovePos.vy += dvec.vy;
		glovePos.vz += dvec.vz;

		ballPos.vx += dvec.vx;
		ballPos.vy += dvec.vy;
		ballPos.vz += dvec.vz;

		JoinGlovePos.vx += dvec.vx;
		JoinGlovePos.vy += dvec.vy;
		JoinGlovePos.vz += dvec.vz;
		JoinBallPos.vx  += dvec.vx;
		JoinBallPos.vy  += dvec.vy;
		JoinBallPos.vz  += dvec.vz;

		GloveCtrl.enabled = TRUE;
	}
	else
	{
		gloveVel.vx = 0;
		gloveVel.vy = 0;
		gloveVel.vz = 0;

		GloveCtrl.direction = ya;
		GloveCtrl.disableTimer=12;

		GloveCtrl.onGround=FALSE;
		glovePos = gloveColl.oldPos = *pos;
	}
	GloveCtrl.stopXZ=FALSE;
}
*/
#define ACTOR_UPDATE_SET 0
#define ACTOR_UPDATE_ADD 1

//void actorUpdatePosition(VECTOR *actorPos, int x, int y, int z, int flags) 
//{
//
//}
//void actorUpdateAllPositions(void)
//{
//
//}

/*********************************************************************************************/
// This is a debug function remove from final game
void	GloveStatusReport()
{

//	printf ("Object positions \n");
//	VSync(0);
//	printf ("Glove Position  X %d Y %d Z %d \n",(int)glovePos.vx/4096,(int)glovePos.vy/4096,(int)glovePos.vz/4096);
//	printf ("Ball Position   X %d Y %d Z %d \n",(int)ballPos.vx/4096,(int)ballPos.vy/4096,(int)ballPos.vz/4096);
//	printf ("Camera look Pos X %d Y %d Z %d \n",(int)CamVars.camera.vrx,(int)CamVars.camera.vry,(int)CamVars.camera.vrz);
//	printf ("Camera Position X %d Y %d Z %d \n",(int)CamVars.camera.vpx,(int)CamVars.camera.vpy,(int)CamVars.camera.vpz);

/*	printf ("GLOVE CONTROL STATUS\n");
	VSync(0);
	printf ("radius 		%d\n",(int)GloveCtrl.radius);
	printf ("Height 		%d\n",(int)GloveCtrl.height);
	printf ("Fprobe Height	%d\n",(int)GloveCtrl.frontProbeHeight);
	printf ("move Vector	%d %d %d\n",(int)GloveCtrl.move.vx,(int)GloveCtrl.move.vy,(int)GloveCtrl.move.vz);

	printf ("slideData Vector	%d %d %d\n",(int)GloveCtrl.slideData.vx,(int)GloveCtrl.slideData.vy,(int)GloveCtrl.slideData.vz);
	printf ("slieNormal Vector	%d %d %d\n",(int)GloveCtrl.slideNormal.vx,(int)GloveCtrl.slideNormal.vy,(int)GloveCtrl.slideNormal.vz);
	printf ("ice data Vector	%d %d %d\n",(int)GloveCtrl.iceData.vx,(int)GloveCtrl.iceData.vy,(int)GloveCtrl.iceData.vz);
	printf ("free Var		%d\n",(int)GloveCtrl.freeVar);
	printf ("water height	%d\n",(int)GloveCtrl.waterHeight);
	printf ("speed			%d\n",(int)GloveCtrl.speed);
	printf ("old speed 		%d\n",(int)GloveCtrl.oldSpeed);
	printf ("target speed	%d\n",(int)GloveCtrl.targetSpeed);
	printf ("direction		%d\n",(int)GloveCtrl.direction);
	printf ("push direction	%d\n",(int)GloveCtrl.pushDirection);
	printf ("action			%d\n",(int)GloveCtrl.action);
	printf ("last action 	%d\n",(int)GloveCtrl.lastAction);
	printf ("current anim 	%d\n",(int)GloveCtrl.currentAnim);
	printf ("active		 	%d\n",(int)GloveCtrl.active);
	printf ("disabletimer 	%d\n",(int)GloveCtrl.disableTimer);
	printf ("throwDelay 	%d\n",(int)GloveCtrl.throwDelay);
	printf ("preDelay	 	%d\n",(int)GloveCtrl.preDelay);
	printf ("idleTimer	 	%d\n",(int)GloveCtrl.idleTimer);
	printf ("actionTime	 	%d\n",(int)GloveCtrl.actionTime);
	printf ("walkType	 	%d\n",(int)GloveCtrl.walkType);
	printf ("onGround	 	%d\n",(int)GloveCtrl.onGround);
	printf ("ballWithHand 	%d\n",(int)GloveCtrl.ballWithHand);
	printf ("hitBall	 	%d\n",(int)GloveCtrl.ballWithHand);
	printf ("handOnBall	 	%d\n",(int)GloveCtrl.handOnBall);
	printf ("dennisBounceCount 	%d\n",(int)GloveCtrl.dennisBounceCount);
	printf ("tipNumber	 	%d\n",(int)GloveCtrl.tipNumber);
	printf ("dennisJumpHit 	%d\n",(int)GloveCtrl.dennisJumpHit);
	printf ("dennisJump 	%d\n",(int)GloveCtrl.dennisJump);
	printf ("dennisOnGround	%d\n",(int)GloveCtrl.dennisOnGround);
	printf ("ballCollision	%d\n",(int)GloveCtrl.ballCollision);
	printf ("flags			%d\n",(int)GloveCtrl.flags);
	printf ("stopXZ			%d\n",(int)GloveCtrl.stopXZ);
	printf ("idleAction		%d\n",(int)GloveCtrl.idleAction);
	printf ("idleSelection	%d\n",(int)GloveCtrl.idleSelection);
	printf ("frontProbeHit	%d\n",(int)GloveCtrl.frontProbeHit);
	printf ("ballHit		%d\n",(int)GloveCtrl.ballHit);
	printf ("tipFlag		%d\n",(int)GloveCtrl.tipFlag);
	printf ("clingFlag		%d\n",(int)GloveCtrl.clingFlag);
	printf ("pushFlag		%d\n",(int)GloveCtrl.pushFlag);
	printf ("lives			%d\n",(int)GloveCtrl.lives);
	printf ("health			%d\n",(int)GloveCtrl.health);
	printf ("hurtFlag 		%d\n",(int)GloveCtrl.hurtFlag);
	printf ("hurtFlagBall	%d\n",(int)GloveCtrl.hurtFlagBall);
	printf ("dieCount		%d\n",(int)GloveCtrl.dieCount);
	printf ("flash			%d\n",(int)GloveCtrl.flash);
	printf ("deathType		%d\n",(int)GloveCtrl.deathType);
	printf ("deathTypeBall	%d\n",(int)GloveCtrl.deathTypeBall);
	printf ("shockFlag		%d\n",(int)GloveCtrl.shockFlag);
	printf ("inWaterFlag	%d\n",(int)GloveCtrl.inWaterFlag);
	printf ("enabled		%d\n",(int)GloveCtrl.enabled);
	printf ("forceSlide		%d\n",(int)GloveCtrl.forceSlide);
	printf ("forceSlideDelay%d\n",(int)GloveCtrl.forceSlideDelay);
	printf ("onIce			%d\n",(int)GloveCtrl.onIce);
	printf ("onIceFlag		%d\n",(int)GloveCtrl.onIceFlag);
	printf ("onConveyer		%d\n",(int)GloveCtrl.onConveyer);
	printf ("conveyerTimer	%d\n",(int)GloveCtrl.conveyerTimer);
	printf ("onTrampoline	%d\n",(int)GloveCtrl.onTrampoline);
	printf ("jumpPressed	%d\n",(int)GloveCtrl.jumpPressed);
	printf ("onWater		%d\n",(int)GloveCtrl.onWater);
	printf ("onSnow			%d\n",(int)GloveCtrl.onSnow);
	printf ("insideBubble	%d\n",(int)GloveCtrl.insideBubble);
	printf ("padIn			%d\n",(int)GloveCtrl.padIn);
	printf ("padOld			%d\n",(int)GloveCtrl.padOld);
	printf ("padInDB		%d\n",(int)GloveCtrl.padInDB);
*/
}

////////////////////////////////////////////////////////////////////////////////////////////

#define	INER_RING_SPEED		10
#define	MID_RING_SPEED		9
#define	OUTER_RING_SPEED	8



CANNONCTRL	CannonCtrl;

void	HandOnCannon(void)
{
	SHORT	leftRight=0,upDown=0;
	USHORT	padIn;
	VECTOR	tempVec;
	SHORT	height,len,tempCos,tempSin,height1;
	UBYTE	buffer[10];

	if (!GloveCtrl.padDisableTimer)
	{
		padIn=pad[0];
		leftRight=(nleftx[0]);
		upDown=-(nlefty[0]);
	}
	else
	{
		padIn=0;
		leftRight=0;
		upDown=0;
	}

	UpdateOverlays();

	GloveCtrl.enabled=FALSE;
	BallCtrl.enabled=FALSE;

	if (Glover.currentAnimation!=HANDANIM_RIDEDENNIS) 	AddToQueue(&Glover,HANDANIM_RIDEDENNIS,YES,NO,4096);


	CamVars.targetmodel=pCannonPSA;
	pRing01PSA->world.rotate.vy+=INER_RING_SPEED;
	pRing02PSA->world.rotate.vy-=MID_RING_SPEED;
	pRing03PSA->world.rotate.vy+=OUTER_RING_SPEED;

	pCannonPSA->world.rotate.vy=pPod01PSA->world.rotate.vy=CannonCtrl.direction;
	pCannonPSA->world.rotate.vx=CannonCtrl.elevation;

	if (upDown)
	{
		if (upDown<0 && CannonCtrl.elevation>-386) CannonCtrl.elevation+=(upDown/128);
		if (upDown>0 && CannonCtrl.elevation<16) CannonCtrl.elevation+=(upDown/128);
	}

	CannonCtrl.lastDirection=CannonCtrl.camDirection;
	if (leftRight)
	{
		CannonCtrl.direction+=(leftRight/256);
		CannonCtrl.direction=(CannonCtrl.direction&4095);
	}
	CannonCtrl.camDirection=CannonCtrl.camDirection&4095;
	CannonCtrl.direction=CannonCtrl.direction&4095;
	CannonCtrl.lastDirection=CannonCtrl.lastDirection&4095;
	CannonCtrl.camDirection=CannonCtrl.lastDirection+(findShortestAngle(CannonCtrl.direction,CannonCtrl.lastDirection)/6);

	if (CannonCtrl.justFiredFlag)
	{
		tempVec.vz=4*4096+(CannonCtrl.justFiredFlag*8192);
		muzzelFlash();
		CannonCtrl.justFiredFlag--;
	}
	else tempVec.vz=4*4096;

	tempVec.vx=0;
	RotateVector2D(&tempVec,&tempVec,CannonCtrl.direction);
	pCannonPSA->position.vx=tempVec.vx/4096;
	pCannonPSA->position.vz=tempVec.vz/4096;
	height=-23;
	tempCos=rcos(CannonCtrl.elevation-350);
	tempSin=rsin(CannonCtrl.elevation-350);	
	height1 = ( tempCos * height )/4096;
	len = ( tempSin * height )/4096;

	tempVec.vz=len*4096;
	tempVec.vx=0;
	RotateVector2D(&tempVec,&tempVec,CannonCtrl.direction);


	if (padIn&PAD_CROSS  && !CannonCtrl.nextFireCount &&!CannonCtrl.endOfBonusFlag)
	{
		addBullet();
		CannonCtrl.justFiredFlag=10;
		CannonCtrl.nextFireCount=10;
		CannonCtrl.shotsFired++;
	}
	if ( CannonCtrl.nextFireCount ) CannonCtrl.nextFireCount--;
	//updateBullets();

	if ( CannonCtrl.endOfBonusFlag )
	{
		DB ("level done\n");
		gameCtrl.dropOutFlag=GAME_COMPLETED;
		NextLevelBasics();
	}


	//NEW_TEXT(300, 250,255,255,255,255, 3277,3277, FALSE, CannonCtrl.shotsFired, TRUE);
	sprintf(buffer, "%d/%d", CannonCtrl.cardsHit ,CannonCtrl.shotsFired);
	//NEW_TEXT(126, 154, 128,128,0, 255, 4096,4096, TRUE, buffer, FALSE);
#if PALMODE== YES
	TEXTPRINTAT(264, 230, buffer);
#else
	TEXTPRINTAT(264, 215, buffer);
#endif



	//TEXTPRINTAT(264, 230, buffer);

	objectSetAnimation(pCannonPSA, 0);
	//iframe=RANDOM256()*256;
	
	pGlovePSA->position.vx=pCannonPSA->position.vx+pCannonPSA->world.matrix.t[0]+(tempVec.vx/4096);
	pGlovePSA->position.vy=pCannonPSA->position.vy+pCannonPSA->world.matrix.t[1]+height1;
	pGlovePSA->position.vz=pCannonPSA->position.vz+pCannonPSA->world.matrix.t[2]+(tempVec.vz/4096);

	pGlovePSA->world.rotate.vx=pCannonPSA->world.rotate.vx;
	pGlovePSA->world.rotate.vy=pCannonPSA->world.rotate.vy;
	pGlovePSA->world.rotate.vz=pCannonPSA->world.rotate.vz;

	drawCards();

	objectDraw(pCannonPSA);

	lscapeDrawRotate(pRing03PSA, 0);

	lscapeDrawRotate(pRing02PSA, 0);

	lscapeDrawRotate(pRing01PSA, 0);

	lscapeDrawRotate(pPod01PSA, 0);

	objectSetAnimation(pGlovePSA, animate(&Glover) );
	objectDraw(pGlovePSA);
	updateBullets();
	miniCollision();

}

/////////////////////////////////////////////////////////////////////////////////////////////////////
void	drawCards(void)
{
SHORT	angle,loop,distance;
VECTOR	tempVec;

	distance=380;

	CannonCtrl.ring1angle+=INER_RING_SPEED;
	angle=CannonCtrl.ring1angle;

	loop=0;
	for (loop=0;loop<20;loop++)
	{
		if (CannonCtrl.ring1CardStatus[loop])
		{
			tempVec.vx=0;
			
			if (CannonCtrl.ring1CardStatus[loop]==CARDGOINGDOWN)
			{
				tempVec.vy=-15+(CannonCtrl.recedingCount1[loop]+=4);
				if (CannonCtrl.recedingCount1[loop]>=100) CannonCtrl.ring1CardStatus[loop]=FALSE;
			}
			else if (CannonCtrl.ring1CardStatus[loop]==CARDCOMEBACK)
			{
				tempVec.vy=-15+(CannonCtrl.recedingCount1[loop]-=4);
				if (CannonCtrl.recedingCount1[loop]<=4) CannonCtrl.ring1CardStatus[loop]=CARDOK;
			}


			else tempVec.vy=-15;
			
			tempVec.vz=distance;
			RotateVector2D(&tempVec,&tempVec,angle);
			//CannonCtrl.ring1CardTypes[loop]=0;
			ChangeLscapeTex(&pCard01PSA->world ,cardTex[CannonCtrl.ring1CardTypes[loop]]);
			pCard01PSA->position.vx=tempVec.vx;
			pCard01PSA->position.vy=tempVec.vy;
			pCard01PSA->position.vz=tempVec.vz;
			pCard01PSA->world.rotate.vy=angle;
			objectSetAnimation(pCard01PSA, 0);
			//objectDraw(pCard01PSA);
			lscapeDrawRotate(pCard01PSA, 0);
		}
		angle+=205;
		angle=(angle&4095);

	}
	distance=500;
	//distance=testRad;
	CannonCtrl.ring2angle-=MID_RING_SPEED;
	angle=CannonCtrl.ring2angle;
	for (loop=0;loop<20;loop++)
	{
		if (CannonCtrl.ring2CardStatus[loop])
		{
			tempVec.vx=0;


			if (CannonCtrl.ring2CardStatus[loop]==CARDGOINGDOWN)
			{
				tempVec.vy=-62+(CannonCtrl.recedingCount2[loop]+=4);
				if (CannonCtrl.recedingCount2[loop]>=100) CannonCtrl.ring2CardStatus[loop]=FALSE;
			}
			else if (CannonCtrl.ring2CardStatus[loop]==CARDCOMEBACK)
			{
				tempVec.vy=-62+(CannonCtrl.recedingCount2[loop]-=4);
				if (CannonCtrl.recedingCount2[loop]<=4) CannonCtrl.ring2CardStatus[loop]=CARDOK;
			}
			else tempVec.vy=-62;

			tempVec.vz=distance;
			RotateVector2D(&tempVec,&tempVec,angle);
			//CannonCtrl.ring1CardTypes[loop]=0;
			ChangeLscapeTex(&pCard01PSA->world ,cardTex[CannonCtrl.ring2CardTypes[loop]]);
			pCard01PSA->position.vx=tempVec.vx;
			pCard01PSA->position.vy=tempVec.vy;
			pCard01PSA->position.vz=tempVec.vz;
			pCard01PSA->world.rotate.vy=angle;
			//objectSetAnimation(pCard01PSA, 0);
			//objectDraw(pCard01PSA);
			lscapeDrawRotate(pCard01PSA, 0);
		}
		angle+=205;
		angle=(angle&4095);
	}
	distance=600;
	CannonCtrl.ring3angle+=OUTER_RING_SPEED;
	angle=CannonCtrl.ring3angle;
	for (loop=0;loop<20;loop++)
	{
		if (CannonCtrl.ring3CardStatus[loop])
		{
			tempVec.vx=0;



			if (CannonCtrl.ring3CardStatus[loop]==CARDGOINGDOWN)
			{
				tempVec.vy=-105+(CannonCtrl.recedingCount3[loop]+=4);
				if (CannonCtrl.recedingCount3[loop]>=100) CannonCtrl.ring3CardStatus[loop]=FALSE;
			}
			else if (CannonCtrl.ring3CardStatus[loop]==CARDCOMEBACK)
			{
				tempVec.vy=-105+(CannonCtrl.recedingCount3[loop]-=4);
				if (CannonCtrl.recedingCount3[loop]<=4) CannonCtrl.ring3CardStatus[loop]=CARDOK;
			}
			else tempVec.vy=-105;

			tempVec.vz=distance;
			RotateVector2D(&tempVec,&tempVec,angle);
			//CannonCtrl.ring1CardTypes[loop]=0;
			ChangeLscapeTex(&pCard01PSA->world ,cardTex[CannonCtrl.ring3CardTypes[loop]]);
			pCard01PSA->position.vx=tempVec.vx;
			pCard01PSA->position.vy=tempVec.vy;
			pCard01PSA->position.vz=tempVec.vz;
			pCard01PSA->world.rotate.vy=angle;
			objectSetAnimation(pCard01PSA, 0);
			//objectDraw(pCard01PSA);
			lscapeDrawRotate(pCard01PSA, 0);
		}
		angle+=205;
		angle=(angle&4095);
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////

void	addBullet(void)
{
SHORT	loop=0;
VECTOR	tempVec;
LONG	height,length;

	while (CannonCtrl.alive[loop])
	{
		loop++;
		if (loop>9)
		{
			DB ("not enought bullets\n");
			return;
		}
	}

	// fire a shot
	height=rsin(CannonCtrl.elevation);
	length=rcos(CannonCtrl.elevation);

	tempVec.vz=-length;
	tempVec.vx=0;
	tempVec.vy=-height;
	RotateVector2D(&tempVec,&tempVec,CannonCtrl.direction);
	CannonCtrl.bulletPos[loop].vx=tempVec.vx/60;
	CannonCtrl.bulletPos[loop].vy=((tempVec.vy/60)-(pCannonPSA->world.matrix.t[1]+6));
	CannonCtrl.bulletPos[loop].vz=tempVec.vz/60;

	CannonCtrl.bulletHit[loop]=FALSE;

	CannonCtrl.bulletRot[loop].vx=RANDOM256()*16;
	CannonCtrl.bulletRot[loop].vy=RANDOM256()*16;
	CannonCtrl.bulletRot[loop].vz=RANDOM256()*16;

	CannonCtrl.bulletRotAdd[loop].vx=RANDOM256();
	CannonCtrl.bulletRotAdd[loop].vy=RANDOM256();
	CannonCtrl.bulletRotAdd[loop].vz=RANDOM256();

	//CannonCtrl.receding[loop]=FALSE;
	CannonCtrl.bulletVel[loop].vx=tempVec.vx/128;
	CannonCtrl.bulletVel[loop].vy=tempVec.vy/128;
	CannonCtrl.bulletVel[loop].vz=tempVec.vz/128;

	tempVec.vx=CannonCtrl.bulletPos[loop].vx<<12;
	tempVec.vy=-CannonCtrl.bulletPos[loop].vy<<12;
	tempVec.vz=CannonCtrl.bulletPos[loop].vz<<12;


	New_Debris(DEBRIS_CANNON,&tempVec,1024);
	//New_Debris(DEBRIS_CANNON,&tempVec,1200);

	height=RANDOM256()/25;


	if (height==1)
	{
		CannonCtrl.bulletModel[loop]=chuckBullet;
		sfxPlay(levelFX, SFX_CA_CHUCK_CALL);
	}
	else if (height==2)
	{
		CannonCtrl.bulletModel[loop]=dennisBullet;
		sfxPlay(levelFX, SFX_CA_DENNIS_LAND);
	}
	else if (height==3)
	{
		CannonCtrl.bulletModel[loop]=bugleBullet;
		sfxPlay(levelFX, SFX_CA_BUGLE_CALL);
	}
	else
	{
		CannonCtrl.bulletModel[loop]=pBallPSA;
		sfxPlay(levelFX,SFX_CA_BUGLE_DEATH);
	}

	
	//if (height==1) CannonCtrl.bulletModel[loop]=chuckBullet;
	//else if (height==2) CannonCtrl.bulletModel[loop]=dennisBullet;
	//else if (height==3) CannonCtrl.bulletModel[loop]=bugleBullet;
	//else CannonCtrl.bulletModel[loop]=pBallPSA;
	//CannonCtrl.bulletVel[loop].vx=tempVec.vx/256;
	//CannonCtrl.bulletVel[loop].vy=tempVec.vy/256;
	//CannonCtrl.bulletVel[loop].vz=tempVec.vz/256;

	//CannonCtrl.alive[loop]=TRUE;
	CannonCtrl.alive[loop]=8;
}


/////////////////////////////////////////////////////////////////////////////////////////////////////
void	updateBullets(void)
{
SHORT	loop;
VECTOR	tempVec;
	loop=0;
	for (loop=0;loop<10;loop++)
	{
		if (CannonCtrl.alive[loop])
		{
			CannonCtrl.bulletModel[loop]->position.vx=CannonCtrl.bulletPos[loop].vx;
			CannonCtrl.bulletModel[loop]->position.vy=-CannonCtrl.bulletPos[loop].vy;
			CannonCtrl.bulletModel[loop]->position.vz=CannonCtrl.bulletPos[loop].vz;
			//CannonCtrl.alive[loop]+=8;
			CannonCtrl.bulletModel[loop]->world.rotate.vx=CannonCtrl.bulletRot[loop].vx;
			CannonCtrl.bulletModel[loop]->world.rotate.vy=CannonCtrl.bulletRot[loop].vy;
			CannonCtrl.bulletModel[loop]->world.rotate.vz=CannonCtrl.bulletRot[loop].vz;

			CannonCtrl.bulletRot[loop].vx=(CannonCtrl.bulletRot[loop].vx+CannonCtrl.bulletRotAdd[loop].vx)&4095;
			CannonCtrl.bulletRot[loop].vy=(CannonCtrl.bulletRot[loop].vy+CannonCtrl.bulletRotAdd[loop].vy)&4095;
			CannonCtrl.bulletRot[loop].vz=(CannonCtrl.bulletRot[loop].vz+CannonCtrl.bulletRotAdd[loop].vz)&4095;

			if (CannonCtrl.bulletPos[loop].vy<-80) CannonCtrl.alive[loop]=FALSE;
			objectSetAnimation(CannonCtrl.bulletModel[loop], 0);
			objectDraw(CannonCtrl.bulletModel[loop]);
			ADDVECTOR(&CannonCtrl.bulletPos[loop],&CannonCtrl.bulletPos[loop],&CannonCtrl.bulletVel[loop]);
			CannonCtrl.alive[loop]++;
			if (!(CannonCtrl.alive[loop]%2) )
			{
				tempVec.vx=CannonCtrl.bulletModel[loop]->position.vx<<12;
				tempVec.vy=CannonCtrl.bulletModel[loop]->position.vy<<12;
				tempVec.vz=CannonCtrl.bulletModel[loop]->position.vz<<12;
				CannonCtrl.bulletVel[loop].vy--;
				New_Debris(DEBRIS_DUST,&tempVec,0x201810);
			}
		}
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////

void	miniCollision(void)
{
SHORT	loop;
LONG	distance,height;
VECTOR	tempVec;


	for (loop=0;loop<10;loop++)
	{
		if (CannonCtrl.alive[loop])
		{
			tempVec.vx=CannonCtrl.bulletPos[loop].vx;
			tempVec.vz=CannonCtrl.bulletPos[loop].vz;
			tempVec.vy=0;
			height=-CannonCtrl.bulletPos[loop].vy;
			distance=Magnitude(&tempVec);
			// have we hit first ring?
			if (height>60) CannonCtrl.alive[loop]=FALSE;

			if ( (distance>370 && distance<390) && (height<25 && height>-50) && CannonCtrl.bulletHit[loop]==FALSE )
				checkCardRing1(height,distance,loop);
			if ( (distance>450 && distance<470) && (height<-20 && height>-95) && CannonCtrl.bulletHit[loop]==FALSE )
				checkCardRing2(height,distance,loop);
			if ( (distance>550 && distance<640) && (height<-65 && height>-140) && CannonCtrl.bulletHit[loop]==FALSE )
				checkCardRing3(height,distance,loop);

			if (distance>=300 && distance<=390 && height>=25)
			{
				// now find out where
				checkRing1(height,distance,loop,&tempVec);
			}
			else if (distance>=420 && distance<=510 && height>=-20)
			{
				// now find out where
				checkRing2(height,distance,loop,&tempVec);
			}
			else if (distance>=550 && distance<=640 && height>=-65)
			{
				// now find out where
				checkRing3(height,distance,loop,&tempVec);
			}
		}
	}

/*				heightCheck=abs(height-65);
				distanceCheck1=abs(distance-300);
				distanceCheck2=abs(distance-390);
				if ( (heightCheck<distanceCheck1) && (heightCheck<distanceCheck1) )
				{
					CannonCtrl.bulletPos[loop].vy=66;
					CannonCtrl.bulletVel[loop].vy=-CannonCtrl.bulletVel[loop].vy;
				}
				else if ( distanceCheck1<distanceCheck2 )
				{
					MakeUnit(&tempVec);
					ScaleVector(&tempVec,300);
					CannonCtrl.bulletPos[loop].vx=tempVec.vx;
					CannonCtrl.bulletPos[loop].vz=tempVec.vz;
					if ( CannonCtrl.bulletPos[loop].vx )
					{
						if ( CannonCtrl.bulletPos[loop].vx<0 && CannonCtrl.bulletVel[loop].vx<0 )
						{
							CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
							CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
						}
						else if ( CannonCtrl.bulletPos[loop].vx>0 && CannonCtrl.bulletVel[loop].vx>0 )
						{
							CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
							CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
						}
					}
					else if ( CannonCtrl.bulletPos[loop].vz )
					{
						if ( CannonCtrl.bulletPos[loop].vz<0 && CannonCtrl.bulletVel[loop].vz<0 )
						{
							CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
							CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
						}
						else if ( CannonCtrl.bulletPos[loop].vz>0 && CannonCtrl.bulletVel[loop].vz>0 )
						{
							CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
							CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
						}
					}
				}
				else
				{
					MakeUnit(&tempVec);
					ScaleVector(&tempVec,390);
					CannonCtrl.bulletPos[loop].vx=tempVec.vx;
					CannonCtrl.bulletPos[loop].vz=tempVec.vz;
					if ( CannonCtrl.bulletPos[loop].vx )
					{
						if ( CannonCtrl.bulletPos[loop].vx<0 && CannonCtrl.bulletVel[loop].vx<0 )
						{
							CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
							CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
						}
						else if ( CannonCtrl.bulletPos[loop].vx>0 && CannonCtrl.bulletVel[loop].vx>0 )
						{
							CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
							CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
						}
					}
					else if ( CannonCtrl.bulletPos[loop].vz )
					{
						if ( CannonCtrl.bulletPos[loop].vz<0 && CannonCtrl.bulletVel[loop].vz<0 )
						{
							CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
							CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
						}
						else if ( CannonCtrl.bulletPos[loop].vz>0 && CannonCtrl.bulletVel[loop].vz>0 )
						{
							CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
							CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
						}
					}
				}
			*/




/*	loop=0;
	for (loop=0;loop<10;loop++)
	{
		if (CannonCtrl.alive[loop])
		{
			tempVec.vx=CannonCtrl.bulletPos[loop].vx;
			tempVec.vz=CannonCtrl.bulletPos[loop].vz;
			tempVec.vy=0;
			height=-CannonCtrl.bulletPos[loop].vy;
			distance=Magnitude(&tempVec);
			// Check for hit first ring
			if (distance>300 && distance<390)
			{
				// inside 1st ring distance
				// check for card hit
				if (distance>370 && distance<390 )
				{
					angle=CannonCtrl.ring1angle;
					for (loop1=0;loop1<20;loop1++)
					{
						if (CannonCtrl.ring1CardStatus[loop1])
						{
							tempVec.vx=0;
							tempVec.vy=0;
							tempVec.vz=distance;
							RotateVector2D(&tempVec,&tempVec,angle);
							tempVec1.vx=tempVec.vx+50;
							tempVec1.vz=tempVec.vz+50;
							tempVec.vx-=50;
							tempVec.vz-=50;

							if ( pointInBox(CannonCtrl.bulletPos[loop].vx,CannonCtrl.bulletPos[loop].vz,&tempVec,&tempVec1) )
							{
								CannonCtrl.ring1CardStatus[loop1]=0;
								CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx/2;
								CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz/2;
								break;
							}
						}
						angle=(angle+205)&4095;
					}
				}

				if (height>=25)
				{
					// hit ring 1
					// now need to work out if hit side or top
					distance-=300;
					if ( distance>5 && distance<80 )
					{
						// top
						if (CannonCtrl.bulletVel[loop].vy<0)
							CannonCtrl.bulletVel[loop].vy=-CannonCtrl.bulletVel[loop].vy;
					}
					else
					{
						CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
						CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
					}
				}
			}
			else if (distance>420 && distance<510)
			{
				// inside 2nd ring distance
				if (distance>450 && distance<470 )
				{
					angle=CannonCtrl.ring1angle;
					for (loop1=0;loop1<20;loop1++)
					{
						if (CannonCtrl.ring2CardStatus[loop1])
						{
							tempVec.vx=0;
							tempVec.vy=0;
							tempVec.vz=distance;
							RotateVector2D(&tempVec,&tempVec,angle);
							tempVec1.vx=tempVec.vx+50;
							tempVec1.vz=tempVec.vz+50;
							tempVec.vx-=50;
							tempVec.vz-=50;
							if ( pointInBox(CannonCtrl.bulletPos[loop].vx,CannonCtrl.bulletPos[loop].vz,&tempVec,&tempVec1) )
							{
								CannonCtrl.ring2CardStatus[loop1]=0;
								CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx/2;
								CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz/2;
								break;
							}
						}
						angle=(angle+205)&4095;
					}
				}
				if (height>=-20)
				{
					// hit ring 2
					// now need to work out if hit side or top
					distance-=420;
					if ( distance>5 && distance<80 )
					{
						// top
						if (CannonCtrl.bulletVel[loop].vy<0 && height>=-18)
						{
							CannonCtrl.bulletVel[loop].vy=-CannonCtrl.bulletVel[loop].vy;
							//CannonCtrl.bulletPos[loop].vy=-22;
						}
					}
					else
					{
						CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
						CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
					}
				}
			}
			else if (distance>550 && distance<640)
			{
				// inside 2nd ring distance

				if (distance>600 && distance<620 )
				{
					angle=CannonCtrl.ring1angle;
					for (loop1=0;loop1<20;loop1++)
					{
						if (CannonCtrl.ring3CardStatus[loop1])
						{
							tempVec.vx=0;
							tempVec.vy=0;
							tempVec.vz=distance;
							RotateVector2D(&tempVec,&tempVec,angle);
							tempVec1.vx=tempVec.vx+50;
							tempVec1.vz=tempVec.vz+50;
							tempVec.vx-=50;
							tempVec.vz-=50;

							if ( pointInBox(CannonCtrl.bulletPos[loop].vx,CannonCtrl.bulletPos[loop].vz,&tempVec,&tempVec1) )
							{
								CannonCtrl.ring3CardStatus[loop1]=0;
								CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx/2;
								CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz/2;
								break;
							}
						}
						angle=(angle+205)&4095;
					}
				}

				if (height>=-60)
				{
					// hit ring 2
					// now need to work out if hit side or top
					distance-=550;
					if ( distance>5 && distance<80 )
					{
						// top
						if (CannonCtrl.bulletVel[loop].vy<0 && height>=-58 )
						{
							CannonCtrl.bulletVel[loop].vy=-CannonCtrl.bulletVel[loop].vy;
							//CannonCtrl.bulletPos[loop].vy=-22;
						}
					}
					else
					{
						CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
						CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
					}
				}
			}
		}
	}*/
}

/////////////////////////////////////////////////////////////////////////////////////////////////////

void	checkRing1(LONG height,LONG distance,LONG loop,VECTOR *tempVec)
{

LONG	heightCheck,distanceCheck1,distanceCheck2;

	heightCheck=abs(25-height);
	distanceCheck1=abs(distance-300);
	distanceCheck2=abs(distance-390);

	if (heightCheck>10) heightCheck=99;

	if ( (heightCheck<distanceCheck1) && (heightCheck<distanceCheck2) )
	{
		//DB ("hc %d dc1 %d dc2 %d\n",heightCheck,distanceCheck1,distanceCheck2);
		//CannonCtrl.bulletPos[loop].vy=25;
		if (CannonCtrl.bulletVel[loop].vy<0)
			CannonCtrl.bulletVel[loop].vy=-CannonCtrl.bulletVel[loop].vy/2;
	}
	else if ( distanceCheck1<distanceCheck2 )
	{
		MakeUnit(tempVec);
		SCALEVECTOR(tempVec,300);
		CannonCtrl.bulletPos[loop].vx=tempVec->vx;
		CannonCtrl.bulletPos[loop].vz=tempVec->vz;
		if ( CannonCtrl.bulletPos[loop].vx )
		{
			if ( CannonCtrl.bulletPos[loop].vx<0 && CannonCtrl.bulletVel[loop].vx<0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
			else if ( CannonCtrl.bulletPos[loop].vx>0 && CannonCtrl.bulletVel[loop].vx>0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
		}
		else if ( CannonCtrl.bulletPos[loop].vz )
		{
			if ( CannonCtrl.bulletPos[loop].vz<0 && CannonCtrl.bulletVel[loop].vz<0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
			else if ( CannonCtrl.bulletPos[loop].vz>0 && CannonCtrl.bulletVel[loop].vz>0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
		}
	}
	else
	{
		MakeUnit(tempVec);
		SCALEVECTOR(tempVec,390);
		CannonCtrl.bulletPos[loop].vx=tempVec->vx;
		CannonCtrl.bulletPos[loop].vz=tempVec->vz;
		if ( CannonCtrl.bulletPos[loop].vx )
		{
			if ( CannonCtrl.bulletPos[loop].vx<0 && CannonCtrl.bulletVel[loop].vx<0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
			else if ( CannonCtrl.bulletPos[loop].vx>0 && CannonCtrl.bulletVel[loop].vx>0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
		}
		else if ( CannonCtrl.bulletPos[loop].vz )
		{
			if ( CannonCtrl.bulletPos[loop].vz<0 && CannonCtrl.bulletVel[loop].vz<0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
			else if ( CannonCtrl.bulletPos[loop].vz>0 && CannonCtrl.bulletVel[loop].vz>0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
		}
	}
}


/////////////////////////////////////////////////////////////////////////////////////////////////////

void	checkRing2(LONG height,LONG distance,LONG loop,VECTOR *tempVec)
{

LONG	heightCheck,distanceCheck1,distanceCheck2;

	heightCheck=abs(-20-height);
	distanceCheck1=abs(distance-420);
	distanceCheck2=abs(distance-510);

	if (heightCheck>10) heightCheck=99;

	if ( (heightCheck<distanceCheck1) && (heightCheck<distanceCheck2) )
	{
		//CannonCtrl.bulletPos[loop].vy=21;
		if (CannonCtrl.bulletVel[loop].vy<0)
			CannonCtrl.bulletVel[loop].vy=-CannonCtrl.bulletVel[loop].vy/2;
	}
	else if ( distanceCheck1<distanceCheck2 )
	{
		MakeUnit(tempVec);
		SCALEVECTOR(tempVec,420);
		CannonCtrl.bulletPos[loop].vx=tempVec->vx;
		CannonCtrl.bulletPos[loop].vz=tempVec->vz;
		if ( CannonCtrl.bulletPos[loop].vx )
		{
			if ( CannonCtrl.bulletPos[loop].vx<0 && CannonCtrl.bulletVel[loop].vx<0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
			else if ( CannonCtrl.bulletPos[loop].vx>0 && CannonCtrl.bulletVel[loop].vx>0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
		}
		else if ( CannonCtrl.bulletPos[loop].vz )
		{
			if ( CannonCtrl.bulletPos[loop].vz<0 && CannonCtrl.bulletVel[loop].vz<0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
			else if ( CannonCtrl.bulletPos[loop].vz>0 && CannonCtrl.bulletVel[loop].vz>0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
		}
	}
	else
	{
		MakeUnit(tempVec);
		SCALEVECTOR(tempVec,510);
		CannonCtrl.bulletPos[loop].vx=tempVec->vx;
		CannonCtrl.bulletPos[loop].vz=tempVec->vz;
		if ( CannonCtrl.bulletPos[loop].vx )
		{
			if ( CannonCtrl.bulletPos[loop].vx<0 && CannonCtrl.bulletVel[loop].vx<0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
			else if ( CannonCtrl.bulletPos[loop].vx>0 && CannonCtrl.bulletVel[loop].vx>0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
		}
		else if ( CannonCtrl.bulletPos[loop].vz )
		{
			if ( CannonCtrl.bulletPos[loop].vz<0 && CannonCtrl.bulletVel[loop].vz<0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
			else if ( CannonCtrl.bulletPos[loop].vz>0 && CannonCtrl.bulletVel[loop].vz>0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
		}
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////

void	checkRing3(LONG height,LONG distance,LONG loop,VECTOR *tempVec)
{

LONG	heightCheck,distanceCheck1,distanceCheck2;

	heightCheck=abs(-65-height);
	distanceCheck1=abs(distance-550);
	distanceCheck2=abs(distance-640);

	if (heightCheck>10) heightCheck=99;

	if ( (heightCheck<distanceCheck1) && (heightCheck<distanceCheck2) )
	{
		//CannonCtrl.bulletPos[loop].vy=-24;
		if (CannonCtrl.bulletVel[loop].vy<0)
			CannonCtrl.bulletVel[loop].vy=-CannonCtrl.bulletVel[loop].vy/2;
	}
	else if ( distanceCheck1<distanceCheck2 )
	{
		MakeUnit(tempVec);
		SCALEVECTOR(tempVec,550);
		CannonCtrl.bulletPos[loop].vx=tempVec->vx;
		CannonCtrl.bulletPos[loop].vz=tempVec->vz;
		if ( CannonCtrl.bulletPos[loop].vx )
		{
			if ( CannonCtrl.bulletPos[loop].vx<0 && CannonCtrl.bulletVel[loop].vx<0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
			else if ( CannonCtrl.bulletPos[loop].vx>0 && CannonCtrl.bulletVel[loop].vx>0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
		}
		else if ( CannonCtrl.bulletPos[loop].vz )
		{
			if ( CannonCtrl.bulletPos[loop].vz<0 && CannonCtrl.bulletVel[loop].vz<0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
			else if ( CannonCtrl.bulletPos[loop].vz>0 && CannonCtrl.bulletVel[loop].vz>0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
		}
	}
	else
	{
		MakeUnit(tempVec);
		SCALEVECTOR(tempVec,640);
		CannonCtrl.bulletPos[loop].vx=tempVec->vx;
		CannonCtrl.bulletPos[loop].vz=tempVec->vz;
		if ( CannonCtrl.bulletPos[loop].vx )
		{
			if ( CannonCtrl.bulletPos[loop].vx<0 && CannonCtrl.bulletVel[loop].vx<0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
			else if ( CannonCtrl.bulletPos[loop].vx>0 && CannonCtrl.bulletVel[loop].vx>0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
		}
		else if ( CannonCtrl.bulletPos[loop].vz )
		{
			if ( CannonCtrl.bulletPos[loop].vz<0 && CannonCtrl.bulletVel[loop].vz<0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
			else if ( CannonCtrl.bulletPos[loop].vz>0 && CannonCtrl.bulletVel[loop].vz>0 )
			{
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz;
			}
		}
	}
}


///////////////////////////////////////////////////////////////////////////////////////////////////
void	checkCardRing1(LONG height,LONG distance,LONG loop)
{
LONG	angle,loop1,loop2;
VECTOR	tempVec,tempVec1;

	angle=CannonCtrl.ring1angle;
	for (loop1=0;loop1<20;loop1++)
	{
		if (CannonCtrl.ring1CardStatus[loop1]!=CARDGOINGDOWN && CannonCtrl.ring1CardStatus[loop1]!=FALSE)
		{
			tempVec.vx=0;
			tempVec.vy=0;
			tempVec.vz=distance;
			RotateVector2D(&tempVec,&tempVec,angle);
			tempVec1.vx=tempVec.vx+50;
			tempVec1.vz=tempVec.vz+50;
			tempVec.vx-=50;
			tempVec.vz-=50;
			if ( pointInBox(CannonCtrl.bulletPos[loop].vx,CannonCtrl.bulletPos[loop].vz,&tempVec,&tempVec1) )
			{
				CannonCtrl.ring1CardStatus[loop1]=CARDGOINGDOWN;
				CannonCtrl.cardsHit++;
				if ( endOfBonusCheck() ) CannonCtrl.endOfBonusFlag=TRUE;
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx/4;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz/4;
				CannonCtrl.bulletHit[loop]=TRUE;

				if (CannonCtrl.ring1CardTypes[loop1]==0)// wizard card
				{
					for (loop2=0;loop2<20;loop2++)
					{
						if (loop!=loop2)
						{
							if (CannonCtrl.ring1CardStatus[loop2]==FALSE)
								CannonCtrl.ring1CardStatus[loop2]=CARDCOMEBACK;
						}
					}
				}
				break;
			}
		}
		angle=(angle+205)&4095;
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////
void	checkCardRing2(LONG height,LONG distance,LONG loop)
{
LONG	angle,loop1,loop2;
VECTOR	tempVec,tempVec1;

	angle=CannonCtrl.ring2angle;
	for (loop1=0;loop1<20;loop1++)
	{
		if (CannonCtrl.ring2CardStatus[loop1]!=CARDGOINGDOWN && CannonCtrl.ring2CardStatus[loop1]!=FALSE)
		{
			tempVec.vx=0;
			tempVec.vy=0;
			tempVec.vz=distance;
			RotateVector2D(&tempVec,&tempVec,angle);
			tempVec1.vx=tempVec.vx+50;
			tempVec1.vz=tempVec.vz+50;
			tempVec.vx-=50;
			tempVec.vz-=50;
			if ( pointInBox(CannonCtrl.bulletPos[loop].vx,CannonCtrl.bulletPos[loop].vz,&tempVec,&tempVec1) )
			{
				CannonCtrl.ring2CardStatus[loop1]=CARDGOINGDOWN;
				CannonCtrl.cardsHit++;
				if ( endOfBonusCheck() ) CannonCtrl.endOfBonusFlag=TRUE;
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx/4;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz/4;
				CannonCtrl.bulletHit[loop]=TRUE;

				if (CannonCtrl.ring2CardTypes[loop1]==0)// wizard card
				{
					for (loop2=0;loop2<20;loop2++)
					{
						if (loop!=loop2)
						{
							if (CannonCtrl.ring2CardStatus[loop2]==FALSE)
								CannonCtrl.ring2CardStatus[loop2]=CARDCOMEBACK;
						}
					}
				}

				break;
			}
		}
		angle=(angle+205)&4095;
	}
}


///////////////////////////////////////////////////////////////////////////////////////////////////
void	checkCardRing3(LONG height,LONG distance,LONG loop)
{
LONG	angle,loop1,loop2;
VECTOR	tempVec,tempVec1;

	angle=CannonCtrl.ring3angle;
	for (loop1=0;loop1<20;loop1++)
	{
		if (CannonCtrl.ring3CardStatus[loop1]!=CARDGOINGDOWN && CannonCtrl.ring3CardStatus[loop1]!=FALSE)
		{
			tempVec.vx=0;
			tempVec.vy=0;
			tempVec.vz=distance;
			RotateVector2D(&tempVec,&tempVec,angle);
			tempVec1.vx=tempVec.vx+50;
			tempVec1.vz=tempVec.vz+50;
			tempVec.vx-=50;
			tempVec.vz-=50;
			if ( pointInBox(CannonCtrl.bulletPos[loop].vx,CannonCtrl.bulletPos[loop].vz,&tempVec,&tempVec1) )
			{
				CannonCtrl.ring3CardStatus[loop1]=CARDGOINGDOWN;
				CannonCtrl.cardsHit++;
				if ( endOfBonusCheck() ) CannonCtrl.endOfBonusFlag=TRUE;
				CannonCtrl.bulletVel[loop].vx=-CannonCtrl.bulletVel[loop].vx/4;
				CannonCtrl.bulletVel[loop].vz=-CannonCtrl.bulletVel[loop].vz/4;
				CannonCtrl.bulletHit[loop]=TRUE;

				if (CannonCtrl.ring3CardTypes[loop1]==0)// wizard card
				{
					for (loop2=0;loop2<20;loop2++)
					{
						if (loop!=loop2)
						{
							if (CannonCtrl.ring3CardStatus[loop2]==FALSE)
								CannonCtrl.ring3CardStatus[loop2]=CARDCOMEBACK;
						}
					}
				}

				break;
			}
		}
		angle=(angle+205)&4095;
	}
}


///////////////////////////////////////////////////////////////////////////////////////////////////
LONG	pointInBox(LONG	x,LONG z,VECTOR *p1,VECTOR *p2)
{

	if (p1->vx > p2->vx)
	{
		if (x > p2->vx && x < p1->vx)
		{
			if (p1->vz > p2->vz)
			{
				if (z > p2->vz && z < p1->vz)
				{
					return(TRUE);
				}
				else return(FALSE);
			}
			else
			{
				if (z > p1->vz && z < p2->vz)
				{
					return(TRUE);
				}
				else return(FALSE);
			}
		}
		else return(FALSE);
	}
	else
	{
		if (x > p1->vx && x < p2->vx)
		{
			if (p1->vz > p2->vz)
			{
				if (z > p2->vz && z < p1->vz)
				{
					return(TRUE);
				}
				else return(FALSE);
			}
			else
			{
				if (z > p1->vz && z < p2->vz)
				{
					return(TRUE);
				}
				else return(FALSE);
			}
		}
		else return(FALSE);
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////

LONG	endOfBonusCheck(void)
{
LONG	loop;

	for (loop=0;loop<20;loop++)
	{
		if (CannonCtrl.ring1CardStatus[loop]==FALSE || CannonCtrl.ring1CardStatus[loop]==CARDGOINGDOWN || CannonCtrl.ring1CardTypes[loop]==0) ;
		else return(FALSE);

		if (CannonCtrl.ring2CardStatus[loop]==FALSE || CannonCtrl.ring2CardStatus[loop]==CARDGOINGDOWN || CannonCtrl.ring2CardTypes[loop]==0) ;
		else return(FALSE);

		if (CannonCtrl.ring3CardStatus[loop]==FALSE || CannonCtrl.ring3CardStatus[loop]==CARDGOINGDOWN || CannonCtrl.ring3CardTypes[loop]==0) ;
		else return(FALSE);
	}
	return(TRUE);

}

///////////////////////////////////////////////////////////////////////////////////////////////////
void	muzzelFlash(void)
{

	POLY_G3 	*si = (POLY_G3 *) GsOUT_PACKET_P; 
	register	GsOTA 	*otptr=(GsOTA*)(PolyList->org+256);
	SHORT		red,loop;
	SHORT		px[10],py[10];
	SHORT		centerx=0,centery=0;
	

	if (CannonCtrl.justFiredFlag<5) return;

	centery=rsin(CannonCtrl.elevation)/70-(pCannonPSA->world.matrix.t[1]-22);

	loop=CannonCtrl.direction-CannonCtrl.camDirection;

	centerx=rsin(loop)/16;

	px[0]=(0*4096)/3072;	py[0]=-100;
	px[1]=(95*4096)/3072;	py[1]=-31;
	px[2]=(59*4096)/3072;	py[2]=81;
	px[3]=(-59*4096)/3072;	py[3]=81;
	px[4]=(-95*4096)/3072;	py[4]=-31;
	
	px[5]=(-17*4096)/3072;	py[5]=-24;
	px[6]=(17*4096)/3072;	py[6]=-24;
	px[7]=(28*4096)/3072;	py[7]=9;
	px[8]=(0*4096)/3072;	py[8]=30;
	px[9]=(-28*4096)/3072;	py[9]=9;

	red=(CannonCtrl.justFiredFlag-5)*48;

	for (loop=0;loop<4;loop++)
	{
	  	if (TOOMANYPOLYS(sizeof(POLY_G3),"CLEAR SCREEN"))return;

		SETRGBC(si->r0, red, 0, 0, GPU_COM_G3);
		SETRGBC(si->r1, red, red/2, red/2, GPU_COM_G3);
		SETRGBC(si->r2, red, red/2, red/2, GPU_COM_G3);

		si->x0=px[loop]+centerx;		si->y0=py[loop]+centery;
		si->x1=px[5+loop]+centerx;		si->y1=py[5+loop]+centery;
		si->x2=px[6+loop]+centerx;		si->y2=py[6+loop]+centery;
	
		si->code = si->code | 2;

	 	PUTPACKETINTABLE(si,otptr,POLYG3_LEN);
		GsOUT_PACKET_P+=sizeof(POLY_G3);
		si++;
	}
  	if (TOOMANYPOLYS(sizeof(POLY_G3),"CLEAR SCREEN"))return;
	SETRGBC(si->r0, red/2, 0, 0, GPU_COM_G3);
	SETRGBC(si->r1, red, red/2, red/2, GPU_COM_G3);
	SETRGBC(si->r2, red, red/2, red/2, GPU_COM_G3);

	si->x0=px[4]+centerx;		si->y0=py[4]+centery;
	si->x1=px[9]+centerx;		si->y1=py[9]+centery;
	si->x2=px[5]+centerx;		si->y2=py[5]+centery;
	si->code = si->code | 2;
 	PUTPACKETINTABLE(si,otptr,POLYG3_LEN);
	GsOUT_PACKET_P+=sizeof(POLY_G3);
	si++;

  	if (TOOMANYPOLYS(sizeof(POLY_G3),"CLEAR SCREEN"))return;
	SETRGBC(si->r0, red, red/2, red/2, GPU_COM_G3);
	SETRGBC(si->r1, red, red/2, red/2, GPU_COM_G3);
	SETRGBC(si->r2, red, red/2, red/2, GPU_COM_G3);

	si->x0=px[5]+centerx;		si->y0=py[5]+centery;
	si->x1=px[6]+centerx;		si->y1=py[6]+centery;
	si->x2=px[9]+centerx;		si->y2=py[9]+centery;
	si->code = si->code | 2;
 	PUTPACKETINTABLE(si,otptr,POLYG3_LEN);
	GsOUT_PACKET_P+=sizeof(POLY_G3);
	si++;

  	if (TOOMANYPOLYS(sizeof(POLY_G3),"CLEAR SCREEN"))return;
	SETRGBC(si->r0, red, red/2, red/2, GPU_COM_G3);
	SETRGBC(si->r1, red, red/2, red/2, GPU_COM_G3);
	SETRGBC(si->r2, red, red/2, red/2, GPU_COM_G3);

	si->x0=px[6]+centerx;		si->y0=py[6]+centery;
	si->x1=px[7]+centerx;		si->y1=py[7]+centery;
	si->x2=px[8]+centerx;		si->y2=py[8]+centery;
	si->code = si->code | 2;
 	PUTPACKETINTABLE(si,otptr,POLYG3_LEN);
	GsOUT_PACKET_P+=sizeof(POLY_G3);
	si++;

  	if (TOOMANYPOLYS(sizeof(POLY_G3),"CLEAR SCREEN"))return;
	SETRGBC(si->r0, red, red/2, red/2, GPU_COM_G3);
	SETRGBC(si->r1, red, red/2, red/2, GPU_COM_G3);
	SETRGBC(si->r2, red, red/2, red/2, GPU_COM_G3);

	si->x0=px[6]+centerx;		si->y0=py[6]+centery;
	si->x1=px[8]+centerx;		si->y1=py[8]+centery;
	si->x2=px[9]+centerx;		si->y2=py[9]+centery;
	si->code = si->code | 2;
 	PUTPACKETINTABLE(si,otptr,POLYG3_LEN);
	GsOUT_PACKET_P+=sizeof(POLY_G3);
	si++;

	// do this after all polys for semi mode addative ect
	{
		DR_TPAGE *si = (DR_TPAGE *) GsOUT_PACKET_P;
		SetDrawTPage(si,1,1,((SEMITRANS_ADD-1)<<5));	// this is a macro, anyway

		PUTPACKETINTABLE(si,otptr,DRTPAGE_LEN);
		GsOUT_PACKET_P+=sizeof(DR_TPAGE);
	}
}


/////////////////////////////////////////////////////////////////////////////////////////////////
void	caBonusDisplay(void)
{
SHORT	loop;

	pCannonPSA->world.rotate.vy=pPod01PSA->world.rotate.vy=CannonCtrl.direction;
	pCannonPSA->world.rotate.vx=CannonCtrl.elevation;

	objectSetAnimation(pCannonPSA,0);

	pGlovePSA->world.rotate.vx=pCannonPSA->world.rotate.vx;
	pGlovePSA->world.rotate.vy=pCannonPSA->world.rotate.vy;
	pGlovePSA->world.rotate.vz=pCannonPSA->world.rotate.vz;


	CannonCtrl.ring1angle-=INER_RING_SPEED;
	CannonCtrl.ring2angle+=MID_RING_SPEED;
	CannonCtrl.ring3angle-=OUTER_RING_SPEED;

	drawCards();

	objectDraw(pCannonPSA);

	lscapeDrawRotate(pRing03PSA, 0);
	lscapeDrawRotate(pRing02PSA, 0);
	lscapeDrawRotate(pRing01PSA, 0);
	lscapeDrawRotate(pPod01PSA, 0);

	objectSetAnimation(pGlovePSA, animate(&Glover) );
	objectDraw(pGlovePSA);


	for (loop=0;loop<10;loop++)
	{
		if (CannonCtrl.alive[loop])
		{
			CannonCtrl.bulletModel[loop]->position.vx=CannonCtrl.bulletPos[loop].vx;
			CannonCtrl.bulletModel[loop]->position.vy=-CannonCtrl.bulletPos[loop].vy;
			CannonCtrl.bulletModel[loop]->position.vz=CannonCtrl.bulletPos[loop].vz;

			CannonCtrl.bulletRot[loop].vx=(CannonCtrl.bulletRot[loop].vx+CannonCtrl.bulletRotAdd[loop].vx)&4095;
			CannonCtrl.bulletRot[loop].vy=(CannonCtrl.bulletRot[loop].vy+CannonCtrl.bulletRotAdd[loop].vy)&4095;
			CannonCtrl.bulletRot[loop].vz=(CannonCtrl.bulletRot[loop].vz+CannonCtrl.bulletRotAdd[loop].vz)&4095;

			if (CannonCtrl.bulletPos[loop].vy<-80) CannonCtrl.alive[loop]=FALSE;
			objectSetAnimation(CannonCtrl.bulletModel[loop], 0);
			objectDraw(CannonCtrl.bulletModel[loop]);

		}
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////
void	cannonHandler(void)
{
LONG	angle,elevation;
VECTOR	tempVec;
LONG	mag;
	tempVec.vx=(pCannonPSA->position.vx-pGlovePSA->position.vx);
	tempVec.vy=(pCannonPSA->position.vy-pGlovePSA->position.vy);
	tempVec.vz=(pCannonPSA->position.vz-pGlovePSA->position.vz);


	angle=calc_angle( tempVec.vx,tempVec.vz );
	mag=Magnitude(&tempVec);

	mag=(mag/60)*4096;
	elevation=calc_angle( mag,(15*4096) );

	angle=angle&4095;
	pCannonPSA->position.vx=-127;
	pCannonPSA->position.vy=-43;
	pCannonPSA->position.vz=3580;

	pCannonPSA->world.rotate.vx=0;
	pCannonPSA->world.rotate.vy=angle+1024;
	//DB ("angle %d \n",angle);
	pCannonPSA->world.rotate.vz=-elevation;


	tempVec.vx=pCannonPSA->position.vx*4096;
	tempVec.vy=pCannonPSA->position.vy*4096;
	tempVec.vz=pCannonPSA->position.vz*4096;


  	gte_SetRotMatrix(&GsWSMATRIX);
  	gte_SetTransMatrix(&GsWSMATRIX);

	if(RadiusCheck4096(&tempVec,30*4096,1500))
	{
		objectSetAnimation(pCannonPSA, 0);
		objectDraw(pCannonPSA);
	}

	if ( !(frame%100) )
	{
		if ( (glovePos.vx > (176*4096) && glovePos.vx < ( (713)*4096)) && (glovePos.vz > (3320*4096) && glovePos.vz < (3850*4096) ) )
			fireShot();
	}
	updateShots();
}

/////////////////////////////////////////////////////////////////////////////////////////////

void	fireShot(void)
{
LONG	loop,mag;
VECTOR	tempVec;

	loop=0;
	while (CannonCtrl.alive[loop])
	{
		loop++;
		if (loop>9)
		{
			//DB ("not enought bullets\n");
			return;
		}
	}

	tempVec.vx=-(pCannonPSA->position.vx-pGlovePSA->position.vx);
	tempVec.vy=-(pCannonPSA->position.vy-pGlovePSA->position.vy);
	tempVec.vz=-(pCannonPSA->position.vz-pGlovePSA->position.vz);
	
	mag=Magnitude(&tempVec);
	MakeUnit(&tempVec);

	tempVec.vx*=15;
	tempVec.vy*=15;
	tempVec.vz*=15;

	tempVec.vy-=((mag/60)+1)*4096;

	CannonCtrl.alive[loop]=TRUE;
	CannonCtrl.bulletPos[loop].vx=pCannonPSA->position.vx*4096;
	CannonCtrl.bulletPos[loop].vy=pCannonPSA->position.vy*4096;
	CannonCtrl.bulletPos[loop].vz=pCannonPSA->position.vz*4096;

	CannonCtrl.bulletHit[loop]=FALSE;

	CannonCtrl.bulletRot[loop].vx=RANDOM256()*16;
	CannonCtrl.bulletRot[loop].vy=RANDOM256()*16;
	CannonCtrl.bulletRot[loop].vz=RANDOM256()*16;

	CannonCtrl.bulletRotAdd[loop].vx=RANDOM256();
	CannonCtrl.bulletRotAdd[loop].vy=RANDOM256();
	CannonCtrl.bulletRotAdd[loop].vz=RANDOM256();

	CannonCtrl.bulletVel[loop].vx=tempVec.vx;
	CannonCtrl.bulletVel[loop].vy=tempVec.vy;
	CannonCtrl.bulletVel[loop].vz=tempVec.vz;

	CannonCtrl.bulletModel[loop]=pBoulderPSA;

	BoulderColl[loop].radius=BoulderBallPhysics.radius;
	BoulderColl[loop].pVel=&CannonCtrl.bulletVel[loop];
	BoulderColl[loop].pPos=&CannonCtrl.bulletPos[loop];
	BoulderColl[loop].physics=&CannonBallPhysics;

	BoulderColl[loop].oldPos = CannonCtrl.bulletPos[loop];
	BoulderColl[loop].oldVel = CannonCtrl.bulletVel[loop];
}

/////////////////////////////////////////////////////////////////////////////////////////////

void	updateShots(void)
{
LONG	loop,mag;
VECTOR	tempVec;

	loop=0;
	for (loop=0;loop<10;loop++)
	{
		if (CannonCtrl.alive[loop])
		{
			CannonCtrl.bulletModel[loop]->position.vx=CannonCtrl.bulletPos[loop].vx/4096;
			CannonCtrl.bulletModel[loop]->position.vy=CannonCtrl.bulletPos[loop].vy/4096;
			CannonCtrl.bulletModel[loop]->position.vz=CannonCtrl.bulletPos[loop].vz/4096;
			CannonCtrl.bulletModel[loop]->world.rotate.vx=CannonCtrl.bulletRot[loop].vx;
			CannonCtrl.bulletModel[loop]->world.rotate.vy=CannonCtrl.bulletRot[loop].vy;
			CannonCtrl.bulletModel[loop]->world.rotate.vz=CannonCtrl.bulletRot[loop].vz;

			if (gameCtrl.gameActive!=FALSE)
			{
				CannonCtrl.bulletRot[loop].vx=(CannonCtrl.bulletRot[loop].vx+CannonCtrl.bulletRotAdd[loop].vx)&4095;
				CannonCtrl.bulletRot[loop].vy=(CannonCtrl.bulletRot[loop].vy+CannonCtrl.bulletRotAdd[loop].vy)&4095;
				CannonCtrl.bulletRot[loop].vz=(CannonCtrl.bulletRot[loop].vz+CannonCtrl.bulletRotAdd[loop].vz)&4095;
				CannonCtrl.bulletVel[loop].vy+=2048;
			}
			if (CannonCtrl.bulletPos[loop].vy<-80) CannonCtrl.alive[loop]=FALSE;

			objectSetAnimation(CannonCtrl.bulletModel[loop], 0);
			objectDraw(CannonCtrl.bulletModel[loop]);

			if (gameCtrl.gameActive!=FALSE) ADDVECTOR(&CannonCtrl.bulletPos[loop],&CannonCtrl.bulletPos[loop],&CannonCtrl.bulletVel[loop]);
			CannonCtrl.alive[loop]++;
			if ( collboxCheckSphere(&BoulderColl[loop]) )
			{
				CannonCtrl.alive[loop]=0;
				// put check for hit glove here
				tempVec.vx=CannonCtrl.bulletModel[loop]->position.vx<<12;
				tempVec.vy=CannonCtrl.bulletModel[loop]->position.vy<<12;
				tempVec.vz=CannonCtrl.bulletModel[loop]->position.vz<<12;
				New_Debris(DEBRIS_CANNON,&tempVec,1024);

				tempVec.vx-=glovePos.vx;
				tempVec.vy-=glovePos.vy;
				tempVec.vz-=glovePos.vz;
				mag=Magnitude(&tempVec);
				if (mag< (GloveBehaviour.radius*4) )
				{
					GloveCtrl.deathType=HURTFALL;
					GloveCtrl.hurtFlag=TRUE;
				}
				tempVec.vx=(CannonCtrl.bulletModel[loop]->position.vx<<12)-ballPos.vx;
				tempVec.vy=(CannonCtrl.bulletModel[loop]->position.vy<<12)-ballPos.vy;
				tempVec.vz=(CannonCtrl.bulletModel[loop]->position.vz<<12)-ballPos.vz;
				mag=Magnitude(&tempVec);
				MakeUnit(&tempVec);
				
				if (mag< (GloveBehaviour.radius*4) )
				{
					if (GloveCtrl.cameoDisableDamage) BallCtrl.health--;
					BallCtrl.hurt=TRUE;
					ballVel.vx+=tempVec.vx;
					ballVel.vz+=tempVec.vz;
					ballVel.vy-=10*4096;
					if (BallCtrl.health==0)
					{
						GloveCtrl.deathTypeBall=DEADFROMBALLBURST;
						GloveCtrl.hurtFlagBall=TRUE;
					}
				}
			}
		}
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////
void handKillGlove()
{

	DB ("hand kill glove\n");

// Don't kill the glove on bonus levels. The fadeout and the level quit are dealt with at the start of the fall,
// coz it works better that way
	if(gameInfo.levelType==BONUS_LEVEL)
	{
// This is necessary here as well as at the fall start, to deal with spbonus, where you die from spikes/lava
		if(!gameCtrl.dropOutFlag)
		{
			MenuFadeOut();
			gameCtrl.dropOutFlag=GAME_FAILEDBONUS;
			NextLevelBasics();
		}
		return;
	}

	if(!(cheatActivated & INFINITE_LIVES_CHEAT))
	{
		GloveCtrl.lives--;
	}

	GloveCtrl.dieCount=255;		// nasty but stops chicken and egg problem
	if (GloveCtrl.lives>250) // no (ubyte check for overflow)
	{
		gameCtrl.dropOutFlag=TRUE;
		MenuFadeOut();
		showGameOver=255;
		DB("game over\n");
	}
	else {gameInfo.mode=GAMEMODE_RESTART;DB ("life over\n");}

}

void handHurtGlove(int deathreason)
{
	DB ("hand hurt glove\n");
	sfxPlay3D(globalFX,SFX_HAND2_HURT1 + (RANDOM256() & 3),&glovePos);	// "hand2" hurts are the "ow" ones

	if(!(cheatActivated & INFINITE_ENERGY_CHEAT))
	{
		GloveCtrl.health--;
		GloveCtrl.healthChange=TRUE;
	}
	if(!GloveCtrl.health)
	{
		GloveCtrl.deathType = deathreason;



// It works better here that at "HandKillGlove"
		if(gameInfo.levelType==BONUS_LEVEL)
		{
			if(!gameCtrl.dropOutFlag)
			{
				MenuFadeOut();
				gameCtrl.dropOutFlag=GAME_FAILEDBONUS;
				NextLevelBasics();
			}
			return;
		}

		switch (deathreason)
		{
			case DEADFROMFALLOFF:	// "arrrrrggghhhh" sfx has already been played
				break;

			case HURTFALL:
			case HURTPAIN:
			case DEADFROMPAIN:
			case DEADFROMFALL:
			case DEADFROMBALLFALLOFF:
			case DEADFROMBALLBURST:
			default:
				sfxPlay3D(globalFX,SFX_HAND2_DIE1 + (RANDOM256() % 3),&glovePos);
				break;

		}
	}
}
