//*****************************************************************************
//	Dependencies
//*****************************************************************************
#include "generic.h"
#include "lfptypes.h"
#include "define.h"
#include "ml.h"
#include "ctrl.h"
#include "audio.h"
#include "crowd.h"
#include "menu.h"

extern void release_jump_shot(playert *plyr);



//*****************************************************************************
//	Defines
//*****************************************************************************

//-----------------------------------------------------------------------------
//	Player Structure Alias Definitions
//-----------------------------------------------------------------------------
#define	Shooter3	bumped_into


//-----------------------------------------------------------------------------
//	Starting Positions
//-----------------------------------------------------------------------------
#define	SP_X1		0xff9552da
#define	SP_Y1		0x00d0b76a
#define	SP_X2		0xffbf99d8
#define	SP_Y2		0x006394a7
#define	SP_X3		0xfff923c2
#define	SP_Y3		0x0050d01f


//-----------------------------------------------------------------------------
//	Shooting States
//-----------------------------------------------------------------------------
#define	ST3_Leaping		0			// Pushing off the ground
#define	ST3_Up			1			// Upward portion of the jump trajectory
#define	ST3_Hold		2			// Holding the ball before release
#define	ST3_Down		3			// Downward segment of the jump trajectory
#define	ST3_Landed		4			// Hit the ground, gotta finish animation

#define	ST3_Mask		7			// True state, not flags
#define	ST3_Counting	8			// Shot release counter disabled


//-----------------------------------------------------------------------------
//	Running States
//-----------------------------------------------------------------------------
#define	ST3_ClearRack	0			// Run in front of the current rack
#define	ST3_Run			1			// Run to the next rack
#define	ST3_FaceNet		2			// Turn to face the net again


//-----------------------------------------------------------------------------
//	Ball States
//-----------------------------------------------------------------------------
#define	BS3_ToNet		0			// Ball shot, heading towards the net
#define	BS3_Made		1			// Ball has/will officiallly be scored
#define	BS3_Missed		2			// Ball has/will definitely not go in
#define BS3_Roll		3			// Ball is rolling on ground


//-----------------------------------------------------------------------------
//	Controller Inputs
//-----------------------------------------------------------------------------
#define	CTRL_GRAB	CTRL_C_LEFT		// Button to press to grab ball from rack


//-----------------------------------------------------------------------------
//	Animations
//-----------------------------------------------------------------------------
#define TOP_NOBALL	TOP_RDY			// Top animation when standing without ball
#define TOP_SHOOT3	TOP_3PJSHOT1


//-----------------------------------------------------------------------------
//	Quick & Dirty Computations
//-----------------------------------------------------------------------------
#define	DIR(plyr)		(((plyr)->no==Human3PtMatchPlayers[0])? 1:-1)
#define	A2B(plyr)		LFPAtn(-(plyr)->xco,DIR(plyr)*BASKET_Y-(plyr)->yco)
//#define	A2B(plyr,dir)	LFPAtn(-(plyr)->xco,current_basket_y-(plyr)->yco)
#define	P2I				(plyr->base+plyr->Rack3*5+plyr->Balls3-1)
#define	BS2B(m)			ball.m=bl->m
#define	B2BS(m)			bl->m=ball.m



//*****************************************************************************
//	External Data
//*****************************************************************************

extern vector16
	RackPosz[];			// Defined in Min.c by Phil

extern int
	gameOver,
	Human3PtMatchPlayers[2],
	Human3PtMatchControllers[2],
	Human3PtMatchScores[2];



//*****************************************************************************
//	Global Data
//*****************************************************************************
ballt	*Balls=0;
int		Num3PtPlayers=2;
int		end_time;
int		time_mark;



//*****************************************************************************
//	Local Data
//*****************************************************************************
int	pos_3pt[5][2]=
		{
			{ SP_X1, SP_Y1 },
			{ SP_X2, SP_Y2 },
			{ SP_X3, SP_Y3 },
			{-SP_X2, SP_Y2 },
			{-SP_X1, SP_Y1 },
		};

