/******************************************************************************************
	CRTest PS   (c) 1999-2001 ISL

	catapult.c:			Specialist code for the level 2 catapult-style games
******************************************************************************************/


#define MAP_SCALE_ADJUST 8


#include "global.h"
#include "main.h"
#include "menu.h"
#include "map_draw.h"
#include "bff_load.h"
#include "collide.h"
#include "debris.h"
#include "lights.h"
#include "timer.h"
#include "maths.h"
#include "overlays.h"
#include "fx.h"
#include "powerbar.h"
#include "catapult.h"
#include "seesaw.h"
#include "demo.h"
#include "map_view.h"
#include "ranges.h"
//#include "text_ids.h"
#include "gametext.h"
#include "charactr.h"
#include "deth.h"
#include "enemies.h"
#include "dualshock.h"
#include <psitypes.h>
#include "map_play.h"
#include "subgame.h"
#include "card.h" 
#include "sound.h"
#include "loadsnd.h"
#include "startup.h"

#ifdef DEBUG	// Make double sure that debugging stuff isn't enabled on a cd build ..OK
	//#define CATAPULT_VIEW_DRONE_MODES
	//#define CATAPULT_VIEW_POS
	//#define DEBUG_CONTROLS_ON	
#endif

								//80
#define CAT_COUNTDOWN_TIME	     80
#define CAT_NUM_CHICKENS_BRONZE_SUCCESS 20
#define CAT_NUM_CHICKENS_SILVER_SUCCESS 25
#define CAT_NUM_CHICKENS_GOLD_SUCCESS   30


#define CATAPULT_VIEW_CRATE


#define CAT_CAMX_START	   0
#define CAT_CAMY_START	   -9869
#define CAT_CAMZ_START	   -10630
#define CAT_GARIBX_START   0
#define CAT_GARIBY_START   -6314
#define CAT_GARIBZ_START   -4002

#define CAT_DEVICE_XPOS    -182
#define CAT_DEVICE_YPOS	   60
#define CAT_DEVICE_ZPOS	   -167

#define CAT_FLOATER1_XPOS   -2951   
#define CAT_FLOATER1_YPOS	200
#define CAT_FLOATER1_ZPOS	10684

#define CAT_FLOATER2_XPOS	2350
#define CAT_FLOATER2_YPOS	200
#define CAT_FLOATER2_ZPOS	10282

#define CAT_FLOATER3_XPOS	1158
#define CAT_FLOATER3_YPOS	200
#define CAT_FLOATER3_ZPOS	13712

#define CAT_DRONE_WAIT_XPOS  3320
#define CAT_DRONE_WAIT_YPOS  0
#define CAT_DRONE_WAIT_ZPOS  463

#define CAT_DRONE_OFFSCREEN_XPOS  5320

#define CAT_WINDER_XPOS  1297
#define CAT_WINDER_YPOS	 0
#define CAT_WINDER_ZPOS	 1671



#define CAT_WATER_HEIGHT  800

#define CATAPULT_FLOATER_ANIM_SPEED  90



#define NUM_FLOATER_POINTS 10
VECTOR floaterPoints[NUM_FLOATER_POINTS] = 
{
	{-4833, 1400, 10376},
	{-3645, 1400, 12982},
	{-914, 1400,  13061},
	{1752, 1400,  13529},
	{4595, 1400,  12330},
	{4809, 1400,  10977},
	{2682, 1400,  9931},
	{98, 1400,    9092},
	{-3066, 1400, 9945},
	{-4281, 1400, 10276},
};

//int heightOfFloaters = 1000;

#define MYFOV  830 //MIKEY
//int MYFOV  680;


int floaterRotSpeeds[NUM_FLOATER_POINTS] = { -150, -60, 50, -80, 110, -130, -50, -50, 75, -70};

extern ACTOR *myactor;

catStr *cat;


// ============================================

#define CAT_CRICKET_X  -228
#define CAT_CRICKET_Y  -110


// ============================================

PSIMODEL	*testchar_model;  // ?
ACTOR		*testchar_actor;  // ?

#define FLOATER_REQUIRED_DIST	500
#define FLOATER_INERTIA			3900
#define FLOATER_ACC				4

#define FLOATER_WOBBLE_SPEED	100
#define FLOATER_WOBBLE_STRENGTH 50

#define CAT_DEVICE_ROT_FACTOR	16

#define FLOATER_HEIGHT			-1200


#define FLOATERS_ANIM_TIME = 4864;
#define CAT_DRONE_BOB_FACTOR  = 400;


#define RIPPLE_SIZE_START  40
#define RIPPLE_DSIZE       5
#define RIPPLES_SIDEWAYS_SCALE  60000
#define RIPPLE_LIFE        45

#define WAKE_RIPPLE_SIZE_START  40
#define WAKE_RIPPLE_DSIZE       10
#define WAKE_RIPPLE_LIFE        40


//int MYX = 0;
//int MYY = 0;
//int MYZ = 0;


void catFloaterUpdate()
{
	static VECTOR org = {0,0,0};

	VECTOR v, v2;
	int i;
	long dist;

	catFloaterStr *flotsam;

	for(i=0; i<CAT_NUM_FLOATERS; i++)
	{
		flotsam = &cat->floaters[i];


		flotsam->wobble += FLOATER_WOBBLE_SPEED;

		if(flotsam->wobble >= 4096)
			flotsam->wobble -= 4096;

		flotsam->actor->psiData.object->rotate.vx = FLOATER_WOBBLE_STRENGTH * rcos(flotsam->wobble) / 4096;
		flotsam->actor->psiData.object->rotate.vz = FLOATER_WOBBLE_STRENGTH * rsin(flotsam->wobble) / 4096;


		if(flotsam->targetyRotSpeed != 0)
			flotsam->targetyRotSpeed = flotsam->targetyRotSpeed * 96 / 100;

		if(flotsam->yRotSpeed != 0)
		{

			flotsam->yRot += flotsam->yRotSpeed;
			if(flotsam->yRot < 0)
				flotsam->yRot += 4096;
			else if(flotsam->yRot > 4096)
				flotsam->yRot -= 4096;

			flotsam->actor->psiData.object->rotate.vy = flotsam->yRot;
		}

		if(flotsam->yRotSpeed != flotsam->targetyRotSpeed)
		{
			dist = flotsam->targetyRotSpeed - flotsam->yRotSpeed;
			
			
			// change this
			if(dist > 0)
				flotsam->yRotSpeed += 1;
			else
				flotsam->yRotSpeed -= 1;
		}
			
		if((cat->state == CAT_STATE_RUNNING) || (cat->state == CAT_STATE_FINISH))
		{
			SUBVECTOR(&v, &floaterPoints[flotsam->point], &flotsam->pos);

			dist = Magnitude2D(v.vx, v.vz);

			if(dist < FLOATER_REQUIRED_DIST)
			{
				// Change target point
				flotsam->point++;
				if( flotsam->point >= NUM_FLOATER_POINTS)
					flotsam->point = 0;
				
				flotsam->targetyRotSpeed = floaterRotSpeeds[flotsam->point];
				continue;
			}

			if(dist < 2)
				dist = 2;

			SCALEVECTOR(&v, FLOATER_ACC*4096/dist);
			ADDTOVECTOR(&flotsam->vel, &v);
			SCALEVECTOR(&flotsam->vel, FLOATER_INERTIA);
			ADDTOVECTOR(&flotsam->pos, &flotsam->vel);
			flotsam->actor->position = flotsam->pos;
		}



		if(flotsam->active > 0)
		{
			long t[3];

			PSIOBJECT *child, *parent;
			VECTOR childPos, parentPos;
			// calculate chickenpos
			// temp

			actorSetAnimation(flotsam->actor, flotsam->actor->animation.animData[0].actualFrame);

			parent = flotsam->actor->psiData.object;
			child = psiObjectScan(parent, "THEOBJECT");

			ASSERT(child);

		  	t[0] = GsWSMATRIX.t[0];
			t[1] = GsWSMATRIX.t[1];
			t[2] = GsWSMATRIX.t[2];
			GsWSMATRIX.t[0] = 0;
			GsWSMATRIX.t[1] = 0;
			GsWSMATRIX.t[2] = 0;
			gte_SetTransMatrix(&GsWSMATRIX);

			if((parent->rotate.vx) || (parent->rotate.vy) || (parent->rotate.vz))
			{
				MATRIX		rotmat1;
				RotMatrixYXZ_gte(&parent->rotate,&rotmat1);

				gte_SetRotMatrix(&rotmat1);
	//			gte_SetTransMatrix	// not doing an rtirtr, so we don't need so set the tx to zero
				gte_ldlvl(&parent->matrix.t);
				gte_rtir();
				gte_stlvl(&parent->matrix.t);
			}

			parent->matrix.t[0] += flotsam->actor->position.vx;
			parent->matrix.t[1] += flotsam->actor->position.vy;	// + (37<<3);
			parent->matrix.t[2] += flotsam->actor->position.vz;


			// SL: setup the scale global, before we do the local matrix thing...
			PSIrootScale = &parent->scale;

			// SL: transform the bones in model space...
			psiCalcLocalMatrix(parent);

//			gte_SetRotMatrix(&parent->matrixscale);
//			gte_SetTransMatrix(&parent->matrixscale);

//			gte_ldlvl(&org);	// long t[3]
//			gte_rtirtr();
//			gte_stlvl(&parentPos);

			gte_SetRotMatrix(&child->matrixscale);
			gte_SetTransMatrix(&child->matrixscale);

			gte_ldlvl(&org);	
			gte_rtirtr();
			gte_stlvl(&childPos);

//			if(i == 0 && pReadPad->digital[0] & PAD_CIRCLE)
//			{
				//DB("..\nactor: %d,%d,%d\n", flotsam->actor->position.vx, flotsam->actor->position.vy, flotsam->actor->position.vz);
//				DB("..\paren: %d,%d,%d\n", parentPos.vx, parentPos.vy, parentPos.vz);
//				DB("child: %d,%d,%d\n", childPos.vx, childPos.vy, childPos.vz);
//				DB("chick: %d,%d,%d\n", flotsam->chickenPos.vx, flotsam->chickenPos.vy, flotsam->chickenPos.vz);
//			}
//			if(i == 0 && pReadPad->digital[0] & PAD_TRIANGLE)
//			{
				flotsam->chickenPos = childPos;
//				flotsam->chickenPos.vx += MYX;
//				flotsam->chickenPos.vy += MYY;
//				flotsam->chickenPos.vz += MYZ;
//			}

	GsWSMATRIX.t[0] = t[0];
	GsWSMATRIX.t[1] = t[1];
	GsWSMATRIX.t[2] = t[2];



		}

		if(random(500) < 10)
		{
			v = flotsam->vel;
			SCALEVECTOR(&v, RIPPLES_SIDEWAYS_SCALE);
			//RotateVector2D(&v2,&v, 3080);

			if(flotsam->point < 6)
				RotateVector2D(&v, &v,1024);
			else
				RotateVector2D(&v, &v,3080);


			ADDTOVECTOR(&v, &flotsam->actor->position);
			//ADDTOVECTOR(&v2, &flotsam->actor->position);

			v.vy = v2.vy = CAT_WATER_HEIGHT;
			//debrisNewBigWaterSplash(&v);

			debrisNewGenericWaterSplash(ripple, &v, WAKE_RIPPLE_SIZE_START, WAKE_RIPPLE_DSIZE, WAKE_RIPPLE_LIFE);
//			debrisNewGenericWaterSplash(ripple, &v2, RIPPLE_SIZE_START, RIPPLE_DSIZE, RIPPLE_LIFE);

//			v.vx = 0;
//			v.vz = 12000;
//			debrisNewBigWaterSplash(&v);
			//debrisNewWaterSplash(&v);

			//debrisDust(&v, 10 , 1024);
		}


		//flotsam->actor->position.vy = heightOfFloaters;

	}
}



