/***************************************************************************
 *
 * ft.c
 *
 ***************************************************************************
 *
 * free throw player interface
 *
 ***************************************************************************/

/*
 * includes
 */

#include "ult_64.h"
#include "main.h"
#include "render.h"
#include "ctrl.h"
#include "n64res.h"
#include "resman.h"
#include "camera.h"
#include "cammodes.h"
#include "net.h"
#include "menu.h"
#include "misc.h"
#include "crowd.h"
#include "playgfx.h"
#include "ft.h"

/*
 * defines
 */

#define FT_TIME		120

#define SWEET_RANGE	200

#define FT_MAX_X	+1000
#define FT_MIN_X	-1000
#define FT_MAX_Y	4900
#define FT_MIN_Y	0

#define Y_SCALE 8


/*
 * typedefs
 */

/*
 * structures
 */

/*
 * globals
 */

int		freeThrowHelp;
int		inFreeThrow;
int ShowFreeThrowNet;
int AwayFreeThrow;

int		freeThrowScore;
int		motionStartTime;
int		defaultAim=256;
int		freeThrowX=0,freeThrowY=0;
int		freeThrowVX=0,freeThrowVY=0;
n64Script	*targetScript;
int		whichEnd=0;
int		freeThrowDrift=0;
int		freeThrowAim=0;
int		freeThrowRunning=0;
int		freeThrowVisible=0;
playert		*freeThrowPlayer=NULL;


#define	BarBw	24
#define	BarBh	103
#define	BarBs	32
#define	BarBy	(2048/BarBs)
#define	BarBsx	298
#define	BarBsy	98

#define	BarFw	24
#define	BarFh	99
#define	BarFs	32
#define	BarFy	(2048/BarFs)
#define	BarFsx	300
#define	BarFsy	100

#define	BarIw	24
#define	BarIh	2

#define	ShadW	32
#define	ShadWc	5
#define	ShadH	112
#define	ShadBPP	8
#define	ShadY	((2048/(1<<ShadWc))*8/ShadBPP)
#define	ShadXs	BarBsx
#define	ShadYs	BarBsy

typedef	struct range
{
	int	min,max;
} range;

range CapLims[]=
			{
				{5,14},
				{3,16},
				{2,17},
				{2,17},
				{1,18},
				{1,18}
			};

#define	CapLen		(sizeof(CapLims)/sizeof(CapLims[0]))

typedef struct FtBar
{
	u8		Back[BarBw*BarBh];
	u8		Shad[ShadW*ShadH];
	RGBA16	ForePal[256];
	u8		Fore[BarFw*BarFh];
	u8		Indicator[BarIw*BarIh];	
} FtBar;

FtBar	*Bar;

s32
	FTwait,
	FTstage,
	FTheight;


// Locals...

static s32
	Ypos,
	Ysize,
	Yspeed;


/*
 * function prototypes
 */

/*
 * code
 */


/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