static int	bcamera=0;


//*****************************************************************************
//	Local Routine Declarations
//*****************************************************************************
void ai_NoBall(playert *plyr);
void ai_Grabbing(playert *plyr);
void ai_InHand(playert *plyr);
void ai_Shooting(playert *plyr);
void ai_Run(playert *plyr);
void ai_ShotBall(playert *plyr);

void init_NoBall(playert *plyr);

void JumpMove(playert *plyr);
void NextRack(playert *plyr);

void Balls2Ball(ballt *bl);
void Ball2Balls(ballt *bl);



//*****************************************************************************
//	Macro Routines
//*****************************************************************************
#define	SHUTDOWN								\
			if (time_left<=0)					\
			{									\
				plyr->main_routine=nothing;		\
				return;							\
			}



//*****************************************************************************
//	Routines
//*****************************************************************************

//-----------------------------------------------------------------------------
//	Routine
//		JumpMove
//
//	Description
//		Updates the player's z coordinate according to his current velocity and
//		gravitational acceleration if the player is in mid-air or has just
//		started his jump; otherwise, the routine simply returns.
//-----------------------------------------------------------------------------
void JumpMove(playert *plyr)
{
	CallChainP(JumpMove);

	if (plyr->zvel || plyr->zco)
	{
		plyr->zco+=plyr->zvel;
		if (plyr->zco<0)
		{
			plyr->zco=0;
			plyr->zvel=0;
		}
		else
			plyr->zvel-=LITTLE_G;
	}
}


#define	BAW	0x5C3000
#define	BAL	0xD30B00
//-----------------------------------------------------------------------------
//	Routine
//		Start3Pt
//
//	Description
//		This routine is called upon to initialize for the 3 point contest.
//-----------------------------------------------------------------------------
void Start3Pt()
{
	int				i;
	int				pi;		// Player index
	playert			*plyr;
	TeamRamData_T	*team;


	SetQuarterTime();	// also sets regular or tie-break times in 3pt contest
	time_mark=time_left;
	time_left+=ONE_SEC*3/2;
	end_time=time_left;
	reset_ai_flags();
	reset_celebration();

	CallChainInit();

	Num3PtPlayers=(Human3PtMatchPlayers[1]==-1)? 1 : 2;

	// Initialize the balls
	if (!Balls)
		Balls=MemMalloc(NUM_BALLS*sizeof(ballt),MEM_ANY);

	for (i=0; i<NUM_BALLS; i++)
	{
		Balls[i].xco=-BAW+(i%5)*BAW*2/4;
		Balls[i].yco=BAL-(i/5)*BAL/12;
		Balls[i].zco=BALL_RADIUS;
		Balls[i].xvel=0;
		Balls[i].yvel=0;
		Balls[i].zvel=0;
		Balls[i].main_routine=nothing;
		Balls[i].type=BALLTYPE_REGULAR;
		Balls[i].angle=0;
		Balls[i].path_list=0;
		Balls[i].ctr2=0;
		Balls[i].initial_zvel=0;
	}

	{
		matrix
			mtx;
		vector16
			vec;
		s32
			j,
			k;

		for (j=0; j<5; j++)
		{
			k = (j * 5) + 4;
			MakeMatPRH( &mtx, 0, 0, RackPosz[j].y );

			for (i=0; i<5; i++)
			{
				vec.x = (2 - i) * 240;
				vec.y = 0;
				vec.z = 0;
				Vec16MulMat( &vec, &mtx, &vec );

				Balls[k].xco = (s32)(vec.x + RackPosz[j].x) << 10;
				Balls[k].yco = (s32)(vec.z + RackPosz[j].z) << 10;
				Balls[k].zco = 1000<<10;

				Balls[k+25].xco=-Balls[k].xco;
				Balls[k+25].yco=-Balls[k].yco;
				Balls[k+25].zco= Balls[k].zco;

				k--;
			}

			Balls[k+1].type = BALLTYPE_MONEY;
			Balls[k+1+25].type=BALLTYPE_MONEY;
		}
	}


	// Duplicate functionality of start_quarter() here
	icon_flag=ICON_OFF;
	cut_flag=FALSE;
	replay_flag=FALSE;

	init_replay_buf();
	
	init_controls();

		for (i=0; i<Num3PtPlayers; i++)
		{
			// Instead of init_team(), initialize players in contest
			pi=Human3PtMatchPlayers[i];
			plyr=&player[pi];
			team=pcl__gMatch->apcl_mTeamRam[0];	// both guys on "same" team- mjk

			plyr->plyrRAM = team->ppcl_tPlyrLst[pi];

			plyr->teamRAM = team;
			plyr->teamROM = team->pcl__tTeamRom;

			setup_player(plyr);
			plyr->team = 0;
			plyr->base = 0;

			// New stuff specific to 3 Point Contest
			if (!i)
			{
				plyr->target_x=plyr->xco=pos_3pt[0][0];
				plyr->target_y=plyr->yco=pos_3pt[0][1];
				plyr->base=0;
			}
			else
			{
				plyr->target_x=plyr->xco=-pos_3pt[0][0];
				plyr->target_y=plyr->yco=-pos_3pt[0][1];
				plyr->base=NUM_BALLS/2;
			}

			plyr->zco=0;
			plyr->angle=A2B(plyr);

			plyr->control=Human3PtMatchControllers[i]+1;
			plyr->Rack3=0;
			plyr->Balls3=5;
			plyr->Score3=0;
			init_NoBall(plyr);
		}

	// Also in init_players
	ball_handler=0;
	bhp=&player[ball_handler];
	
	ball.xco=bhp->xco;	
	ball.yco=bhp->yco;

	// Return to regular initialization stuff here
	init_camera();
	InitRnd250();

	switch_flag=FALSE;
	switch_ends_flag = FALSE;

	tempo=mtempo=0x100;
}