// ============================================
void catapultStart()
{
	subGameRestart = FALSE;


	// load sound bank here
	loadsndLoadBank("A2_CATAPULT");
	mapviewLoadMap("A2_CATAPULT");

	draw_routine = catapultDraw;
	cycle_routine = catapultCycle;

	cat = (catStr*)MALLOC(sizeof(catStr));
	memset(cat, 0, sizeof(catStr));

	if(gameCalledFrom != GAMECALLEDFROM_DEBUG)
	{
		if(!gameSaveData.levels_available[REPLAY_AVAILABLE_CATAPULT])
		{
			gameSaveData.levels_available[REPLAY_AVAILABLE_CATAPULT] = REPLAY_NOTBEATEN;
		}
	}


	cat->state = CAT_STATE_FADEIN;
	cat->frameCount = 0;


//	debrisInit();	// RFW - done inside mapviewLoadMap

//	nmeDogEnsureHourglass();
	initStopWatch(164, -70, MYFOV);
	initFowler(MYFOV);


	loadsndSubGames(LEVNUMBER_A2_CATAPULT, cat->pSamples, NUM_CATAPULT_SAMPLES);



	mycamera.vpx =  CAT_CAMX_START;//0;//+aimLine.vx;
	mycamera.vpy = CAT_CAMY_START;//-6854;
	mycamera.vpz = CAT_CAMZ_START;//-11573;//+aimLine.vz;

	mycamera.vrx = CAT_GARIBX_START;//0;								    
	mycamera.vry = CAT_GARIBY_START;//-4084;
	mycamera.vrz = CAT_GARIBZ_START;//-4894;


	// Load Catapult
	cat->device.model = BFF_IsModelLoaded("DEVICE");
	ASSERT(cat->device.model);
	cat->device.actor = actorCreate(cat->device.model);
	ASSERT(cat->device.actor);
	actorInitAnim(cat->device.actor);	
	ASSERT(cat->device.actor);


	cat->countdown = CAT_COUNTDOWN_TIME * FRAMESEC;

	cat->device.actor->position.vx = CAT_DEVICE_XPOS;
	cat->device.actor->position.vy = CAT_DEVICE_YPOS;
	cat->device.actor->position.vz = CAT_DEVICE_ZPOS;


	actorAnimate(cat->device.actor, CATAPULT_FIRE, FALSE, FALSE, 0, FALSE, 0);

	catDeviceUpdate();

	cat->device.nextDrone = -1;




	cat->drones[0].model = BFF_IsModelLoaded("SUB1");//DRONE1");
	ASSERT(cat->drones[0].model);
	cat->drones[0].actor = actorCreate(cat->drones[0].model);
	ASSERT(cat->drones[0].actor);
	actorInitAnim(cat->drones[0].actor);	
	ASSERT(cat->drones[0].actor);

	cat->drones[0].state = CAT_DRONE_ONDEVICE;


	cat->drones[0].actor->position.vx = CAT_DRONE_WAIT_XPOS;
	cat->drones[0].actor->position.vy = CAT_DRONE_WAIT_YPOS;
	cat->drones[0].actor->position.vz = CAT_DRONE_WAIT_ZPOS;


	actorAnimate(cat->drones[0].actor, DRONE_DOWN_FLAPPING, FALSE, FALSE, 256, FALSE, 0);       
	actorAnimate(cat->drones[0].actor, DRONE_LAND_ON_SEESAW, FALSE, TRUE, 256, FALSE, 0);       
	actorAnimate(cat->drones[0].actor, DRONE_SEESAW_GULP, FALSE, TRUE, 256, FALSE, 0);       
	actorAnimate(cat->drones[0].actor, DRONE_SEESAW_COVER_EYES, FALSE, TRUE, 256, FALSE, 0);       


	cat->drones[1].model = BFF_IsModelLoaded("SUB2");//DRONE2");
	ASSERT(cat->drones[1].model);
	cat->drones[1].actor = actorCreate(cat->drones[1].model);
	ASSERT(cat->drones[1].actor);
	actorInitAnim(cat->drones[1].actor);	
	ASSERT(cat->drones[1].actor);


	cat->drones[1].actor->position.vx = CAT_DRONE_OFFSCREEN_XPOS;
	cat->drones[1].actor->position.vy = CAT_DRONE_WAIT_YPOS;
	cat->drones[1].actor->position.vz = CAT_DRONE_WAIT_ZPOS;



	cat->drones[2].model = BFF_IsModelLoaded("SUB3");//DRONE3");
	ASSERT(cat->drones[2].model);
	cat->drones[2].actor = actorCreate(cat->drones[2].model);
	ASSERT(cat->drones[2].actor);
	actorInitAnim(cat->drones[2].actor);	
	ASSERT(cat->drones[2].actor);

	cat->drones[2].actor->position.vx = CAT_DRONE_OFFSCREEN_XPOS;
	cat->drones[2].actor->position.vy = CAT_DRONE_WAIT_YPOS;
	cat->drones[2].actor->position.vz = CAT_DRONE_WAIT_ZPOS;



	cat->drones[3].model = BFF_IsModelLoaded("SUB1");//DRONE4");
	ASSERT(cat->drones[3].model);
	cat->drones[3].actor = actorCreate(cat->drones[3].model);
	ASSERT(cat->drones[3].actor);
	actorInitAnim(cat->drones[3].actor);	
	ASSERT(cat->drones[3].actor);

	cat->drones[3].actor->position.vx = CAT_DRONE_OFFSCREEN_XPOS;
	cat->drones[3].actor->position.vy = CAT_DRONE_WAIT_YPOS;
	cat->drones[3].actor->position.vz = CAT_DRONE_WAIT_ZPOS;


	cat->drones[4].model = BFF_IsModelLoaded("SUB4");//DRONE2");
	ASSERT(cat->drones[4].model);
	cat->drones[4].actor = actorCreate(cat->drones[4].model);
	ASSERT(cat->drones[4].actor);
	actorInitAnim(cat->drones[4].actor);	
	ASSERT(cat->drones[4].actor);

	cat->drones[4].actor->position.vx = CAT_DRONE_OFFSCREEN_XPOS;
	cat->drones[4].actor->position.vy = CAT_DRONE_WAIT_YPOS;
	cat->drones[4].actor->position.vz = CAT_DRONE_WAIT_ZPOS;




/*
	cat->device.winderModel = BFF_IsModelLoaded("CRANKER");
	ASSERT(cat->device.winderModel);
	cat->device.winderActor = actorCreate(cat->device.winderModel);
	ASSERT(cat->device.winderActor);
	actorInitAnim(cat->device.winderActor);	


	cat->device.winderActor->psiData.object->rotate.vy = 1024;

	cat->device.winderActor->position.vx = CAT_WINDER_XPOS;
	cat->device.winderActor->position.vy = CAT_WINDER_YPOS;
	cat->device.winderActor->position.vz = CAT_WINDER_ZPOS;

*/

	cat->floaters[0].model = BFF_IsModelLoaded("CRATE");//
	ASSERT(cat->floaters[0].model);
	cat->floaters[0].actor = actorCreate(cat->floaters[0].model);
	ASSERT(cat->floaters[0].actor);
	actorInitAnim(cat->floaters[0].actor);	
	actorAnimate(cat->floaters[0].actor, CATAPULT_FLOATER_BOB, TRUE, FALSE, 89, FALSE, 0);


	//cat->floaters[0].actor->position.vx = CAT_FLOATER1_XPOS;
	//cat->floaters[0].actor->position.vy = CAT_FLOATER1_YPOS;
	//cat->floaters[0].actor->position.vz = CAT_FLOATER1_ZPOS;
	cat->floaters[0].point = 0;
	cat->floaters[0].pos = floaterPoints[9];
	cat->floaters[0].actor->position = floaterPoints[9];
	cat->floaters[0].wobble = 1400;
	cat->floaters[0].droneOn = -1;
	cat->floaters[0].yRot = 300;


	cat->floaters[1].model = BFF_IsModelLoaded("OILDRUM");
	ASSERT(cat->floaters[1].model);
	cat->floaters[1].actor = actorCreate(cat->floaters[1].model);
	ASSERT(cat->floaters[1].actor);


	actorInitAnim(cat->floaters[1].actor);	
	actorAnimate(cat->floaters[1].actor, CATAPULT_FLOATER_BOB, TRUE, FALSE, 82, FALSE, 0);

//	cat->floaters[1].actor->position.vx = CAT_FLOATER2_XPOS;
//	cat->floaters[1].actor->position.vy = CAT_FLOATER2_YPOS;
//	cat->floaters[1].actor->position.vz = CAT_FLOATER2_ZPOS;
	cat->floaters[1].point = 8;
	cat->floaters[1].pos = floaterPoints[7];
	cat->floaters[1].actor->position = floaterPoints[7];

	cat->floaters[1].wobble = 200;
	cat->floaters[1].droneOn = -1;
	cat->floaters[1].yRot = 1100;



	cat->floaters[2].model = BFF_IsModelLoaded("BARREL");
	ASSERT(cat->floaters[2].model);
	cat->floaters[2].actor = actorCreate(cat->floaters[2].model);
	ASSERT(cat->floaters[2].actor);
	actorInitAnim(cat->floaters[2].actor);	
	actorAnimate(cat->floaters[2].actor, CATAPULT_FLOATER_BOB, TRUE, FALSE, 75, FALSE, 0);

//	cat->floaters[2].actor->position.vx = CAT_FLOATER3_XPOS;
//	cat->floaters[2].actor->position.vy = CAT_FLOATER3_YPOS;
//	cat->floaters[2].actor->position.vz = CAT_FLOATER3_ZPOS;
	cat->floaters[2].point = 3;
	cat->floaters[2].pos = floaterPoints[2];
	cat->floaters[2].actor->position = floaterPoints[2];

	cat->floaters[2].wobble = 3100;
	cat->floaters[2].droneOn = -1;
	cat->floaters[2].yRot = 1500;



	cat->floaters[3].model = BFF_IsModelLoaded("CRATE");
	ASSERT(cat->floaters[3].model);
	cat->floaters[3].actor = actorCreate(cat->floaters[0].model);
	ASSERT(cat->floaters[3].actor);
	actorInitAnim(cat->floaters[3].actor);	
	actorAnimate(cat->floaters[3].actor, CATAPULT_FLOATER_BOB, TRUE, FALSE, 95, FALSE, 0);
	cat->floaters[3].droneOn = -1;


	//cat->floaters[0].actor->position.vx = CAT_FLOATER1_XPOS;
	//cat->floaters[0].actor->position.vy = CAT_FLOATER1_YPOS;
	//cat->floaters[0].actor->position.vz = CAT_FLOATER1_ZPOS;
	cat->floaters[3].point = 5;
	cat->floaters[3].pos = floaterPoints[4];
	cat->floaters[3].actor->position = floaterPoints[4];

	cat->floaters[3].wobble = 400;
	cat->floaters[3].yRot = 3000;


	pReadPad->shockEnable=1;
	dsEvent_Init();



	PSImodelctrl.farclip =  1023;
	max_map_ot_depth = 1023;

	subgameInitPowerBar();

	initCricketScores(CAT_CRICKET_X, CAT_CRICKET_Y, CAT_NUM_CHICKENS_BRONZE_SUCCESS, CAT_NUM_CHICKENS_SILVER_SUCCESS, CAT_NUM_CHICKENS_GOLD_SUCCESS, 2);


	myactor = cat->drones[0].actor;
}


