
#include "lfptypes.h"
#include "define.h"
#include "ml.h"

/* #include ":Music:soundsgx.h"*/
/* #include "muzak.h"*/

#include "audio.h"
#include "sfxids.h"


#include "gamefx.h"

extern u8
	*GameBank;


typedef struct _FoulEvent
	{
	int	type;		// Foul type
	int	time;		// lp_ctr when the incident occured
	int	fouler;		// Index of player committing the foul
	int	foulee;		// Index of the player getting fouled
	} FoulEvent;

#define	FE_SIZE	50			// Number of elements in the fouler array

FoulEvent	FoulHistory[FE_SIZE];
int			FoulIndex=0;

#define	FE_FOUL(ty,t,fr,to)		\
			FoulHistory[FoulIndex].type=(ty);		\
			FoulHistory[FoulIndex].time=(t);		\
			FoulHistory[FoulIndex].fouler=(fr);	\
			FoulHistory[FoulIndex].foulee=(to);	\
			if (++FoulIndex==FE_SIZE) FoulIndex=0;


/**/
/**/
/**/

int fouler;
int foul_flag;
int foul_flag2;

static u8 HackSound=0;

void foul_check(void)
{
	if (!foul_flag2)	return;

	if ((ball.main_routine == shot_ball_move) || (dunk_flag) || shoot_stage)	return;

#if defined(DEBUG)
	{
		int		i;
		char	txt[128];
		char	num[16];

		for (i=0; i<16; i++)
			num[i]=0;

		IntToDecStr(lp_ctr,num);
		sprintf(txt,"%s: foul_check %d\n",num,foul_flag2);
		PCwrite(-1,txt,strlen(txt));
	}
#endif

	if (foul_flag2==CHARGING)
	{
		foul_flag2 = 0; 
		foul_set(player+fouler, CHARGING);
	}
	else if ((foul_flag2 == FLAGRANT) && (free_thrower !=last_shooter))
	{
		foul_flag2 = 0; 
		foul_set(player+fouler, FLAGRANT);
	}
	else
	{
		foul_flag2 = 0; 
		if (scored_flag)
		{
			foul_set(player+fouler, HACKING1);
		}
		else
		{
			if (pt3_flag)
			{
				//don't count last shot as 3Pt attempt
				if (player[last_shooter].plyrRAM->cl___pStatGame.uw___p3PA > player[last_shooter].plyrRAM->cl___pStatGame.uw___p3PM)
				{
					player[last_shooter].plyrRAM->cl___pStatGame.uw___p3PA -= 1;
					player[last_shooter].teamRAM->cl___tStatGame.uw___t3PA -= 1;
				#if defined(DEBUG)
					LogPointStats(foul_check,"3Pt Decrement",&player[last_shooter]);
				#endif
				}
				else
				{
				#ifdef DEBUG
					BRK;
				#endif
				}

				foul_set(player+fouler, HACKING3);
				return;
			}
			else
			{
				//don't count last shot as attempt
				if (player[last_shooter].plyrRAM->cl___pStatGame.uw___pFGA > player[last_shooter].plyrRAM->cl___pStatGame.uw___pFGM)
				{
					player[last_shooter].plyrRAM->cl___pStatGame.uw___pFGA -= 1;
					player[last_shooter].teamRAM->cl___tStatGame.uw___tFGA -= 1;
				}
				else
				{
					//BRK;
				}
			}

			foul_set(player+fouler, HACKING2);
		}

		free_thrower = ball_handler;
	}
}




int BestFT(int t)
{
	int	s,e,i,p,h;

	s=(t)? 1 : 6;
	e=s+4;

	p=s-1;
	h=player[p].plyrROM->ub___pAttrFT;

	for (i=s; i<e; i++)
		if (player[i].plyrROM->ub___pAttrFT>h)
		{
			h=player[i].plyrROM->ub___pAttrFT;
			p=i;
		}

	return p;
}