void End3Pt()
{
	MemFree( Balls );
	Balls = NULL;
}


//-----------------------------------------------------------------------------
//	Routine
//		Contest3PtLoop
//
//	Description
//		Main loop for the 3 point contest.  This routine is called every game
//		frame to process everything that happens in the 3 point contest.  Each
//		player and the balls are processed as well as the crowd and other
//		ambient effects.
//-----------------------------------------------------------------------------
void Contest3PtLoop(SI *v)
{
	int		i, p;
	playert *plyr;

	CallChainP(Contest3PtLoop);

	get_dpad(v);


		for (p=0;p<4;p++)
		{
			ctrlrT	*ctrl;

			ctrl=&ctrlrs[p+1];

			if ((ctrlrs[p+1].ctrlr&CTRL_START) && !(ctrlrs[p+1].last&CTRL_START))
			{
				if (!menuFlag)
				{
					StartMenu( p, MENU_CONTEST );
					PauseAll( TRUE);

				}
				else
				{
					EndMenu( p );
					PauseAll( FALSE);

				}
				break;
			}
		}


	if (menuFlag)
		ProcessMenu( v );
	else
	{
		save_replay();
		advance_frame();
		get_angles_dist();

		// Update player(s)
		current_basket_y=BASKET_Y;
		plyr=&player[Human3PtMatchPlayers[0]];
		bhp=plyr;

		current_ctrlr=&ctrlrs[plyr->control];
		plyr->basket_angle=A2B(plyr);
		plyr->basket_dist=MANHATTAN(plyr->xco,plyr->yco-current_basket_y);

		if (time_left<=time_mark)
			plyr->main_routine(plyr);
		animate(plyr);

		// Update player 2
		if (Num3PtPlayers>1)
		{
			current_basket_y=-BASKET_Y;
			plyr=&player[Human3PtMatchPlayers[1]];
			bhp=plyr;

			current_ctrlr=&ctrlrs[plyr->control];
			plyr->basket_angle=A2B(plyr);
			plyr->basket_dist=MANHATTAN(plyr->xco,plyr->yco-current_basket_y);

			if (time_left<=time_mark)
				plyr->main_routine(plyr);
			animate(plyr);
		}

		// Update balls
		for (i=0; i<NUM_BALLS; i++)
		{
			int		dir;
			ballt	*bl=&Balls[i];

			current_basket_y=(i<25)? BASKET_Y : -BASKET_Y;
			dir=(i<25)? 1 : -1;
			bhp=&player[Human3PtMatchPlayers[(i<25)? 0 : 1]];

			Balls2Ball(bl);
			ball.basket_angle=A2B(&ball);
			ball.main_routine(&ball);
			Ball2Balls(bl);
		}

		Balls2Ball(&Balls[bcamera]);

		time_left--;
		end_time--;
		if (end_time==-ONE_SEC*7)
		{
			Human3PtMatchScores[0]=player[Human3PtMatchPlayers[0]].Score3;
			Human3PtMatchScores[1]=player[Human3PtMatchPlayers[1]].Score3;
			currentProcess->status = PROCESS_FREEING;
		}
		lp_ctr++;
		move_camera();


		if (gameOver)
			currentProcess->status = PROCESS_FREEING;
	}
}