int CAT_CAM_ROT_FACTOR = 128;

void catUpdateCamAim()
{
	int camRot;
	VECTOR pos = {(CAT_CAMX_START - CAT_DEVICE_XPOS), CAT_CAMY_START, (CAT_CAMZ_START - CAT_DEVICE_ZPOS)};
	VECTOR gar = {(CAT_GARIBX_START - CAT_DEVICE_XPOS), CAT_GARIBY_START, ( CAT_GARIBZ_START - CAT_DEVICE_ZPOS)};

	camRot = (cat->device.yRot * CAT_CAM_ROT_FACTOR)/4096;

	RotateVector2D(&pos, &pos, camRot);
	mycamera.vpx = pos.vx + cat->device.actor->position.vx;
	mycamera.vpy = pos.vy;
	mycamera.vpz = pos.vz + cat->device.actor->position.vz;

	RotateVector2D(&pos, &pos, camRot);
	mycamera.vrx = gar.vx + cat->device.actor->position.vx;
	mycamera.vry = gar.vy;
	mycamera.vrz = gar.vz + cat->device.actor->position.vz;

}




int CAT_HG = 200;


int CAT_INRO_TEXT_XPOS = -130;
#define CAT_PB_XPOS -225
int CAT_CHICKENS_FREED_XPOS = -236;

#if PALMODE==1
  #define CAT_PB_YPOS 74
  int CAT_CHICKENS_FREED_YPOS = -120;
#else
  #define CAT_PB_YPOS 60
  int CAT_CHICKENS_FREED_YPOS = -105;
#endif

int CAT_POWER_RANGE = 174;



/*
(draw actor 1)

	temp = modctrl->depthoverride;

	depth_of_actor1 = actor->psiData.object->depth;	// (Calculated in psiDrawSegments (custom.c))

	modctrl->depthoverride = depth_of_actor1 - 20;	// 20 should do the job
	if(modctrl->depthoverride <1)
		modctrl->depthoverride = 1;	// coz zero means "don't", and -ves will probably crash

(draw actor 2)

	modctrl->depthoverride = temp;

*/

void catapultDraw(void)
{
	VECTOR	aimLine;
	VECTOR	corners[4];
	int prev_lighting, i;

	int temp;
//	int depth_floater;
	PSIMODELCTRL		*modctrl = &PSImodelctrl;



	max_map_ot_depth = 1023;

	GsSetProjection(MYFOV);


//	actorMaintainAnimation(cat->device.actor);
//	actorMaintainAnimation(cat->floaters[0].actor);
//	actorMaintainAnimation(cat->floaters[1].actor);
//	actorMaintainAnimation(cat->floaters[2].actor);
//	actorMaintainAnimation(cat->floaters[3].actor);


	mapCamSetRefView2L(&mycamera);
	MapDraw_DrawFMA_World((FMA_WORLD2 *)mapview_fma_world);
//	catapultPrintDebugText();



	
	prev_lighting = PSImodelctrl.lighting;
	PSImodelctrl.lighting = NOLIGHTING;

	// Gourad Shaded
//	EXLIGHT_SetupActorLights(cat->floaters[0].actor);
#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(cat->floaters[0].actor);
	else
		d2mActorDraw(cat->floaters[0].actor);
#else
		actorDraw(cat->floaters[0].actor);
#endif

//	EXLIGHT_SetupActorLights(cat->floaters[1].actor);
#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(cat->floaters[1].actor);
	else
		d2mActorDraw(cat->floaters[1].actor);
#else
		actorDraw(cat->floaters[1].actor);
#endif

//	EXLIGHT_SetupActorLights(cat->floaters[2].actor);
#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(cat->floaters[2].actor);
	else
		d2mActorDraw(cat->floaters[2].actor);
#else
		actorDraw(cat->floaters[2].actor);
#endif
//		EXLIGHT_SetupActorLights(cat->floaters[2].actor);
#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(cat->floaters[3].actor);
	else
		d2mActorDraw(cat->floaters[3].actor);
#else
		actorDraw(cat->floaters[3].actor);
#endif

	PSImodelctrl.lighting = prev_lighting;


	

///	EXLIGHT_SetupActorLights(cat->device.actor);
///	actorDraw(cat->device.actor);
	
	for(i=0;i<CAT_NUM_DRONES; i++)
	{

		if(cat->drones[i].state != CAT_DRONE_INACTIVE)
		{
			//actorMaintainAnimation(cat->drones[i].actor);
			EXLIGHT_SetupActorLights(cat->drones[i].actor);

	#ifdef _WINDOWS
		if (!runningHard)
			actorDraw(cat->drones[i].actor);
		else
			d2mActorDraw(cat->drones[i].actor);
	#else

			if((cat->drones[i].state != CAT_DRONE_CRASHING))//(cat->drones[i].state == CAT_DRONE_LANDED) || (cat->drones[i].state == CAT_DRONE_LANDING) || (cat->drones[i].state == CAT_DRONE_ONDEVICE))

			{
				temp = modctrl->depthoverride;
//				depth_floater = cat->floaters[cat->drones[i].floater].actor->psiData.object->depth;	// (Calculated in psiDrawSegments (custom.c))
				modctrl->depthoverride = 40;//depth_floater - 40;	// 20 should do the job
				if(modctrl->depthoverride <1)
					modctrl->depthoverride = 1;	// coz zero means "don't", and -ves will probably crash

				actorDraw(cat->drones[i].actor);
				modctrl->depthoverride = temp;
			}
			else
				actorDraw(cat->drones[i].actor);
	#endif
			
		}
	}
	EXLIGHT_SetupActorLights(cat->device.actor);
#ifdef _WINDOWS
	if (!runningHard)
		actorDraw(cat->device.actor);
	else
		d2mActorDraw(cat->device.actor);
#else
		actorDraw(cat->device.actor);
#endif


	debrisDraw();


	if(cat->state == CAT_STATE_RUNNING)
		drawStopWatch(4096 - ((4096*cat->countdown)/(CAT_COUNTDOWN_TIME * FRAMESEC)));
	else
		drawStopWatch(0);


	switch(cat->state)
	{
		case CAT_STATE_FADEIN:  
			i= 256 - (cat->frameCount)*10;
			if(i <= 0)
				cat->state = CAT_STATE_INTRO;
			else
				deathScreenAdd(i, i, i, SEMITRANS_SUB, 2);

			break;	

		case CAT_STATE_INTRO:
			catDrawIntro();
			break;	
	
		case CAT_STATE_FINISH:			  
			fontPrintCentred(font, 0, 0, (char*)TEXTSTR(TEXTSTR_SUB_CAT_FINISH), 128, 128 , 128);


		case CAT_STATE_RUNNING:
			subgameDrawPowerBar(CAT_PB_XPOS, CAT_PB_YPOS, 4096 * (cat->device.power + CAT_POWER_RANGE) / (2 * CAT_POWER_RANGE));
			drawCricketScores(CAT_CRICKET_X, CAT_CRICKET_Y, cat->numChickensSaved);
			break;	


		case CAT_STATE_BRONZE_SUCCESS:
			catDrawBronzeSuccess();
			fowlerDraw();
			break;	

		case CAT_STATE_SILVER_SUCCESS:
			catDrawSilverSuccess();
			fowlerDraw();
			break;	

		case CAT_STATE_GOLD_SUCCESS:
			catDrawGoldSuccess();
			fowlerDraw();
			break;	


		case CAT_STATE_FAIL:
			catDrawFail();
			fowlerDraw();
			break;	

		case CAT_STATE_FADEOUT:
			i= (cat->frameCount)*20;
			if(i > 230)
				deathScreenAdd(255, 255, 255, SEMITRANS_SUB, 0);

			if(i >=255)
			{
				catapultEnd();
			}
			else
				deathScreenAdd(i, i, i, SEMITRANS_SUB, 0);

			break;	
	}

}



