/****************************************************************************
*
* UWPARTS.C
*
*    VERSION : 00.00
*    CREATED : 2/07/98
*   MODIFIED : 2/07/98
*	   TABS : 5
*
* DESCRIPTION
*	Andy's strange underwater particles
*
*****************************************************************************/

/*---------------------------------------------------------------------------
 * Import Headers
\*--------------------------------------------------------------------------*/

#ifdef PSX_VERSION
#include "..\spec_psx\typedefs.h"
#include "..\spec_psx\gpu.h"
#include "..\spec_psx\maths.h"
#include <libgte.h>
#include <libgpu.h>
#include <gtemac.h>
#include <inline_c.h>
#else
#include "../specific/stypes.h"
#endif

#include "lara.h"
#include "snow.h"
#include "anim.h"
#include "objects.h"
#include "control.h"
#include "camera.h"

//void GetClosestSink();

/*---------------------------------------------------------------------------
 * Constants
\*--------------------------------------------------------------------------*/

#define SNOW_COLLISION

#define X 	0
#define Y 	1
#define Z		2

#define CENTREX 256
#define CENTREY 120

/*---------------------------------------------------------------------------
 * Externals
\*--------------------------------------------------------------------------*/

#ifdef PSX_VERSION
extern VECTOR3D CamPos, CamTgt;
#endif

extern WORD rcossin_tbl[];
extern long SmokeWindX, SmokeWindZ;
extern short IsRoomOutsideNo;
extern sint32 IsRoomOutsideExtra(sint32 x, sint32 y, sint32 z, sint32 oy, sint32 old_roomflags);

/*---------------------------------------------------------------------------
 * Globals
\*--------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------
 * Locals
\*--------------------------------------------------------------------------*/

static SNOWFLAKE uwparts[MAX_SNOWFLAKES];
//static long uwxvel;
//static long uwzvel;

/*---------------------------------------------------------------------------
 * Macros
\*--------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------
 * Public Functions
\*--------------------------------------------------------------------------*/

void DoUwEffect()
{
	long	x, y, z, radius, lp, angle, u1, u2, v1, v2, size, third, triggered;
	SNOWFLAKE	*snowptr;
	PSXSPRITESTRUCT *pSpriteInfo;
	POLY_FT3 	*ft3;

	short	*scrxy;	// X,Y
	long		*scrz;	// Z
	short	*TempMesh;

	scrxy = (short *) 0x1f800000;	// Set pointer to scratch pad.
	scrz = (long *) 0x1f800100;	// Set pointer to scratch pad.
	TempMesh = (short *) 0x1f800200;	// Set pointer to scratch pad.

	triggered = 0;

//	GetClosestSink();

// Update uwparts and trigger any if need be (i.e. Xpos = 0).

	snowptr = &uwparts[0];

	for ( lp=0 ; lp<MAX_SNOWFLAKES ; lp++ )
	{
		if (snowptr->x == 0 && triggered < 16)	// Trigger a new one.
		{
			triggered++;
			y = (GetRandomDraw()&2047)-1024;

			radius = (GetRandomDraw()&4095);
			angle = GetRandomDraw()&8190;

			x = (((rcossin_tbl[angle])*radius)>>12);
			z = (((rcossin_tbl[angle+1])*radius)>>12);

			snowptr->x = lara_item->pos.x_pos+x;
			snowptr->y = lara_item->pos.y_pos+y;
			snowptr->z = lara_item->pos.z_pos+z;
			if (IsRoomOutside(snowptr->x, snowptr->y, snowptr->z) < 0 ||
				!(room[IsRoomOutsideNo].flags & UNDERWATER))
			{
				snowptr->x = 0;
				snowptr++;
				continue;
			}

			snowptr->stopped = 1;
			snowptr->life = 16 + (GetRandomDraw()&7);
			snowptr->xv = (GetRandomDraw()&3);// + uwxvel;
			if (snowptr->xv == 2)
				snowptr->xv = -1;
			snowptr->yv = ((GetRandomDraw()&7) + 8)<<3;
			snowptr->zv = (GetRandomDraw()&3);// + uwzvel;
			if (snowptr->zv == 2)
				snowptr->zv = -1;
		}

		snowptr->x+=snowptr->xv;
		snowptr->y+=(snowptr->yv&(~7))>>6;
		snowptr->z+=snowptr->zv;

		if (!snowptr->life)
		{
			snowptr->x = 0;	// Turn it off.
			snowptr++;
			continue;
		}

		snowptr->life--;
		if ((snowptr->yv&7) < 7)
			snowptr->yv++;
		snowptr++;
	}

	pSpriteInfo=psxspriteinfo+objects[EXPLOSION1].mesh_index+17;
	u1 = pSpriteInfo->u1;
	u2 = pSpriteInfo->u2;
	v1 = pSpriteInfo->v1;
	v2 = pSpriteInfo->v2;

	mPushMatrix();
//	SetRotMatrix((MATRIX*) Matrix);
//	SetTransMatrix((MATRIX*) Matrix);
//	mTranslateXYZ(lara_item->pos.x_pos,lara_item->pos.y_pos,lara_item->pos.z_pos);
	mTranslateAbsXYZ(lara_item->pos.x_pos,lara_item->pos.y_pos,lara_item->pos.z_pos);

	ft3=(POLY_FT3*)db.polyptr;

	snowptr = &uwparts[0];

	for ( lp=0 ; lp<MAX_SNOWFLAKES ; lp++ )
	{
		if ((char *)ft3 >= db.polybuf_limit)
		{
			db.polyptr = (char *)ft3;
			mPopMatrix();
			return;
		}

		if (snowptr->x == 0)	// Not triggered?
		{
			snowptr++;
			continue;
		}

		TempMesh[X] = snowptr->x-lara_item->pos.x_pos;
		TempMesh[Y] = snowptr->y-lara_item->pos.y_pos;
		TempMesh[Z] = snowptr->z-lara_item->pos.z_pos;

  		gte_ldv0(TempMesh);
		gte_rtps();
		gte_stsxy(scrxy);
		gte_stsz(scrz);

		if ((*scrz) > 16384 || (*scrz) < 32 ||
			scrxy[X] < -32 ||
			scrxy[X] > 512+32 ||
			scrxy[Y] < -64 ||
			scrxy[Y] > 256+64)
		{
			if ((*scrz) < 32)
			{
				if (snowptr->life > 16)
			 		snowptr->life = 16;
			}
			snowptr++;
			continue;
		}

		size = (((snowptr->yv>>3))*phd_persp) / ((*scrz)>>2);
		if (size < 3)
			size = 3;
		else	if (size > 6)
			size = 6;

		third = (size * 0x5556)>>16;
		setlen(ft3, 7);
		setcode(ft3, 0x26);	// Transparent ft3.
		setXY3(ft3,scrxy[X]+third,scrxy[Y]-(third<<1),scrxy[X]+third,scrxy[Y]+third,scrxy[X]-(third<<1),scrxy[Y]+third);
		setUV3(ft3,u2,v1+1,u2,v2,u1+1,v2);

		if ((snowptr->yv&7) < 7)	// Fade in.
		{
			long	fadeval = (snowptr->yv&7)<<3;
			setRGB0(ft3,fadeval,fadeval,fadeval);
		}
		else if (snowptr->life > 18)	// Normal.
			setRGB0(ft3,64,64,64);
		else
			setRGB0(ft3,snowptr->life<<2,snowptr->life<<2,snowptr->life<<2);	// Fade out.
		ft3->clut = pSpriteInfo->clut;
		ft3->tpage = (pSpriteInfo->tpage & (~96)) | (1<<5);	// Set Colour addition.
		MyaddPrim( db.ot,((*scrz)>>3)+48, ft3 );
		ft3++;

		snowptr++;
	}
	db.polyptr = (uchar *) ft3;

	mPopMatrix();
}