//-----------------------------------------------------------------------------
//	Routine
//		Balls2Ball
//
//	Description
//		Copy the data from a ballt into the ball playert structure.  This is
//		a necessary step before processing the actiosn of the ball.  All code
//		works on a playert structure; however, such a structure is too large
//		to use with the ball array.  Therefore, each ball is copied into the
//		ball structure for processing.
//-----------------------------------------------------------------------------
void Balls2Ball(ballt *bl)
{
	BS2B(xco);
	BS2B(yco);
	BS2B(zco);

	BS2B(xvel);
	BS2B(yvel);
	BS2B(zvel);

	BS2B(main_routine);
	BS2B(basket_angle);

// Don't think this needs to be stored - Phil
//	BS2B(flip_xco);
//	BS2B(flip_yco);
//	BS2B(flip_zco);

	BS2B(angle);
	BS2B(path_list);
	BS2B(ctr2);
	BS2B(rim_bounce_count);
	BS2B(initial_zvel);

	ball_rotx = bl->rotx;
	ball_roty = bl->roty;
	ball_rotz = bl->rotz;

	ball_spinx = bl->spinx;
	ball_spiny = bl->spiny;
	ball_spinz = bl->spinz;

	ball.State3=bl->state;
	ball.Rack3=bl->rack;
	ball.Balls3=bl->ball;
	ball.Shooter3=bl->shooter;
}


//-----------------------------------------------------------------------------
//	Routine
//		Ball2Balls
//
//	Description
//		This routine copies the data out of the ball playert structure into a
//		ballt structure.  After AI processing, the 3 point contest loop calls
//		this routine to copy the data back into the ballt array.
//-----------------------------------------------------------------------------
void Ball2Balls(ballt *bl)
{
	B2BS(xco);
	B2BS(yco);
	B2BS(zco);

	B2BS(xvel);
	B2BS(yvel);
	B2BS(zvel);

	B2BS(main_routine);
	B2BS(basket_angle);

// Don't think this needs to be stored - Phil
//	B2BS(flip_xco);
//	B2BS(flip_yco);
//	B2BS(flip_zco);

	B2BS(angle);
	B2BS(path_list);
	B2BS(ctr2);
	B2BS(rim_bounce_count);
	B2BS(initial_zvel);

	bl->rotx = ball_rotx;
	bl->roty = ball_roty;
	bl->rotz = ball_rotz;

	bl->spinx = ball_spinx;
	bl->spiny = ball_spiny;
	bl->spinz = ball_spinz;

	bl->state=ball.State3;
	bl->rack=ball.Rack3;
	bl->ball=ball.Balls3;
	bl->shooter=ball.Shooter3;
}


