/****************************************************************************
*
* SNOW.C
*
*    VERSION : 00.00
*    CREATED : 2/07/98
*   MODIFIED : 2/07/98
*	   TABS : 5
*
* DESCRIPTION
*
*****************************************************************************/


/*---------------------------------------------------------------------------
 * 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"

/*---------------------------------------------------------------------------
 * 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];

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

/*---------------------------------------------------------------------------
 * Local Functions
\*--------------------------------------------------------------------------*/

void DoUwEffect()
{
	long	x, y, z, radius, lp, angle, u1, u2, v1, v2, size, out, 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;

// 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 < 8)	// 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;
			snowptr->yv = (GetRandomDraw()&7) + 8)<<3;
		}

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

		snowptr->life-=2;
		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);

	ft3=(POLY_FT3*)db.polyptr;

	snowptr = &uwparts[0];

	for ( lp=0 ; lp<MAX_SNOWFLAKES ; lp++ )
	{
		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 < 4)
			size = 4;
		else	if (size > 8)
			size = 8;

		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,72,72,72);
		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();
}