void catapultCycle(void)
{
	int i;


	debrisCycle();
	catFloaterUpdate();
	catDronesUpdate();

	
	actorMaintainAnimation(cat->device.actor);
	actorMaintainAnimation(cat->floaters[0].actor);
	actorMaintainAnimation(cat->floaters[1].actor);
	actorMaintainAnimation(cat->floaters[2].actor);
	actorMaintainAnimation(cat->floaters[3].actor);


	for(i=0;i<CAT_NUM_DRONES; i++)
	{
		if(cat->drones[i].state != CAT_DRONE_INACTIVE)
		{
			actorMaintainAnimation(cat->drones[i].actor);
		}
	}


	cat->frameCount++;

	switch(cat->state)
	{
		case CAT_STATE_FADEIN:
			break;	
	
		case CAT_STATE_INTRO:
			if(pReadPad->debounce[0] & PAD_CROSS)
				cat->state = CAT_STATE_RUNNING;
			else if(pReadPad->debounce[0] & PAD_TRIANGLE)
			{
				cat->frameCount = 1;
				cat->state = CAT_STATE_FADEOUT;
				subGameRestart = FALSE;
				return;
			}
			break;	

		case CAT_STATE_RUNNING:
			catDeviceUpdate();
			catapultControls();
			catUpdateCamAim();


			cat->countdown--;


#ifdef DEBUG
			if(SwimCheatCycle())
			{
				cat->countdown = 0;
				if(padData.digital[0] & PAD_L1)	// "L" is for "Lose"
				{
				}
				else if(padData.digital[0] & PAD_R1)	// "R" is for, ummm, "Really good win"
				{
					cat->numChickensSaved = CAT_NUM_CHICKENS_GOLD_SUCCESS;
				}
				else
				{
					cat->numChickensSaved = CAT_NUM_CHICKENS_BRONZE_SUCCESS;
				}
			}
#endif


			if(cat->countdown <= 0)
			{
				cat->countdown = 0;
				cat->state = CAT_STATE_FINISH;

				catMakeActiveChickensRunOff();
			}
//			catCountDownUpdate();






			break;	

		case CAT_STATE_FINISH:
			for(i=0; i<CAT_NUM_DRONES; i++)
				if(cat->drones[i].state != CAT_DRONE_INACTIVE)
					break;

			if(i < CAT_NUM_DRONES)
				break;


			DB("states %d %d %d %d %d\n", cat->drones[0].state, cat->drones[1].state, cat->drones[2].state, cat->drones[3].state, cat->drones[4].state);


			// If you want to give the player some rewards give them here

			if(cat->numChickensSaved >= CAT_NUM_CHICKENS_BRONZE_SUCCESS)
			{
				if(gameCalledFrom != GAMECALLEDFROM_DEBUG)
				{
					gamePlayData->SubGameStates[SUBGAME_CATAPULT] = REPLAY_BEATEN;
					gameSaveData.levels_available[REPLAY_AVAILABLE_CATAPULT] = REPLAY_BEATEN;
				}

				if(cat->numChickensSaved >= CAT_NUM_CHICKENS_GOLD_SUCCESS)
				{
					gameSaveData.medals_won[MEDAL_WON_CATAPULT] = 3;
					cat->state = CAT_STATE_GOLD_SUCCESS;
					startFowler(FOWLER_GOLD_OFFSET, 100);


	#ifndef _WINDOWS
					sound_XA_Start(TUNE_3_COMPLETE + SOUND_XA_NOLOOP);
	#endif
				}
				else if(cat->numChickensSaved >= CAT_NUM_CHICKENS_SILVER_SUCCESS)
				{
					if(gameSaveData.medals_won[MEDAL_WON_CATAPULT]<2)
						gameSaveData.medals_won[MEDAL_WON_CATAPULT] = 2;

					startFowler(FOWLER_SILVER_OFFSET, 100);

					cat->state = CAT_STATE_SILVER_SUCCESS;
	#ifndef _WINDOWS
					sound_XA_Start(TUNE_3_COMPLETE + SOUND_XA_NOLOOP);
	#endif
				}
				else if(cat->numChickensSaved >= CAT_NUM_CHICKENS_BRONZE_SUCCESS)
				{
					if(gameSaveData.medals_won[MEDAL_WON_CATAPULT]<1)
						gameSaveData.medals_won[MEDAL_WON_CATAPULT] = 1;

					startFowler(FOWLER_BRONZE_OFFSET, 100);
					cat->state = CAT_STATE_BRONZE_SUCCESS;
	#ifndef _WINDOWS
					sound_XA_Start(TUNE_3_COMPLETE + SOUND_XA_NOLOOP);
	#endif
				}
			}
			else
			{
				cat->state = CAT_STATE_FAIL;
				startFowler(FOWLER_FAIL_OFFSET, 100);

#ifndef _WINDOWS
				sound_XA_Start(TUNE_4_FAILED + SOUND_XA_NOLOOP);
#endif
			}

			cat->frameCount = 2;
			break;	

		case CAT_STATE_BRONZE_SUCCESS:
		case CAT_STATE_SILVER_SUCCESS:
		case CAT_STATE_GOLD_SUCCESS:
		case CAT_STATE_FAIL:

			if(cat->frameCount > 30)
			{
				if((pReadPad->debounce[0] & PAD_CROSS))
				{
					cat->state = CAT_STATE_FADEOUT;
					cat->frameCount = 1;
					subGameRestart = TRUE;
				}
				else if((pReadPad->debounce[0] & PAD_TRIANGLE))
				{
					cat->state = CAT_STATE_FADEOUT;
					cat->frameCount = 1;
					subGameRestart = FALSE;
				}
			}
			break;	


		case CAT_STATE_FADEOUT:
			break;	
	}

}


// ============================================
void catapultPrintDebugText(void)
{
	char strBuff[128];

	if(pReadPad->digital[0] & PAD_TRIANGLE)
	{

#ifdef CATAPULT_VIEW_POS
	sprintf(strBuff, "camPosxyz : %d,%d,%d", mycamera.vpx, mycamera.vpy, mycamera.vpz);
	fontPrint(font, -250, -120, strBuff, 128, 128, 0);

	sprintf(strBuff, "camGrbxyz : %d,%d,%d", mycamera.vrx, mycamera.vry, mycamera.vrz);
	fontPrint(font, -250, -104, strBuff, 128, 128, 0);

	sprintf(strBuff, "actorPos: %d %d %d", myactor->position.vx, myactor->position.vy, myactor->position.vz);
	fontPrint(font, -250, -84, strBuff, 128, 128, 0);



#endif

#ifdef CATAPULT_VIEW_DRONE_MODES

	
	
	sprintf(strBuff, "drone1: %d, %d", cat->drones[0].state, cat->drones[0].floater);
	fontPrint(font, -250, -120, strBuff, 128, 128, 0);

	sprintf(strBuff, "drone2: %d, %d", cat->drones[1].state, cat->drones[1].floater);
	fontPrint(font, -250, -104, strBuff, 128, 128, 0);

	sprintf(strBuff, "drone3: %d, %d", cat->drones[2].state, cat->drones[2].floater);
	fontPrint(font, -250, -84, strBuff, 128, 128, 0);

	sprintf(strBuff, "drone4: %d, %d", cat->drones[3].state, cat->drones[3].floater);
	fontPrint(font, -250, -68, strBuff, 128, 128, 0);

#endif



#ifdef CATAPULT_VIEW_CRATE

	sprintf(strBuff, "crate : %d,%d,%d state %d", (int)cat->floaters[2].pos.vx, (int)cat->floaters[2].pos.vy, (int)cat->floaters[2].pos.vz, cat->floaters[2].point);
	fontPrint(font, -240, -120, strBuff, 128, 128, 0);

	sprintf(strBuff, "targetRot : %d", cat->floaters[2].targetyRotSpeed);
	fontPrint(font, -240, -104, strBuff, 128, 128, 0);

	sprintf(strBuff, "Rot : %d", cat->floaters[2].yRotSpeed);
	fontPrint(font, -240, -84, strBuff, 128, 128, 0);

#endif
	}
}



#define CAT_DEVICE_MAX_POWER		176
#define CAT_LAUNCH_SPEED_INVFACTOR  22