//-----------------------------------------------------------------------------
//	Routine
//		init_NoBall
//
//	Description
//		Initializes the player into the NoBall state.
//-----------------------------------------------------------------------------
void init_NoBall(playert *plyr)
{
	CallChainP(init_NoBall);

	SetMain(init_NoBall,plyr,ai_NoBall);

	plyr->top_routine=NULL;
	plyr->leg_routine=NULL;

	plyr->top_rate=0x100;

	start_blend_anim(plyr,TOP_RDY);
	start_leg_anim(plyr,LEG_RDY);

	// If computer-controlled, set a delay for grabbing the ball
	if (!plyr->control)
		plyr->ctr2=15+RANDOM(25);
}


//-----------------------------------------------------------------------------
//	Routine
//		ai_NoBall
//
//	Description
//		Main routine handling the no ball state.  In this state, the player is
//		standing next to a rack of balls.  When the player presses a button,
//		the next ball is grabbed.
//-----------------------------------------------------------------------------
void ai_NoBall(playert *plyr)
{
	CallChainP(ai_NoBall);

	SHUTDOWN;

	if (!plyr->control)
	{
		if (!--plyr->ctr2)
			goto grab;
	}
	else if (CCTL_DOWN(CTRL_GRAB))
	{
		CCTL_CLRDOWN(CTRL_GRAB);
		CCTL_RMASK(CTRL_GRAB);
		jmask(CTRL_GRAB);
	grab:
		start_anim(plyr,TOP_GRAB1);
		SetMain(ai_NoBall,plyr,ai_Grabbing);
	}
}


//-----------------------------------------------------------------------------
//	Routine
//		ai_Grabbing
//
//	Description
//		Main routine run while the player is grabbing the ball from the rack.
//		It basically waits until the ball is grabbed then places it in the
//		player's hand and continues to the InHand state.
//-----------------------------------------------------------------------------
void ai_Grabbing(playert *plyr)
{
	CallChainP(ai_Grabbing);

	if (end_animation_test(plyr))
		switch(abs(plyr->top_anim))
		{
			case TOP_GRAB1:
				start_next_anim(plyr);
				Balls[P2I].main_routine=follow_player;
				Balls[P2I].shooter=plyr;
				bhp=plyr;

				//set possession flags
				loose_flag      = FALSE;
				rebound_flag    = FALSE;
				SetPossession(ai_Grabbing,TRUE);
				steal_ticks     = 0;
				possession_ticks= 0;
				back_down_ticks = 0	;
				SetDribbleFlag(ai_Grabbing,0);
				pivot_flag   = 0;
				rebound_time = 0;

				pick_ctr = 0;

				crossX = crossY = 0;

				break;

			case TOP_GRAB2:
				SHUTDOWN;
				SetMain(ai_Grabbing,plyr,ai_InHand);
				bcamera=P2I;
				if (!plyr->control)
					plyr->ctr2=10+RANDOM(10);
				break;

			default:
				BRK;
		}
}


//-----------------------------------------------------------------------------
//	Routine
//		ai_InHand
//
//	Description
//		Main routine to handle the state where the player is holding onto a
//		ball but hasn't shot it yet.  This just hangs around and waits until
//		the player presses the shoot button and then starts up the shot motion.
//-----------------------------------------------------------------------------
void ai_InHand(playert *plyr)
{
	CallChainP(ai_InHand);

	SHUTDOWN;

	if (!plyr->control)
	{
		if (!--plyr->ctr2)
			goto shoot_it;
	}
	else if (CCTL_DOWN(CTRL_SHOOT))
	{
	shoot_it:
		start_blend_anim(plyr,TOP_SHOOT3);
		SetMain(ai_InHand,plyr,ai_Shooting);
		plyr->State3=ST3_Leaping;
		plyr->top_rate=0x200;
		plyr->ctr2=0;
	}
}