void FreeThrowOpen(struct openSet *res)
{
	extern int	ID_SHP_TARGET;

//	targetScript=(n64Script *)ResOpenID(res,ID_SHP_TARGET);
	freeThrowRunning=0;
	SetFreeThrowVisible(FreeThrowOpen,0);
	inFreeThrow=0;
	freeThrowHelp=1;
	freeThrowPlayer=NULL;
	Bar=(FtBar *)AllocAndLoadFile("FREEBAR.TEX",MEM_ANY);
	*(u16 *)&Bar->ForePal[0] = 0;
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

void FreeThrowClose()
{
	MemFree( Bar );
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

void FreeThrowStart(int we,playert *p)
{
	static u8
		faceanims[] =
		{
			FACEANIM_BLINK,
			FACEANIM_CHEW,
			FACEANIM_SMILEA,
			FACEANIM_SMILEB,
			FACEANIM_SNEER
		};
	int		i;
	extern int	camActionBasket;

	inFreeThrow=1;
	if(freeThrowPlayer) return;

	freeThrowPlayer=p;

	AwayFreeThrow = p->team;

	FTwait = (2 * ONE_SEC);
	FTstage = 0;
	FTheight = p->scale * 6;

	if (p->control)
		CamStartSpecial(CAM_SPECIAL_FREETHROW,-2,1,0);
	else
		CamStartSpecial(CAM_SPECIAL_FREETHROW_CPU,-2,1,0);

	PlayGfx_SetFaceAnim( p->no, faceanims[random( 5 )], 0 );


	camActionBasket=(current_basket_y>0?1:-1);

	if (p->team == HOME_TEAM)
		whichEnd = +1;
	else
		whichEnd = -1;

	if (switch_ends_flag)
	{
		camActionBasket=-camActionBasket;
		whichEnd = -whichEnd;
	}


	if(p->control!=0)
	{
		if(freeThrowHelp)
		{
			StartMenu(-1,MENU_FTHELP);
			freeThrowHelp=0;
		}

		freeThrowX=MyRnd()*2000/256 - 1000;
#if 0
		if(MyRnd() & 8)
		{
			freeThrowX=-3000;
			freeThrowVX=120;
		}
		else
		{
			freeThrowX=3000;
			freeThrowVX=-120;
		}
#endif

		i=p->plyrROM->ub___pAttrFT;

		// factor in rookie/pro/all-star
//phil		i+=(2-(int)pcl__gMatch->pcl__mOptions->sb___Difficulty) * 25;
		if(i>100) i=100;

		Ypos = 0;
		Ysize = (100 * Y_SCALE);

		Yspeed = (108-i) >> 3;

		i=100-i;			// (now 0=excellent, 100=crap
		freeThrowAim=(i*1024/100)+256;	// 256-1280
		freeThrowDrift=0;


		freeThrowVX = (i*2) + 40;
		if (freeThrowX > 0)
			freeThrowVX = -freeThrowVX;


//		freeThrowY=MyRnd()*6000/256;
		freeThrowY = 0;
		freeThrowVY=MyRnd()/4;

//		freeThrowY=3000;
	}
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

void FreeThrowProcess(unsigned long ctrl,int timeLeft)
{
	int		x,y;
	extern long	cont[4];

	// get analog pos
	if(!freeThrowPlayer) return;
	if(freeThrowRunning && freeThrowPlayer->control)
	{
		ctrl=cont[freeThrowPlayer->control-1];

		if(ctrl & CTRL_LEFT)		x=-((ctrl>>24)&0x0F);
		else if(ctrl & CTRL_RIGHT)	x=((ctrl>>24)&0x0F);
		else x=0;
		if(ctrl & CTRL_DOWN)		y=-((ctrl>>28)&0x0F);
		else if(ctrl & CTRL_UP)		y=((ctrl>>28)&0x0F);
		else y=0;

		x=(x*freeThrowAim)/256;

//		freeThrowVX+=x;
		freeThrowVY+=y;

		freeThrowX+=freeThrowVX;
//		freeThrowY+=freeThrowVY;


		Ypos += (ctrl>>28) & 0x0F;
		Ypos -= 8;

		if (Ypos < 0)
			Ypos = 0;
		if (Ypos > 100)
			Ypos = 100;


		Ysize -= Yspeed;

		if (Ysize < (4 * Y_SCALE))
			Ysize = (4 * Y_SCALE);

//		freeThrowVX+=freeThrowDrift;

#if 0
		if (Ysize > 32)
			Ysize -= 2;
#endif

		if (freeThrowX < FT_MIN_X)
		{
			freeThrowX += FT_MIN_X - freeThrowX;
			freeThrowVX = -freeThrowVX;
		}

		if (freeThrowX > FT_MAX_X)
		{
			freeThrowX += FT_MAX_X - freeThrowX;
			freeThrowVX = -freeThrowVX;
		}

//		if(freeThrowY < FT_MIN_Y) { freeThrowY=FT_MIN_Y; freeThrowVY=0; }
//		if(freeThrowY > FT_MAX_Y) { freeThrowY=FT_MAX_Y; freeThrowVY=0; }

//		freeThrowY=3000;
	}
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

Gfx *FreeThrowRender(Gfx *gp,dyn *d)
{
	int	i;
	int	x,y;
	int	w,h;
	int	height;
	int	xo,yo;

	if (!freeThrowVisible || !possession_flag || Paused)
		return gp;

	if (!ICL_ROOKIE(&ctrlrs[freeThrowPlayer->control]) && !ScoreBoardCam)
	{
		ShowFreeThrowNet = TRUE;

		// Draw background chunk
		gDPPipeSync(gp++);
		gDPSetRenderMode(gp++,G_RM_XLU_SURF,G_RM_XLU_SURF);
		gDPSetCombineMode(gp++,G_CC_DECALRGBA,G_CC_DECALRGBA);
		gSPTexture(gp++,0x8000,0x8000,0,G_TX_RENDERTILE,G_ON);
		gDPSetTextureLUT( gp++, G_TT_NONE );

		for (y=0; y<BarBh; y+=BarBy)
		{
			h=BarBh-y;
			if (h>BarBy)
				h=BarBy;

			gDPLoadTextureBlock(gp++,&Bar->Back[y*BarBw],G_IM_FMT_IA,G_IM_SIZ_8b,
				BarBw,h,0,G_TX_WRAP,G_TX_WRAP,8,8,G_TX_NOLOD,G_TX_NOLOD);
			gSPTextureRectangle(gp++,(BarBsx)<<2,(BarBsy+y)<<2,(BarBsx+BarBw)<<2,(BarBsy+y+h)<<2,
				0,0,0,(1<<10),(1<<10));
		}

		// Draw the shadow
		gDPPipeSync(gp++);
		for (y=0; y<ShadH; y+=ShadY)
		{
			h=ShadH-y;
			if (h>ShadY)
				h=ShadY;

			gDPLoadTextureBlock(gp++,&Bar->Shad[y*ShadW],G_IM_FMT_IA,G_IM_SIZ_8b,
				ShadW,h,0,G_TX_WRAP,G_TX_WRAP,8,8,G_TX_NOLOD,G_TX_NOLOD);
			gSPTextureRectangle(gp++,(ShadXs)<<2,(ShadYs+y)<<2,(ShadXs+ShadW)<<2,(ShadYs+y+h)<<2,
				0,0,0,(1<<10),(1<<10));
		}

		// Draw sweetspot
		gDPPipeSync( gp++ );
		gDPSetRenderMode( gp++, G_RM_OPA_SURF, G_RM_OPA_SURF2 );
		gDPSetCombineMode( gp++, G_CC_DECALRGBA, G_CC_DECALRGBA );
		gDPSetBlendColor(gp++,0x00,0x00,0x00,0x08);
		gDPSetAlphaCompare(gp++,G_AC_THRESHOLD);
		gSPTexture( gp++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON );
		gDPSetTextureLUT( gp++, G_TT_RGBA16 );
		gDPLoadTLUT_pal256( gp++, Bar->ForePal);

		height = (Ysize * BarFh) / (100 * Y_SCALE);
		yo=(BarFh-height)/2;
		for (y=0; y<height; y+=BarFy)
		{
			h=height-y;
			if (h>BarFy)
				h=BarFy;
			
			gDPLoadTextureBlock(gp++,&Bar->Fore[(y+yo)*BarFw],G_IM_FMT_CI,G_IM_SIZ_8b,
				BarFw,h,0,G_TX_WRAP,G_TX_WRAP,8,8,G_TX_NOLOD,G_TX_NOLOD);
			gSPTextureRectangle(gp++,(BarFsx)<<2,(BarFsy+y+yo)<<2,(BarFsx+BarFw)<<2,(BarFsy+y+h+yo)<<2,
				0,0,0,(1<<10),(1<<10));
		}

		// Draw the indicator
		h=(Ypos*BarFh/100)-(BarIh-1)/2;
		w=BarIw;
		xo=0;

		if (h<CapLen)
		{
			xo=CapLims[h].min;
			w=CapLims[h].max;
		}
		else if (h>BarFh-CapLen)
		{
			i=BarFh-h;

			xo=CapLims[i].min;
			w=CapLims[i].max;
		}

		gDPLoadTextureBlock(gp++,Bar->Indicator,G_IM_FMT_CI,G_IM_SIZ_8b,
				BarIw,BarIh,0,G_TX_WRAP,G_TX_WRAP,5,5,G_TX_NOLOD,G_TX_NOLOD);
		gSPTextureRectangle(gp++,(BarFsx+xo)<<2,(BarFsy+h)<<2,(BarFsx+w)<<2,(BarFsy+h+BarIh)<<2,
			0,0,0,(1<<10),(1<<10));
	}

#ifdef phil
	int	q;

	// generate and load matrix

	MakeMat64PRH(&(d->shellLines[3]),
		     0*-16384*whichEnd,0,0,
		     freeThrowX/2,
		     0*freeThrowY,
		     0*whichEnd*13312,
		     256);

	gSPMatrix(gp++,&(d->shellLines[3]),G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);

	// render object, Z-buffered...
#if 0
	gSPSetGeometryMode(gp++,G_ZBUFFER);
	gDPSetDepthSource(gp++,G_ZS_PIXEL);
       	gSPTexture(gp++,0,0,0,0,G_OFF);
	gDPSetCombineMode(gp++,G_CC_PRIMITIVE,G_CC_PRIMITIVE);
	gDPSetRenderMode(gp++,G_RM_AA_ZB_OPA_SURF,G_RM_AA_ZB_OPA_SURF);

	N64ResDisablePrimCol(1);
//	q=freeThrowX<0?-freeThrowX:freeThrowX;
//	q=512*q/FT_MAX_X;
	q=lp_ctr-motionStartTime;
	q=(q*255)/FT_TIME;
	if(q>255) q=255;
	if(q<0) q=0;
	gDPSetPrimColor(gp++,0,0,q,255-q,32,255);
	N64ResAppendDL(targetScript,&gp,NULL);
	N64ResDisablePrimCol(0);
#else
	NetRender(&gp,0);
#endif

	gSPPopMatrix(gp++,G_MTX_MODELVIEW);
#endif

	return(gp);
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

void FreeThrowReturn(void)
{
	inFreeThrow=0;
	CamStopSpecial();
	Crowd_FreeThrow( FALSE );
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

void FreeThrowStop(void)
{
	SetFreeThrowVisible(FreeThrowStop,0);
	freeThrowPlayer=NULL;
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

void FreeThrowStartMotion(void)
{
	motionStartTime=lp_ctr;

	if(freeThrowPlayer->control==0) return;
	freeThrowRunning=1;
	SetFreeThrowVisible(FreeThrowStartMotion,1);
}

/***************************************************************************
 *
 *
 *
 ***************************************************************************
 *
 *
 *
 ***************************************************************************/

#define IN_RANGE(a,b) (((a)>=-(b)&&(a)<=(b))?TRUE:FALSE)

void FreeThrowStopMotion(void)
{
	s32
		size;

	FTstage++;

	freeThrowRunning = 0;
	freeThrowScore = 0;

	size = (Ysize >> 4);			// If Y_SCALE is changed, this must also be changed.

	if (IN_RANGE( freeThrowX, SWEET_RANGE ))
	{
		size += 8;

		if (IN_RANGE( Ypos-50, size ))
			freeThrowScore = 1;
	}
	else if (IN_RANGE( Ypos-50, size ))
	{
		size = SWEET_RANGE + 100;

		if (IN_RANGE( freeThrowX, size ))
			freeThrowScore = 1;
	}
}