/*void GetClosestSink()
{
	OBJECT_VECTOR *fixed;     // array of fixed camera positions
	PHD_VECTOR 	target;
	long			angle,dx,dy,dz,speed,sinkval,closestdist,closestnum,lp;

	if (lara.current_active)
	{
		uwxvel = lara.current_xvel>>9;
		uwzvel = lara.current_zvel>>9;
		return;
	}

	closestdist = 0x7fffffff;
	closestnum = -1;


	fixed = &camera.fixed[0];

	for (lp =0 ;lp<NumFixedCameras;lp++)
	{
		target.x = fixed->x;
		target.y = fixed->y;
		target.z = fixed->z;
		angle = ((mGetAngle(target.x,target.z,lara_item->pos.x_pos,lara_item->pos.z_pos)-0x4000)>>4)&4095;

		dx = target.x - lara_item->pos.x_pos;
		dy = target.y - lara_item->pos.y_pos;
		dz = target.z - lara_item->pos.z_pos;

		if (	dx < -0x6000 || dx > 0x6000 ||
			dy < -0x6000 || dy > 0x6000 ||
			dz < -0x6000 || dz > 0x6000 ||
			(fixed->data & 31) == 31)
		{
			fixed++;
			continue;
		}

		dx = SQUARE(dx);
		dx += SQUARE(dy);
		dx += SQUARE(dz);

		if (dx < closestdist)
		{
			closestdist = dx;
			closestnum = lp;
		}
		fixed++;
	}

	if (closestnum != -1)
	{
		sinkval = closestnum;
		target.x = camera.fixed[sinkval].x;
		target.y = camera.fixed[sinkval].y;
		target.z = camera.fixed[sinkval].z;
		angle = ((mGetAngle(target.x,target.z,lara_item->pos.x_pos,lara_item->pos.z_pos)-0x4000)>>4)&4095;

		dx = target.x - lara_item->pos.x_pos;
		dz = target.z - lara_item->pos.z_pos;

		closestdist = mSqrt(closestdist);

		speed = (camera.fixed[sinkval].data<<10);

		if (closestdist > speed)
			uwxvel = uwzvel = 0;
		else
		{
			speed = (speed - closestdist) >> 8;
			uwxvel = (((rcossin_tbl[(angle<<1)] * speed))) >> (W2V_SHIFT-2);
			uwzvel = (((rcossin_tbl[(angle<<1)+1] * speed))) >> (W2V_SHIFT-2);
		}
	}
	else
		uwxvel = uwzvel = 0;
} */
