
#include "generic.h"
#include "lfptypes.h"

#include "define.h"
#include "ml.h"
#include "playgfx.h"

#ifdef N64
 #include "shell.h"
 #include "sub.h"
 #include "min.h"
#endif


static void init_team(TeamRamData_T *team , playert *plyr);
void setup_player(playert *plyr);

global bool defense_flag=TRUE;


#define ONLY10GUYS	0	// early versions had on 10 guys in league


SI start_cos[]={

#ifdef DEBUG
 0,

 0x00, 0x40,
-0x40, -0x38,
 0x40, -0xc8,
-0x40, -0xc8,
 0x0, 0x90,

 0x00, -0x58,
-0x30, -0x80,
 0x20, -0xc8,
-0x20, -0xc8,
 0x0, 0xa0,
#endif

 4,

 0x20, -0x98,
-0x40, -0x70,
-0x40, -0x84,
-0x50, -0x80,
-0x20, 0x88,

 0x50, -0x70,
-0x50, -0x70,
 0x20, -0xc8,
-0x20, -0xc8,
 0x32, 0x57,
};



int tip_off_cos[]={
10,

-0x10,-0x1c,
 0x20, -0x02,
-0x4 ,-0x70,
-0x10, 0x1c,
-6   , -2,

 0x10,-0x1c,
 0x4 , 0x70,
-0x20, 0x02,
 0x10, 0x1c,
 6   , 2,
};



int home_inbound[]={
4,

-0x10, -0xc0,
 0x30, -0xc0,
-0x40, -0x50,
 0x40, -0x50,
-0x10, -0xf0,

-0x10, 0x40,
 0x30, 0x40,
-0x40, 0x40,
 0x40, 0x40,
-0x20, 0x40,
};


int away_inbound[]={
9,

 0x10,-0x40,
 0x30,-0x40,
-0x40,-0x40,
 0x40,-0x40,
-0x20,-0x40,

-0x10, 0xc0,
 0x30, 0xc0,
-0x40, 0x50,
 0x40, 0x50,
-0x10, 0xf0,
};


int away_halfcourt[]={
9,

 0x58, -0x20,
-0x40, -0x30,
 0x40, -0x60,
-0x40, -0x90,
 0x70, -0x30,

 0x60, -0x10,
-0x40, -0x20,
 0x60, -0x80,
-0x40, -0x80,
 0x88, -0x10,

};


int home_halfcourt[]={
4,

 0x60, 0x10,
-0x40, 0x20,
 0x60, 0x80,
-0x40, 0x80,
 0x88, 0x10,

 0x58, 0x20,
-0x40, 0x30,
 0x40, 0x90,
-0x40, 0x90,
 0x70, 0x30,
};


bool switch_ends_flag;


SB pressures[10];
SB doubles[10];
SB fronts[10];
SB markee[10];

int quarter_length;
int max_mins;


void start_game(void)
{
playert *plyr;
int i;

	memset(pressures, sizeof(pressures), 0);
	memset(doubles, sizeof(doubles), 0);
	memset(fronts, sizeof(fronts), 0);

	for (i=0;i<5;i++) 	markee[i]=i+5;
	for (;i<10;i++)		markee[i]=i-5;

	reset_markers();

	for (i=0; i<10; i++)
		player[i].flagrant=0;



	//high pressure on point gaurd
#ifndef MOVE
	//player[0].pressure = 2;
	//player[5].pressure = 2;
#endif

	//pcl__gMatch->apcl_mTeamRam[0]->ub___tTimeOuts = 7;
	//pcl__gMatch->apcl_mTeamRam[1]->ub___tTimeOuts = 7;

//#ifdef PC
	ai_team[0].current_set=
	ai_team[0].set1		  = 0;
	ai_team[0].set2		  = 1;

	ai_team[1].current_set=
	ai_team[1].set1		  = 1;
	ai_team[1].set2		  = 0;
//#endif


#ifdef N64
	/*
	ai_team[0].current_set=
	ai_team[0].set1		  = pcl__gMatch->apcl_mTeamRom[0]->ub___tDefaultSet0;
	ai_team[0].set2		  = pcl__gMatch->apcl_mTeamRom[0]->ub___tDefaultSet1;

	ai_team[1].current_set=
	ai_team[1].set1		  = pcl__gMatch->apcl_mTeamRom[1]->ub___tDefaultSet0;
	ai_team[1].set2		  = pcl__gMatch->apcl_mTeamRom[1]->ub___tDefaultSet1;
	*/
#endif

	max_mins	   = 
	quarter_length = time_left;
}