void catapultControls()
{
	VECTOR v;
	v.vx = v.vy = v.vz = 0;

#ifdef DEBUG_CONTROLS_ON	


	if(pReadPad->digital[0] & PAD_R1)
	{

		if(pReadPad->analogYS[0] < -100)
		{
			MoveCameraTowardsLookAtPoint(-pReadPad->analogYS[0]/50);
		}

		if(pReadPad->analogYS[0] > 100)
		{
			MoveCameraTowardsLookAtPoint(-pReadPad->analogYS[0]/50);
		}

//		if(pReadPad->analogXS[0] > 100)
//		{	
//			cat->camRotSpeed -= pReadPad->analogXS[0] / 300;
//		}

//		if(pReadPad->analogXS[0] < -100)
//		{	
//			cat->camRotSpeed -= pReadPad->analogXS[0] / 300;
//		}

//		if(cat->camRotSpeed != 0)
//		{
//			cat->camRotSpeed = (cat->camRotSpeed*2)/3;
//			RotateCameraAroundLookAtPoint(cat->camRotSpeed);
//		}

		if(pReadPad->digital[0] & PAD_TRIANGLE)
		{
			mycamera.vpy -= 25;
		}
		
		if(pReadPad->digital[0] & PAD_SQUARE)
		{
			mycamera.vpy += 25;
		}
	}
	else if(pReadPad->digital[0] & PAD_L1)
	{
		
		if(pReadPad->digital[0] & PAD_TRIANGLE)
		{
			mycamera.vry -= 40;
		}

		if(pReadPad->digital[0] & PAD_SQUARE)
		{
			mycamera.vry += 40;
		}

//		if(pReadPad->analogYS[0] < -100)
//		{
//			mycamera.vrz += pReadPad->analogYS[0]/100;
//		}
  
//	if(pReadPad->analogYS[0] > 100)
//		{
//			mycamera.vrz += pReadPad->analogYS[0]/100;
//		}
  //
//		if(pReadPad->analogXS[0] < -100)
//		{
//			mycamera.vrx += pReadPad->analogXS[0]/100;
//	}

//		if(pReadPad->analogXS[0] > 100)
//		{
//			mycamera.vrx += pReadPad->analogXS[0]/100;
//		}

	}

		else if(pReadPad->digital[0] & PAD_R2)
	{

	

		if(pReadPad->analogYS[0] < -100)
		{
			myactor->position.vz -= pReadPad->analogYS[0]/40;
		}

		if(pReadPad->analogYS[0] > 100)
		{
			myactor->position.vz -= pReadPad->analogYS[0]/40;
		}

		if(pReadPad->analogXS[0] > 100)
		{	
			myactor->position.vx += pReadPad->analogXS[0]/40;
		}

		if(pReadPad->analogXS[0] < -100)
		{	
			myactor->position.vx += pReadPad->analogXS[0]/40;
		}

		if(pReadPad->digital[0] & PAD_TRIANGLE)
		{
			myactor->position.vy -= 60;
		}
		
		if(pReadPad->digital[0] & PAD_SQUARE)
		{
			myactor->position.vy += 60;
		}

		if(pReadPad->digital[0] & PAD_CIRCLE)
		{
			myactor->psiData.object->rotate.vy += 30;
		}

		if(pReadPad->digital[0] & PAD_CROSS)
		{
			myactor->psiData.object->rotate.vy -= 30;
		}
		
	}
	else

#endif
	{
//		if(pReadPad->debounce[0] & PAD_CROSS)
//		{
//			actorAnimate(cat->device.actor, CATAPULT_FIRE, FALSE, FALSE, 500, FALSE, 0);
//			actorAnimate(cat->device.actor, CATAPULT_DOWN, FALSE, TRUE, 500, FALSE, 0);
//		}	

		if(pReadPad->digital[0]&PAD_LEFT)
		{
			cat->device.yTargetRot = -4000/CAT_DEVICE_ROT_FACTOR;
		}
		else if(pReadPad->digital[0]&PAD_RIGHT)
		{
			cat->device.yTargetRot = 4000/CAT_DEVICE_ROT_FACTOR;
		}
		else
		{
			cat->device.yTargetRot = pReadPad->analogXS[0]/CAT_DEVICE_ROT_FACTOR;
		}


		if(pReadPad->digital[0]&PAD_UP)
		{
			cat->device.power = cat->device.power + ((4096/CAT_LAUNCH_SPEED_INVFACTOR) - cat->device.power) * 1/10;
		}
		else if(pReadPad->digital[0]&PAD_DOWN)
		{
			cat->device.power = cat->device.power + ((-4096/CAT_LAUNCH_SPEED_INVFACTOR) - cat->device.power) * 1/10;
		}
		else
		{
			cat->device.power = cat->device.power + (-12*(pReadPad->analogYS[0]/CAT_LAUNCH_SPEED_INVFACTOR)/10 - cat->device.power) * 1/10;
		}

		if(cat->device.power > CAT_DEVICE_MAX_POWER)
			cat->device.power = CAT_DEVICE_MAX_POWER;

		if(cat->device.power < -CAT_DEVICE_MAX_POWER)
			cat->device.power = -CAT_DEVICE_MAX_POWER;

	}

}





#define MIN_SEESAW_CAM_DIST 80

void MoveCameraTowardsLookAtPoint(int delta)
{
	VECTOR v;

	v.vx = mycamera.vrx - mycamera.vpx;
	v.vy = mycamera.vry - mycamera.vpy;
	v.vz = mycamera.vrz - mycamera.vpz;

	v.vx = v.vx * (delta)/4096;
	v.vy = v.vy * (delta)/4096;
	v.vz = v.vz * (delta)/4096;

	mycamera.vpx += v.vx; 
	mycamera.vpy += v.vy;
	mycamera.vpz += v.vz;

	mycamera.vrx += v.vx;
	mycamera.vry += v.vy;
	mycamera.vrz += v.vz;
}



int CAT_ZOFFSET = -1400;
int CAT_YOFFSET = -100;

int CAT_XOFFSET_POST = 545;
int CAT_ZOFFSET_POST = 2050;


void catDeviceUpdate()
{
	VECTOR tempVect;
	int tempInt;
	PSIOBJECT *object;

	tempInt = cat->device.yTargetRot - cat->device.yRot;
	tempInt /= 5;

	cat->device.yRot += tempInt;

// need to find PSIOBJECT of DEVICE
	object = psiObjectScan(cat->device.actor->psiData.object, "TURNME");
	if(object)
		object->rotate.vy = cat->device.yRot;

	tempVect.vx = 0;
	tempVect.vy = 0;
	tempVect.vz = CAT_ZOFFSET;

	RotateVector2D(&tempVect, &tempVect, cat->device.yRot);

	cat->device.chickenPos.vx = CAT_DEVICE_XPOS + tempVect.vx + CAT_XOFFSET_POST;

	cat->device.chickenPos.vy = CAT_DEVICE_YPOS + CAT_YOFFSET - cat->device.animPos/20;
	cat->device.chickenPos.vz = CAT_DEVICE_ZPOS + tempVect.vz + CAT_ZOFFSET_POST;


	if((cat->device.droneOnDevice < 0) && (cat->state == CAT_STATE_RUNNING))
	{
		for(tempInt=0; ((tempInt < CAT_NUM_DRONES) && (cat->device.droneOnDevice < 0)); tempInt++)
		{
			if(cat->drones[tempInt].state == CAT_DRONE_WAITING)
			{
				cat->drones[tempInt].state = CAT_DRONE_RUNNINGON;
				cat->device.droneOnDevice = tempInt;
				cat->device.nextDrone = -1;
				cat->drones[tempInt].rotAim = 1024;
				actorAnimate(cat->drones[tempInt].actor, DRONE_RUN, YES, FALSE, 600, FALSE, 0);
			}
		}
	}

	if((cat->device.nextDrone < 0) && (cat->state != CAT_STATE_FINISH))
	{
		for(tempInt=0; ((tempInt < CAT_NUM_DRONES) && (cat->device.nextDrone < 0)); tempInt++)
		{
			if(cat->drones[tempInt].state == CAT_DRONE_INACTIVE)
			{
				cat->drones[tempInt].state = CAT_DRONE_RUNTO_WAITING;
				cat->device.nextDrone = tempInt;
				cat->drones[tempInt].target.vx = CAT_DRONE_WAIT_XPOS;
				cat->drones[tempInt].target.vy = CAT_DRONE_WAIT_YPOS;
				cat->drones[tempInt].target.vz = CAT_DRONE_WAIT_ZPOS;

				cat->drones[tempInt].rotAim = 1024;

				actorAnimate(cat->drones[tempInt].actor, DRONE_TIP_TOE, YES, FALSE, 1200, FALSE, 0);
			}
		}
	}

	//Launch Drone here
	if((pReadPad->debounce[0] & PAD_CROSS) && (cat->device.droneOnDevice >= 0) && (cat->drones[cat->device.droneOnDevice].state == CAT_DRONE_ONDEVICE))
	{
		catDroneLaunch();
	}	


}


long CAT_FLOATER_HEIGHT =0;

void catDroneLaunch()
{

	int time;

	cat->device.actor->animation.animData[0].speed = 200;
	actorAnimate(cat->device.actor, CATAPULT_DOWN, FALSE, TRUE, 500, FALSE, 0);
	actorAnimate(cat->device.actor, CATAPULT_FIRE, FALSE, TRUE, 0, FALSE, 0);
	cat->drones[cat->device.droneOnDevice].state = CAT_DRONE_LAUNCHING;
	cat->device.droneOnDevice = -1;

	
	soundPlaySample(cat->pSamples[SFX_CATAPULT_BOIING], 255, 0);//, &cat->device.actor->position);
	soundPlaySample(cat->pSamples[SFX_CATAPULT_LAUNCH], 255, 0);//, &cat->device.actor->position);
	// why not PanOnly??
}																	   


#define CAT_DRONE_DIST_TO_JUMP 700
#define CAT_DRONE_JUMPINGON_SPEED  -200
#define CAT_DRONE_MAX_SPEED  90
#define CAT_DRONE_RUNOFF_MAX_SPEED  70
#define CAT_DRONE_JUMPING_MAX_SPEED  200

#define CAT_DRONE_GROUND_HEIGHT 0

int CAT_DRONE_LAUNCH_YVEL = -600;
int CAT_DRONE_LAUNCH_ZVEL = 600;
int CAT_GRAVITY  =64;
#define CAT_DRONE_WATER_HEIGHT  1400


int CAT_POWER_FACTOR =8192;

int CAT_DRONE_JUMPOFFYSPEED = -200;
int CAT_DRONE_JUMPOFFXSPEED = 200;
int CAT_DRONE_LANDING_HEIGHT = -1600;
int CAT_DRONE_LANDING_MAX_SPEED = 1600;
int CAT_DRONE_SPLASH_EXTRA = 600;
int CAT_RUN_OFF_HEIGHT = 200;
int CAT_RUN_OFF_DIST = 1600;


