// HotSpot.c

#include "ult_64.h"

#include "define.h"
#include "ml.h"

#include "misc.h"
#include "hotspot.h"


#define ON_TIME		(8*ONE_SEC)
#define OFF_TIME	(8*ONE_SEC)

#define FLASH_TIME (ONE_SEC/3)

#define SPOT_SIZE		1000
#define CHECK_SIZE	1000


typedef struct SData
{
	RGBA16
		Pal[3][16];
	u8
		Tex[3][64*64/2];
} SData;


static Vtx
	Verts[4];

static RGBA16
	Pal[16];

static SData
	*Data;

static s32
	Xpos,
	Ypos,
	Time;

static s8
	Team,
	Which,
	State,
	Flash,
	PalFlip;


void HotSpot_Init()
{
	if (ArcadeMode)
	{
		Data = AllocAndLoadFile( "HotSpot.TEX", MEM_ANY );

		Data->Pal[0][0].a = 0;
		Data->Pal[1][0].a = 0;
		Data->Pal[2][0].a = 0;

		State = OFF;
		Time = OFF_TIME;
		Team = -1;
		PalFlip = FALSE;
	}
}


void HotSpot_Deinit()
{
	if (ArcadeMode)
	{
		MemFree( Data );
	}
}


static void UpdatePal()
{
	s32
		i;

	if (State != OFF)
	{
		if (PalFlip)
		{
			for (i=1; i<16; i++)
				Pal[16-i] = Data->Pal[Which][i];
		}
		else
		{
			Copy16s( &Data->Pal[Which][0], Pal, 16 );
		}
	}
}


static void UpdateSpot()
{
	VertexN64
		*v;
	s32
		x,
		y;

	if (State != OFF)
	{
		x = Xpos;
		y = Ypos;


		v = (VertexN64 *)&Verts[0];

		v->x = x + SPOT_SIZE;
		v->y = 0;
		v->z = y + SPOT_SIZE;

		v->u = ( 0 << 6) + 32;
		v->v = ( 0 << 6) + 32;


		v++;

		v->x = x + SPOT_SIZE;
		v->y = 0;
		v->z = y - SPOT_SIZE;

		v->u = (63 << 6) + 32;
		v->v = ( 0 << 6) + 32;


		v++;

		v->x = x - SPOT_SIZE;
		v->y = 0;
		v->z = y - SPOT_SIZE;

		v->u = (63 << 6) + 32;
		v->v = (63 << 6) + 32;


		v++;

		v->x = x - SPOT_SIZE;
		v->y = 0;
		v->z = y + SPOT_SIZE;

		v->u = ( 0 << 6) + 32;
		v->v = (63 << 6) + 32;
	}
}


static void NewSpot()
{
	VertexN64
		*v;
	s32
		d,
		s,
		x,
		y;

	Flash = FLASH_TIME;
	Which = random( 3 );

	PalFlip = FALSE;
	UpdatePal();


	s = bhp->team ? -1 : +1;

	if (switch_ends_flag)
		s = -s;


	d = (SIDE_LINE - EDGE) >> (10-1);
	x = random( d ) - (d >> 1);

	d = (BASE_LINE - EDGE) >> 10;
	y = random( d ) * s;
	y &= ~3;


	Xpos = x;
	Ypos = y;

	UpdateSpot();
}


void HotSpot_Update()
{
	if (ArcadeMode && !Paused)
	{
		if (State != OFF)
		{
			Flash--;
			if (!Flash)
			{
				Flash = (FLASH_TIME * Time) / ON_TIME;

				if (Flash < 1)
					Flash = 1;

				PalFlip = !PalFlip;
				UpdatePal();
			}
		}


		if (possession_flag)
		{
			if (bhp->team != Team)			// Change of possession.
			{
				Team = bhp->team;

				State = ON;
				Time = ON_TIME;

				NewSpot();
			}
		}


		if (Team >= 0)
		{
			Time--;
			if (!Time)
			{
				if (State == OFF)
				{
					State = ON;
					Time = ON_TIME;

					NewSpot();
				}
				else
				{
					State = OFF;
					Time = OFF_TIME;
				}
			}
		}
	}
}


Gfx *HotSpot_Draw( Gfx *gp, u32 db )
{
	if (ArcadeMode && State != OFF)
	{
		gDPPipeSync( gp++ );

		gDPSetCombineMode( gp++, G_CC_DECALRGBA, G_CC_DECALRGBA );
		gDPSetRenderMode( gp++, G_RM_OPA_SURF, G_RM_OPA_SURF2 );
		gDPSetAlphaCompare( gp++, G_AC_THRESHOLD );
		gDPSetBlendColor( gp++, 0, 0, 0, 128 );

		gSPTexture( gp++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON );
		gDPSetTextureLUT( gp++, G_TT_RGBA16 );

		gDPLoadTextureBlock_4b( gp++,
														&Data->Tex[Which][0],
														G_IM_FMT_IA,
														64, 64,
														0,
														G_TX_CLAMP,
														G_TX_CLAMP,
														6, 6,
														G_TX_NOLOD, G_TX_NOLOD );

		gDPLoadTLUT_pal16( gp++, 0, Pal );

		gSPVertex( gp++, Verts, 4, 0 );

		gSP2Triangles( gp++, 0, 2, 1, 0, 0, 3, 2, 0 );
	}

	return( gp );
}


s32 HotSpot_Check( playert *plyr )
{
	s32
		x,
		y;

	if (!ArcadeMode || State == OFF)
		return( 0 );


	x = plyr->xco >> 10;
	y = plyr->yco >> 10;

	if (switch_ends_flag)
	{
		x = -x;
		y = -y;
	}

	if (abs( x - Xpos) < CHECK_SIZE &&
			abs( y - Ypos) < CHECK_SIZE)
	{
		return( (Which+1)*5 );
	}

	return( 0 );
}


s32 HotSpot_GetPos( s32 *x, s32 *y )
{
	if (!ArcadeMode || State == OFF)
		return( FALSE );

	*x = Xpos << 10;
	*y = Ypos << 10;

	return( TRUE );
}


void HotSpot_Save( s32 *buf )
{
	s32
		bits = 0;

	if (ArcadeMode)
	{
		bits |= (Xpos << 18);
		bits |= (Ypos & 0xfffc) << 2;
		bits |= (State & 1) << 3;
		bits |= (Which << 1);
		bits |= (PalFlip & 1);
	}

	*buf = bits;
}


void HotSpot_Load( s32 *buf )
{
	s32
		bits;

	if (ArcadeMode)
	{
		bits = *buf;

		Xpos = (bits >> 18);
		Ypos = (bits >> 2) & ~3;
		State = (bits >> 3) & 1;
		Which = (bits >> 1) & 3;
		PalFlip = (bits & 1);

		UpdatePal();
		UpdateSpot();
	}
}