void start_quarter(int quarter)
{
int		i;
playert *plyr;


	icon_flag      = ICON_OFF;
	cut_flag		= FALSE;

	replay_flag=FALSE;	// BRS - just makin' sure
	AR_Time=0;
	init_replay_buf();

	switch_ends_flag = (quarter>1) ? TRUE: FALSE;

	init_team(pcl__gMatch->apcl_mTeamRam[0], &player[0]);
	init_team(pcl__gMatch->apcl_mTeamRam[1], &player[5]);


	ai_team[0].fouls_left =
	ai_team[1].fouls_left = 4;

	if (quarter>=4)
	{
		ai_team[0].fouls_left =
		ai_team[1].fouls_left = 3;
	}

	// clear team fouls
	pcl__gMatch->apcl_mTeamRam[0]->cl___tStatGame.uw___tTF = 0;
	pcl__gMatch->apcl_mTeamRam[1]->cl___tStatGame.uw___tTF = 0;

	SetNumberOfTimeOuts();	// fixes bug #342

	//following fixes bug #44(?)
	SetQuarterTime();	// sets time left
	quarter_length = time_left;
	max_mins += time_left;


	switch (quarter)
	{

	case -1:
		start_game();
		init_players(start_cos);
		in_play_flag    = TRUE;
		SetPossession(start_quarter,TRUE);
		break;

	case 0:
		start_game();
		init_players(tip_off_cos);
		break;

	case 1:
	case 2:
		init_players( (!tip_off_won) ? away_inbound: home_inbound);
		break;

	case 3:
		init_players( (tip_off_won) ? away_inbound: home_inbound);
		break;

	default:
		init_players(tip_off_cos);
		break;

	}

	stats_init();

	five_sec_clock =
	ten_sec_clock  = 0;
	new_shot_clock();

	reset_markers();

	ball.no=10;

#ifdef N64
	SubInitQuarter();
#endif
}


void InitBones(playert *plyr)
{
	s32
		i,
		x,
		y,
		z;

	for (i=0;i<MAX_BONES;i++)
	{
		plyr->aFrame.q[i].w = 0x4000;
		plyr->aFrame.q[i].x = 0;
		plyr->aFrame.q[i].y = 0;
		plyr->aFrame.q[i].z = 0;


		x = BoneOffs[i].x;
		y = BoneOffs[i].y;
		z = BoneOffs[i].z;

		if (i == NODE_LHAND)
		{
			x -= (BALL_RADIUS >> 10);
			y -= 220;
		}

		if (i == NODE_RHAND)
		{
			x += (BALL_RADIUS >> 10);
			y -= 220;
		}

		plyr->nodeOffset[i].x = (x * plyr->scale) >> 8;
		plyr->nodeOffset[i].y = (y * plyr->scale) >> 8;
		plyr->nodeOffset[i].z = (z * plyr->scale) >> 8;
	}
}