//------------------------------------------------
void catDronesUpdate()
{
	int i, drone;
	long dist;

	VECTOR *v=NULL;
	VECTOR tempVect;

	for(i=0; i< CAT_NUM_DRONES; i++)
	{

		if(cat->drones[i].actor->psiData.object->rotate.vy != cat->drones[i].rotAim)
		{

			dist = cat->drones[i].rotAim - cat->drones[i].actor->psiData.object->rotate.vy;
			cat->drones[i].actor->psiData.object->rotate.vy += (dist)/4;
			if((dist < 6) && (dist > -6))
			{
				cat->drones[i].actor->psiData.object->rotate.vy = cat->drones[i].rotAim;
			}
		}

 
		switch(cat->drones[i].state)
		{
			case CAT_DRONE_INACTIVE:     
				break;
			case CAT_DRONE_RUNTO_WAITING:
				//cat->drones[i].target.vx = d

				cat->drones[i].rotAim = 1024;
				
				dist = (cat->drones[i].actor->position.vx - CAT_DRONE_WAIT_XPOS)/2;

				if(dist < 32)
				{
					cat->drones[i].state = CAT_DRONE_WAITING;
					actorAnimate(cat->drones[i].actor, DRONE_STAR_JUMP, TRUE, FALSE, 300, FALSE, 0);
					cat->drones[i].rotAim = 0;
				}
				
				if(dist > CAT_DRONE_MAX_SPEED/2)
					dist = CAT_DRONE_MAX_SPEED/2;


				cat->drones[i].actor->position.vx -= dist;

					//CAT_DRONE_WAIT_XPOS;
//				cat->drones[i].actor->position.vy = CAT_DRONE_WAIT_YPOS;
//				cat->drones[i].actor->position.vz = CAT_DRONE_WAIT_ZPOS;
				
				break;
			case CAT_DRONE_WAITING:

				dist=random(4000)/20;

/*
				if((cat->drones[i].anim == 2))
				{
					cat->drones[i].rotAim += 36;
					if(cat->drones[i].rotAim > 4096)
					{
						cat->drones[i].rotAim -= 4096;
						cat->drones[i].actor->psiData.object->rotate.vy -= 4096;
					}
				}
*/

				if(cat->drones[i].countUp++ > 120)
				{
					cat->drones[i].countUp = 0;
					cat->drones[i].anim++;
					if(cat->drones[i].anim >5)
						cat->drones[i].anim = 0;
				
					switch(cat->drones[i].anim)
					{
						case 0:
							cat->drones[i].rotAim = 0;
							//actorFlushQueue(cat->drones[i].actor);
							actorAnimate(cat->drones[i].actor, DRONE_STAR_JUMP, TRUE, 0, 300, FALSE, 400);

							break;
						case 1:
							//actorFlushQueue(cat->drones[i].actor);
							cat->drones[i].countUp = 90;
							actorAnimate(cat->drones[i].actor, DRONE_STRETCH_ARMS_CYCLE, TRUE, 0, 300, FALSE, 400);
							break;
						case 2:
							//actorFlushQueue(cat->drones[i].actor);
							actorAnimate(cat->drones[i].actor, DRONE_STAR_JUMP, TRUE, 0, 300, FALSE, 400);

							break;
						case 3:
							cat->drones[i].rotAim = 0;
							//actorFlushQueue(cat->drones[i].actor);
							actorAnimate(cat->drones[i].actor, DRONE_STAND_BREATHE, TRUE, 0, 300, FALSE, 400);
							break;
						case 4:
							//actorFlushQueue(cat->drones[i].actor);
							actorAnimate(cat->drones[i].actor, DRONE_JUMP_CYCLE, TRUE, 0, 300, FALSE, 400);
							break;
						case 5:
							//actorFlushQueue(cat->drones[i].actor);
							cat->drones[i].countUp = 90;
							actorAnimate(cat->drones[i].actor, DRONE_STRETCH_ARMS_CYCLE, TRUE, 0, 300, FALSE, 400);
							break;


					}
				}
				break;
			case CAT_DRONE_RUNNINGON:
				SUBVECTOR(&tempVect, &cat->device.chickenPos, &cat->drones[i].actor->position);
				if((tempVect.vx < CAT_DRONE_DIST_TO_JUMP) && (tempVect.vx > -CAT_DRONE_DIST_TO_JUMP))
				{
					cat->drones[i].state = CAT_DRONE_JUMPINGON;
					actorAnimate(cat->drones[i].actor, DRONE_JUMP, FALSE, FALSE, 256, FALSE, 0);       
					actorAnimate(cat->drones[i].actor, DRONE_DOWN_FLAPPING, FALSE, TRUE, 256, FALSE, 0);       
					actorAnimate(cat->drones[i].actor, DRONE_LAND_ON_SEESAW, FALSE, TRUE, 256, FALSE, 0);       
					actorAnimate(cat->drones[i].actor, DRONE_SEESAW_GULP, FALSE, TRUE, 256, FALSE, 0);       
					actorAnimate(cat->drones[i].actor, DRONE_SEESAW_COVER_EYES, FALSE, TRUE, 256, FALSE, 0);       

					cat->drones[i].vel.vy = CAT_DRONE_JUMPINGON_SPEED;
					cat->drones[i].vel.vx = 0;
					cat->drones[i].vel.vz = 0;
					cat->drones[i].rotAim = 2048;
					break;
				}

				SCALEVECTOR(&tempVect, 2048);
				dist = Magnitude(&tempVect);
				if(dist > CAT_DRONE_MAX_SPEED)
				{
					SCALEVECTOR(&tempVect, 4096*CAT_DRONE_MAX_SPEED/dist);
				}
				ADDTOVECTOR(&cat->drones[i].actor->position, &tempVect);
				cat->drones[i].actor->position.vy = CAT_DRONE_GROUND_HEIGHT;
				break;

			case CAT_DRONE_JUMPINGON:    
				SUBVECTOR(&tempVect, &cat->device.chickenPos, &cat->drones[i].actor->position);
				SCALEVECTOR(&tempVect, 2048);
				dist = Magnitude(&tempVect);
				if(dist > CAT_DRONE_JUMPING_MAX_SPEED)
				{
					SCALEVECTOR(&tempVect, 4096*CAT_DRONE_MAX_SPEED/dist);
				}
				ADDTOVECTOR(&cat->drones[i].actor->position, &tempVect);
				if(dist < 32)
					cat->drones[i].state = CAT_DRONE_ONDEVICE;

				cat->drones[i].actor->position.vy += cat->drones[i].vel.vy;
				cat->drones[i].vel.vy = cat->drones[i].vel.vy * 4096 / 5000;  
				break;

			case CAT_DRONE_ONDEVICE:
				cat->drones[i].actor->position = cat->device.chickenPos;
				cat->drones[i].actor->psiData.object->rotate.vy = cat->drones[i].rotAim = 2048 + 2*cat->device.yRot;

				break;
			case CAT_DRONE_LAUNCHING:
			{
				long res;
				unsigned long tempInt;

				actorAnimate(cat->drones[i].actor, DRONE_MID_AIR_CYCLE, TRUE, FALSE, 750, FALSE, 0);
				cat->drones[i].state = CAT_DRONE_FLYING;
				v = &cat->drones[i].vel;
				v->vx = 0;
				v->vy = CAT_DRONE_LAUNCH_YVEL;
				v->vz = CAT_DRONE_LAUNCH_ZVEL;
				RotateVector2D(v, v, cat->device.yRot);

				SCALEVECTOR(v, (4096 + CAT_POWER_FACTOR*cat->device.power/4096));

				//Find out if it's gonna hit a floater
				
				// time	(not includes scaling for less! accuraccy)

//-------------------------------------------------------------------------------------------------				

//				dist = CAT_WATER_HEIGHT - cat->drones[i].actor->position.vy;

//				tempInt = v->vy*v->vy - 2* CAT_GRAVITY * dist;
//				tempInt = utilSqrt(tempInt) >> 16;

//				dist = (-v->vy + tempInt)/CAT_GRAVITY; 
//				if(pReadPad->digital[0] & PAD_TRIANGLE)
//					DB("..\ndist new %d ti=%d\n", dist, tempInt);

//-----------------------------------------------------------------

				dist =  -4096*2*v->vy/CAT_GRAVITY;

//				if(pReadPad->digital[0] & PAD_TRIANGLE)
//					DB("dist %d\n", dist);


				tempVect.vx = v->vx;
				tempVect.vy = 0;
				tempVect.vz = v->vz;

				SCALEVECTOR(&tempVect, dist);




				cat->drones[i].floater = catFloaterCatchChicken(&tempVect, dist);

				tempVect.vy = CAT_WATER_HEIGHT;


				//Launching
				dsEvent_Add(1, 1, 1, 165, 0, 6, FALSE);


				//temp
//				debrisNewGenericWaterSplash(ripple, &tempVect, RIPPLE_SIZE_START, RIPPLE_DSIZE*4, 45);
//				debrisNewGenericWaterSplash(ripple, &tempVect, RIPPLE_SIZE_START*2, RIPPLE_DSIZE*5, 30);
//				debrisNewGenericWaterSplash(ripple, &tempVect, RIPPLE_SIZE_START*12, -RIPPLE_DSIZE*3, 16);

			}
				break;

			case CAT_DRONE_FLYING:
				cat->drones[i].vel.vy += CAT_GRAVITY;
				ADDTOVECTOR(&cat->drones[i].actor->position, &cat->drones[i].vel);


				if(cat->drones[i].floater >= 0)
				{
					// landing on floater

					long tempInt;
					VECTOR v1, v2;

//					if(cat->drones[i].actor->position.vy > cat->floaters[cat->drones[i].floater].chickenPos.vy)
					if((cat->drones[i].actor->position.vy > (cat->floaters[cat->drones[i].floater].chickenPos.vy + CAT_DRONE_LANDING_HEIGHT)) && (cat->drones[i].vel.vy > 0) )
					{
//						cat->drones[i].actor->position.vy = cat->floaters[cat->drones[i].floater].chickenPos.vy;
//						cat->drones[i].state = CAT_DRONE_LANDED;
//						actorAnimate(cat->drones[i].actor, DRONE_RUN_OFF_SCREAMING, TRUE, FALSE, 300, FALSE, 128);
						cat->drones[i].rotAim = 0;

						actorAnimate(cat->drones[i].actor, DRONE_DOWN_FLAPPING, TRUE, FALSE, 600, FALSE, 1024);
						cat->drones[i].state = CAT_DRONE_LANDING;


						if((tempInt = cat->floaters[cat->drones[i].floater].droneOn) >= 0)
						{
							cat->drones[tempInt].state = CAT_DRONE_FALLOFF;
							cat->drones[tempInt].rotAim = 2048;
							actorAnimate(cat->drones[i].actor, DRONE_RUN_OFF_SCREAMING, TRUE, FALSE, 600, FALSE, 0);

							cat->drones[tempInt].vel.vx = 0;
							cat->drones[tempInt].vel.vy = -200;
							cat->drones[tempInt].vel.vz = 100;
						}
						else
							cat->numChickensSaved++;


						break;
					}

					// how far have we progressed in the jump?
					dist = 4096*(cat->drones[i].actor->position.vz - cat->device.chickenPos.vz)/(cat->floaters[cat->drones[i].floater].targetPos.vz - cat->device.chickenPos.vz);

					//DB("dist = %d\n",dist);
					v1 = cat->floaters[cat->drones[i].floater].chickenPos;
					v2 = cat->floaters[cat->drones[i].floater].targetPos;

					SCALEVECTOR(&v1, dist);
					SCALEVECTOR(&v2, (4096-dist));

					// This is our new improved target Position
					ADDTOVECTOR(&v1, &v2);

					// current magnitude
					dist = Magnitude2D(cat->drones[i].vel.vx, cat->drones[i].vel.vz);

					//DB("mag drone = %d\n",dist);

					// accurate direction
					SUBVECTOR(&v2, &v1, &(cat->drones[i].actor->position));

					tempInt	= Magnitude2D(v2.vx, v2.vz);

					SCALEVECTOR(&v2, (4096 * dist / tempInt));

					cat->drones[i].vel.vx = v2.vx;
					cat->drones[i].vel.vz = v2.vz;

				}
				else
				{
					//not landing on floater
																			  // ????
					if(cat->drones[i].actor->position.vy > (CAT_WATER_HEIGHT+ CAT_DRONE_SPLASH_EXTRA))//CAT_DRONE_WATER_HEIGHT)
					{

						tempVect = cat->drones[i].actor->position;
						tempVect.vy = CAT_WATER_HEIGHT + CAT_DRONE_SPLASH_EXTRA;
						
						debrisNewGenericWaterSplash(ripple, &tempVect, RIPPLE_SIZE_START, RIPPLE_DSIZE*4, 45);
						debrisNewGenericWaterSplash(ripple, &tempVect, RIPPLE_SIZE_START*2, RIPPLE_DSIZE*5, 30);
						debrisNewGenericWaterSplash(ripple, &tempVect, RIPPLE_SIZE_START*12, -RIPPLE_DSIZE*3, 16);


					//	cat->drones[i].actor->position.vx = CAT_DRONE_OFFSCREEN_XPOS;
					//	cat->drones[i].actor->position.vy = CAT_DRONE_WAIT_YPOS;
					//	cat->drones[i].actor->position.vz = CAT_DRONE_WAIT_ZPOS;


					//	cat->drones[i].state = CAT_DRONE_INACTIVE;//CRASHING;
						cat->drones[i].state = CAT_DRONE_CRASHING;

						// splashing
						dsEvent_Add(0, 0, 1, 150, 0, 7, FALSE);
						break;
					}
				}
				// splashing
				break;
			case CAT_DRONE_CRASHING:
				cat->drones[i].state = CAT_DRONE_INACTIVE;
				cat->drones[i].actor->position.vx = CAT_DRONE_OFFSCREEN_XPOS;
				cat->drones[i].actor->position.vy = CAT_DRONE_WAIT_YPOS;
				cat->drones[i].actor->position.vz = CAT_DRONE_WAIT_ZPOS;


				soundPlaySample(cat->pSamples[SFX_CATAPULT_BIGSPLASH], 255, 0);


				break;
			case CAT_DRONE_LANDING:
				SUBVECTOR(&tempVect, &cat->floaters[cat->drones[i].floater].chickenPos, &cat->drones[i].actor->position);
				SCALEVECTOR(&tempVect, 2048);
				dist = Magnitude(&tempVect);
				if(dist > CAT_DRONE_LANDING_MAX_SPEED)
				{
					SCALEVECTOR(&tempVect, 4096*CAT_DRONE_MAX_SPEED/dist);
				}
				ADDTOVECTOR(&cat->drones[i].actor->position, &tempVect);
				
				if((dist < 256) && (cat->floaters[cat->drones[i].floater].actor->animation.animData[0].segment == CATAPULT_FLOATER_BOB))
				{
//					if((cat->drones[i].floater == 0) || (cat->drones[i].floater == 3))
						actorAnimate(cat->floaters[cat->drones[i].floater].actor, CATAPULT_FLOATER_NEWLAND, FALSE, FALSE, 300, FALSE, 600);
//					else
//						actorAnimate(cat->floaters[cat->drones[i].floater].actor, CATAPULT_FLOATER_LAND, FALSE, FALSE, 300, FALSE, 600);

					soundPlaySample(cat->pSamples[SFX_CATAPULT_SPLASH], 100, 0);

					actorAnimate(cat->floaters[cat->drones[i].floater].actor, CATAPULT_FLOATER_BOB, TRUE, TRUE, CATAPULT_FLOATER_ANIM_SPEED, FALSE, 0);

					// Landing
					dsEvent_Add(0, 0, 1, 140, 0, 5, FALSE);

				}
				
				if(dist < 64)
				{


					cat->drones[i].state = CAT_DRONE_LANDED;

					cat->floaters[cat->drones[i].floater].droneOn = i;
					cat->drones[i].actor->position = cat->floaters[cat->drones[i].floater].chickenPos;
					actorAnimate(cat->drones[i].actor, DRONE_STAND_ON_CRATE, TRUE, FALSE, 500, FALSE, 0);
				}

//				cat->drones[i].actor->position.vy += cat->drones[i].vel.vy;
//				cat->drones[i].vel.vy = cat->drones[i].vel.vy * 4096 / 5000;  

				break;
			case CAT_DRONE_LANDED:
				cat->drones[i].actor->position = cat->floaters[cat->drones[i].floater].chickenPos;

				if(((cat->floaters[cat->drones[i].floater].point == 1) || (cat->floaters[cat->drones[i].floater].point == 6)))
				{
					cat->floaters[cat->drones[i].floater].droneOn = -1;
					cat->drones[i].state = CAT_DRONE_JUMPINGOFF;

					if(cat->floaters[cat->drones[i].floater].point == 1)
					{
						cat->drones[i].vel.vx = -CAT_DRONE_JUMPOFFXSPEED;
						cat->drones[i].rotAim = 1024;
					}
					else
					{
						cat->drones[i].vel.vx =  CAT_DRONE_JUMPOFFXSPEED;
						cat->drones[i].rotAim = 3080;
					}

					cat->drones[i].vel.vy =  CAT_DRONE_JUMPOFFYSPEED;
					cat->drones[i].vel.vz = 0;

					//actorAnimate(cat->drones[i].actor, DRONE_JUMP, FALSE, FALSE, 900, FALSE, 1024);
					actorAnimate(cat->drones[i].actor, DRONE_DOWN_FLAPPING, TRUE, TRUE, 900, FALSE, 1024);

//					actorAnimate(cat->floaters[cat->drones[i].floater].actor, CATAPULT_FLOATER_LAND, FALSE, FALSE, 300, FALSE, 600);

//					if((cat->drones[i].floater == 0) || (cat->drones[i].floater == 3))
						actorAnimate(cat->floaters[cat->drones[i].floater].actor, CATAPULT_FLOATER_NEWLAND, FALSE, FALSE, 300, FALSE, 500);
//					else
//						actorAnimate(cat->floaters[cat->drones[i].floater].actor, CATAPULT_FLOATER_LAND, FALSE, FALSE, 300, FALSE, 500);

					actorAnimate(cat->floaters[cat->drones[i].floater].actor, CATAPULT_FLOATER_BOB, TRUE, TRUE, CATAPULT_FLOATER_ANIM_SPEED, FALSE, 0);


				}
				break;

			case CAT_DRONE_FALLOFF:
				ADDTOVECTOR(&cat->drones[i].actor->position, &cat->drones[i].vel);

				cat->drones[i].vel.vy += CAT_GRAVITY;

				//DB("FALLING %d \n",cat->drones[i].vel.vy);

				if(cat->drones[i].actor->position.vy > CAT_WATER_HEIGHT)
				{
					tempVect = cat->drones[i].actor->position;
					tempVect.vy = CAT_WATER_HEIGHT;
						
					debrisNewGenericWaterSplash(ripple, &tempVect, RIPPLE_SIZE_START, RIPPLE_DSIZE*4, 35);
					debrisNewGenericWaterSplash(ripple, &tempVect, RIPPLE_SIZE_START*2, RIPPLE_DSIZE*5, 30);
					debrisNewGenericWaterSplash(ripple, &tempVect, RIPPLE_SIZE_START*12, -RIPPLE_DSIZE*3, 16);

					cat->drones[i].actor->position.vx = CAT_DRONE_OFFSCREEN_XPOS;
					cat->drones[i].actor->position.vy = CAT_DRONE_WAIT_YPOS;
					cat->drones[i].actor->position.vz = CAT_DRONE_WAIT_ZPOS;

					cat->drones[i].state = CAT_DRONE_INACTIVE;
					cat->floaters[cat->drones[i].floater].active--;

				}
				break;


			case CAT_DRONE_JUMPINGOFF:
				
				ADDTOVECTOR(&cat->drones[i].actor->position, &cat->drones[i].vel);

				cat->drones[i].vel.vy += CAT_GRAVITY/2;

				if((cat->drones[i].actor->position.vy > CAT_RUN_OFF_HEIGHT) && (cat->drones[i].vel.vy > 0))
				{
//					cat->drones[i].actor->position.vx = CAT_DRONE_OFFSCREEN_XPOS;
					cat->drones[i].actor->position.vy = CAT_RUN_OFF_HEIGHT;
//					cat->drones[i].actor->position.vz = CAT_DRONE_WAIT_ZPOS;


					if(cat->drones[i].vel.vx < 0)
					{
						cat->drones[i].target.vx = cat->drones[i].actor->position.vx - CAT_RUN_OFF_DIST;
					}
					else
					{
						cat->drones[i].target.vx = cat->drones[i].actor->position.vx + CAT_RUN_OFF_DIST;
					}

					cat->drones[i].vel.vy = 0;
					cat->drones[i].vel.vz = 0;

					cat->drones[i].target.vy = cat->drones[i].actor->position.vx;
					cat->drones[i].target.vz = cat->drones[i].actor->position.vz;


					cat->drones[i].state = CAT_DRONE_RUNNINGOFF;
					actorAnimate(cat->drones[i].actor, DRONE_RUN_OFF_SCREAMING, TRUE, FALSE, 300, FALSE, 128);
					cat->floaters[cat->drones[i].floater].active--;

				}
				break;

			case CAT_DRONE_RUNNINGOFF:
				// drone must be given a target pos and a velocity
				//when it passes this point it is made inactive

				ADDTOVECTOR(&cat->drones[i].actor->position, &cat->drones[i].vel);

				if( ((cat->drones[i].vel.vx > 0) && (cat->drones[i].actor->position.vx > cat->drones[i].target.vx))
					|| ((cat->drones[i].vel.vx < 0) && (cat->drones[i].actor->position.vx < cat->drones[i].target.vx)) )
				{
					cat->drones[i].actor->position.vx = CAT_DRONE_OFFSCREEN_XPOS;
					cat->drones[i].actor->position.vy = CAT_DRONE_WAIT_YPOS;
					cat->drones[i].actor->position.vz = CAT_DRONE_WAIT_ZPOS;

					cat->drones[i].state = CAT_DRONE_INACTIVE;
					actorFlushQueue(cat->drones[i].actor);
				}
				break;

		}
	}
}