//-----------------------------------------------------------------------------
//	Routine
//		ai_Shooting
//
//	Description
//		Main routine run while the player is shooting.  This is a scaled-down
//		version of the four jump_shot_rou* routines.  The actual feel is
//		identical to the in-game interface, but extraneous and pernicious code
//		relating to a 5-on-5 game has been removed.
//-----------------------------------------------------------------------------
void ai_Shooting(playert *plyr)
{
	bool shoot_flag=FALSE;

	CallChainP(ai_Shooting);

	JumpMove(plyr);

	switch(plyr->State3&ST3_Mask)
	{
		case ST3_Leaping:

			if (end_animation_test(plyr))
			{
				plyr->zvel=J_ZVEL;
				start_next_anim2(plyr,3);
				plyr->State3=(plyr->State3&(~ST3_Mask))|ST3_Hold;
			}
			break;

		case ST3_Hold:
			if (plyr->control)
				shoot_flag = ((current_ctrlr->ctrlr & CTRL_SHOOT) == 0);
			else
				shoot_flag=TRUE;

			if ((plyr->zco < 0x20000) & (plyr->zvel < 0))
				shoot_flag = TRUE;

			if (end_animation_test(plyr)) //shoot_flag)
			{
				start_next_anim(plyr);
				plyr->State3=(plyr->State3&(~ST3_Mask))|ST3_Up;
			}
			break;

		case ST3_Up:

			if (end_animation_test(plyr))
			{
				shoot_flag|=(time_till_land(plyr)<=8);
				possession_flag=TRUE;		// Ensure I am considered the ball handler
				ball_handler=plyr->no;
				release_jump_shot(plyr);

				Ball2Balls(&Balls[P2I]);
				Balls[P2I].main_routine=ai_ShotBall;
				Balls[P2I].shooter=plyr;
				if (time_left<=0)
					Balls[P2I].shooter=0;
				Balls[P2I].state=BS3_ToNet;
				Balls[P2I].rack=plyr->Rack3;
				Balls[P2I].ball=plyr->Balls3;

				plyr->Balls3--;  // Update ball counter

				start_next_anim2(plyr,time_till_land(plyr));
				plyr->State3=ST3_Down;
			}
			break;

		case ST3_Down:
			if (!plyr->zco)
			{
				CCTL_CLRDOWN(CTRL_GRAB);
				CCTL_RMASK(CTRL_GRAB);

				plyr->zvel=0;
				start_next_anim(plyr);
				plyr->top_rate*=2;
				plyr->State3=ST3_Landed;
			}
			break;

		case ST3_Landed:
			if (end_animation_test(plyr))
			{
				plyr->top_rate/=2;
				init_NoBall(plyr);
				NextRack(plyr);
			}
			break;
	}


	if (plyr->zco && !(plyr->State3&ST3_Counting))
	{
		if (CCTL_DOWN(CTRL_SHOOT))
			plyr->ctr2++;
		else
			plyr->State3|=ST3_Counting;
	}
}