void foul_set (playert *plyr, int foul_type)
{
	crossX = crossY = 0;

	if (time_left <= 0)	return;

	if (foul_flag2)		return;


	switch (foul_type)
	{
	//whistle (buzzer sounded already for shot clock)
	//hacking blown already
	case SHOT_CLOCK:
	case HACKING1:
	case HACKING3:
		break;

	case HACKING2:
		if (HackSound)
			break;

		HackSound=1;

	default:
//old		AudioPlaySfx(SFX_ID_WHISTLE,22050,255,7);
		Audio_SfxPlay( GameBank, SFX_WHISTLE );
	}


	foul_flag = foul_type;
	fouler    = plyr->no;

	if ((ball.main_routine == shot_ball_move) || (dunk_flag) || (shoot_stage) )
	{
		foul_flag2 = foul_type;
		return;
	}
	else
		HackSound=0;

	got_pos_flag = FALSE;
	in_play_flag = FALSE;
	time_flag    = FALSE;
	dunk_flag    = FALSE;
	pass_flag    = FALSE;
	fast_break_flag = FALSE;

	if (ball.main_routine == pass_ball_move)
	{
		set_default(player+int_recvr);
	}

	#ifdef N64
	CamStopSpecial();
	#endif

//place ball at edge of court
	ball.target_x = (ball.xco > 0) ? SIDE_LINE+(EDGE/2): -SIDE_LINE-(EDGE/2);
	ball.target_y = ball.yco;

	//last_handler = plyr->no;

	switch(inbounds_flag)
	{
	case 1:
	case 2:
		ball.target_x = (ball.xco > 0) ? SIDE_LINE/2: -SIDE_LINE/2;
		ball.target_y = (ball.yco < 0) ?-BASE_LINE-EDGE: BASE_LINE+EDGE;
		break;

	case 3:
	case 4:
		ball.target_x = (ball.xco < 0) ?-SIDE_LINE-EDGE: SIDE_LINE+EDGE;
		if (ball.target_y > BASKET_Y)	ball.target_y = BASKET_Y;
		if (ball.target_y < -BASKET_Y)  ball.target_y = -BASKET_Y;
		break;

	}

	scored_flag = 0;
	free_throws = 0;

	switch (foul_type)
	{
	case THREE_SECOND:
	case TEN_SECOND:
	case FIVE_SECOND:
	case SHOT_CLOCK:
		SetLastHandler(foul_set,plyr->no);
		plyr->teamRAM->cl___tStatGame.uw___tTO++;
		break;

	case CHARGING:
		SetLastHandler(foul_set,plyr->no);
		AudioPlayCrowdSfx(AUDIO_CROWD_ROWDY+(lp_ctr&1));
		stats_foul(plyr);
		ai_team[plyr->no/5].fouls_left += 1;
		stats_TO(plyr);
		break;

	case FLAGRANT:
		SetLastHandler(foul_set,plyr->no);
		AudioPlayCrowdSfx(AUDIO_CROWD_ROWDY+(lp_ctr&1));
		stats_foul(plyr);
		free_throws=2;
		break;\

	case ILLEGAL_DEFENSE:
		stats_foul(plyr);
		if (++ai_team[fouler/5].illegalD>1)	// Has this foul occurred before?
		{
			//foul_flag=TECHNICAL;
			//free_thrower=ball_handler;	// choose technical guy here
			free_thrower=BestFT(bhp->team^1);
			free_throws=1;
		}
		break;

	case REACHING_IN:
		SetLastHandler(foul_set,plyr->no);
		AudioPlayCrowdSfx(AUDIO_CROWD_ROWDY+(lp_ctr&1));
		stats_foul(plyr);
		if ((ai_team[fouler/5].fouls_left < 0) || (shoot_stage==2))	free_throws=2;
		break;

	case TECHNICAL:
		//say technical foul
		SetLastHandler(foul_set,plyr->no);
		AudioPlayCrowdSfx(AUDIO_CROWD_ROWDY+(lp_ctr&1));
		free_throws=1;
		free_thrower=BestFT(plyr->team^1);
		break;

	case HACKING1:
	case HACKING2:
	case HACKING3:
		AudioPlayCrowdSfx(AUDIO_CROWD_ROWDY+(lp_ctr&1));
		free_throws = (1+foul_type-HACKING1);
		stats_foul(plyr);
		break;

	case HALF_COURT:
	case OUT_OF_BOUNDS:
		SetLastHandler(foul_set,plyr->no);
		if (possession_ticks>1)
		{
			stats_TO(plyr);
		}
		else if (plyr->no/5 == last_handler/5)
		{
			stats_TO(player+last_handler);
		}
		break;

	default:
		break;
	}

	if (foul_type<OUT_OF_BOUNDS)
	{
		new_shot_clock();
	}


	if (free_throws)
	{
		ball.target_x = 0;
		ball.target_y = (plyr->no > 4) ? FOUL_LINE+EDGE:-FOUL_LINE-EDGE;
	}


	if (possession_flag)	drop_ball(bhp);
	start_drop_bounce(&ball);

	last_bx  = ball.xco;
	last_by  = ball.yco;

	if (ball.zco<0x100000)	ball.zco = 0x100000;
	last_bz  = ball.zco;

	ball.xvel = ball.yvel = ball.zvel = 0;

	foul_commentary(plyr,foul_type);
}