long CAT_LAND_DISTANCE =1000000;
//------------------------------------------------
// gets position where chicken is gonna land and time(4096 == 1 frame) before it does
int catFloaterCatchChicken(VECTOR *pos, int dist)
{
	int i;
	long nearish;
	VECTOR tempVect, test;

	for(i=0; i<CAT_NUM_FLOATERS; i++)
	{
		tempVect = cat->floaters[i].vel;
		SCALEVECTOR(&tempVect, dist);
		ADDTOVECTOR(&tempVect, &cat->floaters[i].pos); 

		// store this here so the incoming chicken can use both it's current pos and predicted pos
		cat->floaters[i].targetPos = tempVect;

		tempVect.vy += FLOATER_HEIGHT;

	//	if(cat->floaters[i].active == TRUE)
	//	{
	//		debrisDust(&tempVect, 30 , 1024);
	//	}
	
		SUBVECTOR(&tempVect, pos, &tempVect);

		nearish = (tempVect.vx * tempVect.vx) + (tempVect.vz * tempVect.vz);
	
		if(nearish < CAT_LAND_DISTANCE)
		{
			cat->floaters[i].active++;
			return i;
		}
	}
	return -1;

}




//------------------------------------------------
void catMakeActiveChickensRunOff()
{
	int i;

	for(i=0; i< CAT_NUM_DRONES; i++)
	{
		switch(cat->drones[i].state)
		{
			case CAT_DRONE_WAITING:
			case CAT_DRONE_RUNTO_WAITING:
				cat->drones[i].target.vx = CAT_DRONE_OFFSCREEN_XPOS;
				cat->drones[i].rotAim = 3072;
				cat->drones[i].vel.vx = CAT_DRONE_RUNOFF_MAX_SPEED;
				cat->drones[i].vel.vy =	(0 - cat->drones[i].actor->position.vy) * (CAT_DRONE_RUNOFF_MAX_SPEED)/ (CAT_DRONE_OFFSCREEN_XPOS - cat->drones[i].actor->position.vx);
				cat->drones[i].vel.vz = 0;
				break;
			
			
			case CAT_DRONE_RUNNINGON:
			case CAT_DRONE_JUMPINGON:
			case CAT_DRONE_ONDEVICE:
				cat->drones[i].target.vx = -CAT_DRONE_OFFSCREEN_XPOS;
				cat->drones[i].rotAim = 1024;
				cat->drones[i].vel.vx = -CAT_DRONE_RUNOFF_MAX_SPEED;
				cat->drones[i].vel.vy =	(0 - cat->drones[i].actor->position.vy) * (CAT_DRONE_RUNOFF_MAX_SPEED)/ (cat->drones[i].actor->position.vx - CAT_DRONE_OFFSCREEN_XPOS);
				cat->drones[i].vel.vz = 0;
				break;


			default:
				continue;
				break;
		}

		cat->drones[i].target.vy = 0;
		cat->drones[i].target.vz = cat->drones[i].actor->position.vz;
		cat->drones[i].state = CAT_DRONE_RUNNINGOFF;
		actorAnimate(cat->drones[i].actor, DRONE_RUN_OFF_SCREAMING, TRUE, FALSE, 500, 0, 600);
	}
}