//-----------------------------------------------------------------------------
//	Routine
//		NextRack
//
//	Description
//		After shooting, the ball, this routine checks to see if the player has
//		finished off all of the balls on the current rack.  If so, and this was
//		not the last rack, the player is sent on his merry way to start
//		shooting from the next rack.
//-----------------------------------------------------------------------------
void NextRack(playert *plyr)
{
	CallChainP(NextRack);

	if (!plyr->Balls3)	// Finished off this rack?
	{
		plyr->Balls3=5;
		if (plyr->Rack3<4)
		{
			plyr->Rack3++;
			plyr->target_x=plyr->xco+LFPCos(plyr->angle)*96;
			plyr->target_y=plyr->yco+LFPSin(plyr->angle)*96;
			SetMain(NextRack,plyr,ai_Run);
			plyr->State3=ST3_ClearRack;

		}
		else	// Finished off contest here
		{
			SetMain(NextRack,plyr,nothing);
			if (Num3PtPlayers==1 || 
				(player[Human3PtMatchPlayers[0]].main_routine==nothing && 
				 player[Human3PtMatchPlayers[1]].main_routine==nothing) )
				 if (time_left>ONE_SEC)
					end_time=ONE_SEC;
		}
	}
}


//-----------------------------------------------------------------------------
//	Routine
//		ai_Run
//
//	Description
//		Main routine that moves the player from one rack to the next by making
//		the player turn to the target point, run to it, and turn to face the
//		basket again.  Upon completing the journey, the player is put back into
//		the NoBall state.
//
//	Notes
//		* Currently, the player is simply teleported to the next spot
//-----------------------------------------------------------------------------
void ai_Run(playert *plyr)
{
	int	dx,dy,a;
	int	tx,ty;

	CallChainP(ai_Run);

	dx=plyr->target_x-plyr->xco;
	dy=plyr->target_y-plyr->yco;
	a=LFPAtn(dx,dy);
	switch(plyr->State3)
	{
		case ST3_ClearRack:
			move_to_place2(plyr);
			if (attack_home_in(plyr,a))
			{
				tx=pos_3pt[plyr->Rack3][0];
				ty=pos_3pt[plyr->Rack3][1];
				if (plyr->base)
				{
					tx=-tx;
					ty=-ty;
				}
				plyr->target_x=tx;
				plyr->target_y=ty;
				plyr->State3=ST3_Run;
			}
			else
			{
				top_deflt(plyr);
				running(plyr);
			}
			break;

		case ST3_Run:
			move_to_place2(plyr);
			if (attack_home_in(plyr,a))
			{
				plyr->xco=plyr->target_x;
				plyr->yco=plyr->target_y;
				plyr->State3=ST3_FaceNet;
			}
			else
			{
				top_deflt(plyr);
				running(plyr);
			}

			break;

		case ST3_FaceNet:
			if (turn_to(plyr,A2B(plyr)))
				init_NoBall(plyr);

			break;
	}
}


//-----------------------------------------------------------------------------
//	Routine
//		ai_ShotBall
//
//	Description
//		Main routine for the ball in motion.  This routine will call standard
//		ball main routines as the situation dictates.
//-----------------------------------------------------------------------------
void ai_ShotBall(playert *bl)
{
	void	(*or)(playert *);
	int		s3,s;

	CallChainP(ai_ShotBall);

	or=bl->main_routine;
	s3=bl->State3;

	switch(bl->State3)
	{
		case BS3_ToNet:
			shot_ball_move(bl);
			if (bl->main_routine==made_ball_move)
			{
				bl->main_routine=ai_ShotBall;
				bl->State3=BS3_Made;
			}
			else if (bl->main_routine==loose_ball_move)
			{
				bl->main_routine=ai_ShotBall;
				bl->State3=BS3_Missed;
			}
			break;

		case BS3_Made:
			made_ball_move(bl);
			if (bl->main_routine==drop_bounce)
			{
				if (bl->Shooter3)
					bl->Shooter3->Score3+= (bl->Balls3==1)? 2 : 1;
				bl->main_routine=ai_ShotBall;
				bl->State3=BS3_Missed;
			}
			break;

		case BS3_Missed:
			loose_ball_move(bl);
			if (bl->main_routine==ball_rolling)
			{
				bl->main_routine=ai_ShotBall;
				bl->State3=BS3_Roll;
			}
			break;

		case BS3_Roll:
			ball_rolling(bl);
			break;
	}
}