void refresh_player(playert *plyr)
{
int i;
int pnum, tnum;

// following line caused problems on Noah's machine (didn't get 0-9 - got # bytes difference)
//	plyr->no = (plyr-&player[0]);	this should have already been set up

	pnum = plyr->no;
	
	if(C3PT)
	{	// 3 point guys on same team - index 0-7
		plyr->teamRAM = pcl__gMatch->apcl_mTeamRam[0];
		plyr->plyrRAM = pcl__gMatch->apcl_mTeamRam[0]->ppcl_tPlyrLst[plyr->no];
	}
	else
	{
		tnum = pnum<5?0:1;
		plyr->teamRAM = pcl__gMatch->apcl_mTeamRam[tnum];
		plyr->plyrRAM = pcl__gMatch->apcl_mTeamRam[tnum]->ppcl_tPlyrLst[plyr->no%5];
	}

#ifdef PC
	plyr->plyrROM = PlyrRomArray + plyr->no;
#else
#if ONLY10GUYS	
	plyr->plyrROM = PlyrRomArray + plyr->no;
#else
	plyr->plyrROM = plyr->plyrRAM->pcl__pPlyrRom;
#endif
#endif

	plyr->scale	= (((plyr->plyrROM->ub___pHgt & 0xf0)>>4) * 12)
                  + (plyr->plyrROM->ub___pHgt & 0xf);


#ifdef DEBUG
	plyr->scale = (int)(3.1*plyr->scale);
#else
	plyr->scale = (int)(3.1*plyr->scale);
#endif


#ifdef N64
	{
		extern int midgetMode;
		if( (plyr->no < 5 && (midgetMode & 1))
			|| (plyr->no >= 5 && (midgetMode & 2)) )
		{
			plyr->scale=((int)plyr->scale*2)/3;
		}		
//		if(midgetMode == 1) plyr->scale=((int)plyr->scale*2)/3;
//		if(midgetMode == 2) plyr->scale=((int)plyr->scale*5)/4;  bigger causes problems with AI
	}
#endif


	

	plyr->no2 = (plyr->plyrROM->ub___pNum % 10) + ((plyr->plyrROM->ub___pNum / 10)<<4);

	plyr->turbo = TURBO_LIMIT;

	plyr->speed = MIN_MAX(plyr->plyrROM->ub___pAttrSpeed, 0x24, 0x2c);

#ifdef PAL
	plyr->speed = MIN_MAX(plyr->plyrROM->ub___pAttrSpeed, 0x2b, 0x34);
#endif

	plyr->strength  = 0x10000;
}


void  RefreshAllPlayers(void)
{
int i;

	for(i=0; i<10; i++)
	{
//		player[i].no = i;
		refresh_player(&player[i]);	// in case of substitution
	}
}

void setup_player(playert *plyr)
{

#ifdef PC
	plyr->plyrROM = PlyrRomArray + plyr->no;
#else
#if ONLY10GUYS	
	plyr->plyrROM = PlyrRomArray + plyr->no;
#else
	plyr->plyrROM = plyr->plyrRAM->pcl__pPlyrRom;
#endif
#endif


    plyr->top_anim       = TOP_RDY;
	plyr->top_frame      = 0;
	plyr->top_blend_ctr  = 0;
	plyr->top_rate       = 0x100;

    plyr->leg_anim		 = LEG_RDY;
	plyr->leg_frame		 = 0;
	plyr->leg_blend_ctr  = 0;
	plyr->leg_rate       = 0x100;

	plyr->flags&=~MOVE_ROOT;

	plyr->freeze_ctr = 0;
	plyr->kb_ctr	 = 0;
	plyr->hand_check_flag = 0;
	plyr->key_ctr    = 0;
	plyr->pitch      = 0;
	plyr->flags	     = 0;
	plyr->last_speed = 0;

	plyr->leg_routine  = NULL;
	plyr->top_routine  = NULL;
	SetMain(setup_player,plyr,nothing);

	refresh_player(plyr);
}



void init_team(TeamRamData_T *team , playert *plyr)
{
int i;

    for (i=0; i<5; i++)
	{
		plyr->teamRAM = team;
		plyr->plyrRAM = team->ppcl_tPlyrLst[i];

		plyr->teamROM = team->pcl__tTeamRom;

		setup_player(plyr);

		if (plyr->no < 5)
		{
			plyr->team = 0;
			plyr->base = 0;
		}
		else
		{
			plyr->team = 1;
			plyr->base = 5;
		}

		plyr++;
	}
}