#if 0

playert *plyr;


/*    ai_team[switch_flag].ideal     = cl___gHomeTeam.ud___tPlaying;*/
/*    ai_team[switch_flag^1].ideal   = cl___gAwayTeam.ud___tPlaying;*/

	time_flag	= FALSE;
	got_pos_flag = FALSE;
	in_play_flag= FALSE;	
	plyr		= &player[foul_flag-1];

	if ((plyr->routine == deflt) |
		(plyr->routine == stand_with_ball) |
		(plyr->routine == dribble))
	{
		if (foul_type == HACKING)
		{
/*wait for shot to drop*/

			if (bhp->routine == do_anim_seq)	return;		/* dunk*/
			if (ball.routine == shot_ball_move)	return;		/* ball still moving*/

			if (scored_flag)
			{
				foul_type = HACKING1;
			}
			else
			{
			}
		}

		scored_flag = 0;

		plyr->routine	= do_anim_seq;
		plyr->anim_ctr	= 0;
		plyr->anim_ptr	= fouled2;

		if (foul_type < TRAVELING)
		{
			plyr->plyr_RAM->ub___pFouls	+= 1;

            plyr->anim_ptr  = fouled;

			if (foul_type != CHARGING)
			{
				plyr->team_RAM->ub___tFouls	+= 1;
				if (ai_team[plyr->team].fouls_left)		ai_team[plyr->team].fouls_left--;
			}


		}
		score_up_flag	= 4;
		score_ctr	= 10000;

	}
}






void go_to_set_play (playert *plyr)
{
int j_pad;

	j_pad	= home_in2(plyr ,plyr->target_x - plyr->xco
							,plyr->target_y - plyr->yco);
	if (j_pad == -1)
	{
		if (turn_to(plyr, plyr->basket_angle))
		{
			if ((plyr == bhp) & possession_flag)	plyr->anim	= 0x52;
			else
			{
				if (no_ft >= 1)	plyr->anim	= 0x8f;
				else			plyr->anim	= 0x6b;
			}

			if ((plyr->flags & COLLIDE) == 0)
			{
				plyr->yco = plyr->target_y;
				plyr->xco = plyr->target_x;
			}
		}
		else	ball.flags = 0;
	}
	else
	{
		ball.flags	= j_pad;

		current_ctrlr->d_angle = asb__gDirXlate[j_pad]<<8;
		current_ctrlr->force   = 15;

		if ((plyr == bhp) & possession_flag)
		{
			plyr->anim |= 0x10;
			if ((plyr->anim & 7) == 4)
			{
/*                if (plyr->anim_ctr<RUN_ANIM_SPEED)  do_sound( plyr, 110, FLR_BNC_FX);*/
			}
			cur_team->main_plyr = plyr;
			get_new_controls(cur_team, plyr);
		}
	}
}


#endif

UB fouls_ok[4]={
1,
2,
3,
5,
};

bool foul_trouble(playert *plyr)
{
int q;

	q = pcl__gMatch->sb___mQuarter;
	if (q>3)	q=3;
	return (plyr->plyrRAM->cl___pStatGame.uw___pPF > fouls_ok[q]);
}


#if defined(DEBUG)

void _FoulSet
		(
		char	*routine,
		playert	*plyr,
		int		foul_type
		)
{
	int		i;
	char	txt[128];
	char	num[16];

	static char *FoulTxt[]=
					{
					"None",
					"Hacking1",
					"Hacking2",
					"Hacking3",
					"ReachingIn",
					"Flagrant",
					"Charging",
					"Technical",
					"Travelling",
					"ThreeSecond",
					"TenSecond",
					"FiveSecond",
					"ShotClock",
					"HalfCourt",
					"IllegalDefense",
					"OutOfBounds",
					"OverTheTop"
					};

	for (i=0; i<16; i++)
		num[i]=0;

	IntToDecStr(lp_ctr,num);
	sprintf(txt,"%s: foul_set(%d,%s) [%s]\n",num,plyr->no,FoulTxt[foul_type],routine);
	PCwrite(-1,txt,strlen(txt));

	foul_set(plyr,foul_type);
}
	
#endif