void catDrawIntro()
{
	char string[400];					
	
	sprintf(string,"%s\n\n%s\n%s\n%s",
		(char*)TEXTSTR(TEXTSTR_SUB_CAT_FIRE_CHICKS),
		(char*)TEXTSTR(TEXTSTR_SUB_FIRE_CHICK),
		(char*)TEXTSTR(TEXTSTR_SUB_SEESAW_AIM),
		(char*)TEXTSTR(TEXTSTR_SUB_XSTART)
		);

	fontPrintMultiLineBox(font, 0, 0, 340, string, 40, 40, 40);

}



#define CAT_OUTRO_TEXT_XPOS  -200
#define CAT_OUTRO_TEXT_MARGIN  20
#define CAT_OUTRO_TEXT_WIDTH  410


//------------------------------------------------
void catDrawBronzeSuccess()
{
	char string[256];					
	

	sprintf(string, "%s %d %s %s\n%s", (char*)TEXTSTR(TEXTSTR_SUB_SUBGAME_SAVED), cat->numChickensSaved, (char*)TEXTSTR(TEXTSTR_SUB_SUBGAME_CHICKENS), (char*)TEXTSTR(TEXTSTR_SUB_CATAPULT_BRONZE), (char*)TEXTSTR(TEXTSTR_SUB_GAME_EXIT_RESTART));
	fontPrintMultiLineBoxSetDepth(font, 0, 0, 340, string, 40, 40, 40,2);
}

//------------------------------------------------
void catDrawSilverSuccess()
{
	char string[256];
	
	sprintf(string, "%s %d %s %s\n%s", (char*)TEXTSTR(TEXTSTR_SUB_SUBGAME_SAVED), cat->numChickensSaved, (char*)TEXTSTR(TEXTSTR_SUB_SUBGAME_CHICKENS), (char*)TEXTSTR(TEXTSTR_SUB_CATAPULT_SILVER), (char*)TEXTSTR(TEXTSTR_SUB_GAME_EXIT_RESTART));
	fontPrintMultiLineBoxSetDepth(font, 0, 0, 340, string, 40, 40, 40,2);
}

//------------------------------------------------
void catDrawGoldSuccess()
{
	char string[256];

	sprintf(string, "%s %d %s %s\n%s", (char*)TEXTSTR(TEXTSTR_SUB_SUBGAME_SAVED), cat->numChickensSaved, (char*)TEXTSTR(TEXTSTR_SUB_SUBGAME_CHICKENS), (char*)TEXTSTR(TEXTSTR_SUB_CATAPULT_GOLD), (char*)TEXTSTR(TEXTSTR_SUB_GAME_EXIT_RESTART));
	fontPrintMultiLineBoxSetDepth(font, 0, 0, 340, string, 40, 40, 40,2);
}


//------------------------------------------------
void catDrawFail()
{
	char string[256];
										   
	if(cat->numChickensSaved == 0)
		sprintf(string, "%s\n%s\n%s", (char*)TEXTSTR(TEXTSTR_SUB_CATAPULT_NONE), (char*)TEXTSTR(TEXTSTR_SUB_CATAPULT_FAIL), (char*)TEXTSTR(TEXTSTR_SUB_GAME_EXIT_RESTART));
 	else if(cat->numChickensSaved == 1)
		
		sprintf(string, "%s\n%s\n%s", (char*)TEXTSTR(TEXTSTR_SUB_CATAPULT_ONE), (char*)TEXTSTR(TEXTSTR_SUB_CATAPULT_FAIL), (char*)TEXTSTR(TEXTSTR_SUB_GAME_EXIT_RESTART));
	else
		sprintf(string, "%s %d %s %s\n%s", (char*)TEXTSTR(TEXTSTR_SUB_SUBGAME_SAVED), cat->numChickensSaved, (char*)TEXTSTR(TEXTSTR_SUB_SUBGAME_CHICKENS), (char*)TEXTSTR(TEXTSTR_SUB_CATAPULT_FAIL), (char*)TEXTSTR(TEXTSTR_SUB_GAME_EXIT_RESTART));
	
	fontPrintMultiLineBoxSetDepth(font, 0, 0, 340, string, 40, 40, 40,2);
}


//------------------------------------------------
// catapultEnd()
//
// Free memory and quit back to the menu
//------------------------------------------------




void catapultEnd(void)
{
	int i;

	// make a record of how many chickens saved
	if (cat->numChickensSaved > gameSaveData.best_chickens_rescued[RESCUELEVEL_CATAPULT])
		gameSaveData.best_chickens_rescued[RESCUELEVEL_CATAPULT]=cat->numChickensSaved;


	dsEvent_Init();
	//mapviewReleaseMap();

	actorFree(cat->device.actor);       
	actorFree(cat->drones[0].actor);    
	actorFree(cat->drones[1].actor);    
	actorFree(cat->drones[2].actor);    
	actorFree(cat->drones[3].actor);    
	actorFree(cat->drones[4].actor);    

	//actorFree(cat->device.winderActor); 
	actorFree(cat->floaters[0].actor);
	actorFree(cat->floaters[1].actor);
	actorFree(cat->floaters[2].actor);
	actorFree(cat->floaters[3].actor);


	freeFowler();
	freeStopWatch();

	FREE(cat);
	
	//psiDestroy();
//	menuStart();

	DB("cat %d fire %d see %d\n",gameSaveData.best_chickens_rescued[RESCUELEVEL_CATAPULT],gameSaveData.best_chickens_rescued[RESCUELEVEL_FIREWORKS],gameSaveData.best_chickens_rescued[RESCUELEVEL_SEESAW]);

	mapviewReleaseMap();
//	dsEvent_Init();

	//memoryShowStats();
	//memoryShow();


	if(subGameRestart)
	{
		catapultStart();
	}
	else
	{
		act2SubgameComplete("A2_WORKHUT2");
	}
}