global void init_players(int *pos_ptr)
{
UB i;
playert *plyr;

#ifdef PC
FILE *in;
#endif

#ifdef PC
 #ifndef PLAY
	time_left = 5*ONE_MIN;
	new_shot_clock();
 #endif
#endif


	i = 0;
    for (plyr=player; plyr<&player[13]; plyr++)
	{
        plyr->no = i++;
		plyr->dunk_declare=-1;
		plyr->bdcp=0xe;
		plyr->bdcc=0;
	}
    player[11].yco = POST_Y2;
    player[12].yco = POST_Y1;

    plyr         = player;
	SetBallHandler(init_players,*pos_ptr++);

    for (i=0; i<11; i++)
	{
		plyr->target_x = plyr->xco = *pos_ptr++ << 16;
		plyr->target_y = plyr->yco = *pos_ptr++ << 16;
		if (PracticeMode && i>4 && i<10)
			plyr->target_y=-FOUL_LINE;
		plyr->zco	   = 0;
		plyr->angle	   = LFPAtn(plyr->xco, plyr->yco-BASKET_Y);

		plyr->max_turbo=TURBO_LIMIT;
		plyr++;
	}

    ai_team[0].base      = 0;
    ai_team[1].base      = 5;
    ai_team[0].plyr1     = &player[0];
    ai_team[1].plyr1     = &player[5];
    ai_team[0].main_plyr = &player[4];
    ai_team[1].main_plyr = &player[9];




	if (ball_handler!=10)
	{
		for (i=0; i<10; i++)
		{
			SetMain(init_players,&player[i],deflt);
			player[i].leg_routine  = leg_deflt;
			player[i].top_routine  = top_deflt;

			#if defined(DEBUG) && 0
				#ifdef N64
				if (player[i].yco<-0x10000)
				{
					SetMain(init_players,&player[i],nothing);
					player[i].leg_routine  = NULL;
					player[i].top_routine  = NULL;
				}
				#endif

				#ifdef PC
//				if (player[i].yco<0)
				{
					SetMain(init_players,&player[i],nothing);
					player[i].leg_routine  = NULL;
					player[i].top_routine  = NULL;
				}
				#endif
			#endif



			#if defined(DEBUG) && defined(ML)
			if (player[i].yco<0)
			{
				SetMain(init_players,&player[i],nothing);
				player[i].leg_routine  = NULL;
				player[i].top_routine  = NULL;
			}
			#endif

			#ifdef DUNK
			if (player[i].yco<0)
			{
				SetMain(init_players,&player[i],nothing);
				player[i].leg_routine  = NULL;
				player[i].top_routine  = NULL;
			}
			#endif
		}

		bhp = &player[ball_handler];
		ball.zvel = ball.yvel = ball.zvel = 0;
		if(abs(bhp->target_x)<SIDE_LINE && abs(bhp->target_y)<BASE_LINE)
		{
			SetMain(init_players,bhp,dribble_animate);
			bhp->main_routine = dribble;
			bhp->leg_routine  = leg_deflt;
		}
		else
		{
			bhp->top_anim	  = TOP_PICKUP;
			bhp->leg_anim	  = 0;
			ball.zco		  = 0;
			bhp->top_rate     = 0xa0;
			start_pick_up_ball(bhp);
		}

		time_flag		  = FALSE;
		in_play_flag	  = FALSE;
		possession_flag	  = TRUE;
		ball.main_routine = follow_player;
		ball_place(bhp);

		SetDribbleFlag(init_players,0);

		get_angles_dist();

		for (plyr=player; plyr<&ball; plyr++)
		{
			if (BALL_HANDLER)	plyr->angle	= plyr->basket_angle;
			else				plyr->angle	= plyr->ball_angle;

			plyr++;
		}

		if (ball_handler > 4)
		{
			ai_team[0].main_plyr = bhp-5;
			ai_team[1].main_plyr = bhp;
		}
		else
		{
			ai_team[0].main_plyr = bhp;
			ai_team[1].main_plyr = bhp+5;
		}
	}
	else
	{
		//tip off
		to_init();
	}

	init_controls();

	/*
	 * start by going to correct positions
	 */


 #ifdef PC
	#ifdef MOVE

    in = fopen("..\\targets.bin","rb");
	if (in)
	{
		fread(targets, 1,sizeof(targets),in);
		fclose(in);
	}

	#endif
 #endif

	if (PracticeMode)
		for (i=0; i<5; i++)
		{
			plyr=&player[(bhp->base^5)+i];

			SetMain(init_players,plyr,nothing);
			plyr->top_routine=NULL;
			plyr->leg_routine=NULL;
			plyr->yco=plyr->target_y=-FOUL_LINE;
		}
}




