#include "..\game\game.h"
#include "..\game\fish.h"

#define	X	0
#define	Y	1
#define	Z	2
#define	XYZ	3
#define	MAX_TRIGGER_RANGE	0x4000

long	wibble = 0;
long	KillEverythingFlag = 0;
static	long	next_spark = 0;

long SmokeCountL, SmokeCountR;
long	SmokeWeapon,SmokeWind;
long SplashCount=0;
long	BatsTriggered;		// 0 = Not yet, 1 = update and draw.

short	SplashRings[8][2] = {	{0,-24},
							{17,-17},
							{24,0},
							{17,17},
							{0,24},
							{-17,17},
							{-24,0},
							{-17,-17}	};	// Multipliers for X and Z velocities going clockwise from top.

//
// 	Vertex order for splashes -
//
//  	0 - 7 	Bottom of inner ring.
//	8 - 15 	Top of inner ring.
//	16 - 23 	Bottom of middle ring.
//	24 - 31 	Top of middle ring.
//	32 - 39 	Bottom of outer ring.
//	40 - 47 	Top of outer ring.

SPLASH_SETUP	splash_setup;
SPLASH_STRUCT	splashes[MAX_SPLASHES];
RIPPLE_STRUCT	ripples[MAX_RIPPLES];
SP_DYNAMIC	spark_dynamics[32];
SPARKS		spark[MAX_SPARKS];
BAT_STRUCT	bats[MAX_BATS];

extern short rcossin_tbl[];

void InterpolateItemLights(ITEM_LIGHT *itemlight)
{
	sint32 x, z, distance, c_distance;
	sint16 angle, c_angle;

	z = itemlight->Tz<<1;
	x = itemlight->Tx<<1;
	angle = phd_atan(z, x);
	distance = phd_sqrt(z*z + x*x);

	// TODO: + need current angle and rotation, so worth adding to camera structure
	z = itemlight->z;
	x = itemlight->x;
	c_angle = phd_atan(z, x);
	c_distance = phd_sqrt(z*z + x*x);

	/* Linearly change both angle and distance to ideal values */
	angle -= c_angle;
	c_angle += angle >> 3;
	c_distance += (distance - c_distance) >> 3;
	itemlight->z = (c_distance * phd_cos(c_angle) >> W2V_SHIFT);
	itemlight->x = (c_distance * phd_sin(c_angle) >> W2V_SHIFT);
	itemlight->y += (itemlight->Ty - itemlight->y) >> 3;
	itemlight->adder += (itemlight->Tadder - itemlight->adder) >> 3;
	itemlight->overall += (itemlight->Toverall - itemlight->overall) >> 3;
}

void InitItemLights(ITEM_LIGHT *itemlight)
{
	itemlight->init++;
	itemlight->x = itemlight->Tx;
	itemlight->y = itemlight->Ty;
	itemlight->z = itemlight->Tz;
	itemlight->adder = itemlight->Tadder;
	itemlight->overall = 1;//itemlight->Toverall;
	if (itemlight->overall == 0)
		itemlight->overall = 1;
}

void DetatchSpark(long num, long type)	// Detatch a spark that's been assigned to an FX or an ITEM.
{
	long		lp;
	SPARKS	*sptr;
	FX_INFO	*fx;
	ITEM_INFO	*item;

	sptr = &spark[0];
	for (lp=0;lp<MAX_SPARKS;lp++)
	{
		if (sptr->On && (sptr->Flags & type) && sptr->FxObj == num)
		{
			if (type == SP_FX)
			{
				fx = &effects[num];
				sptr->x += fx->pos.x_pos;
				sptr->y += fx->pos.y_pos;
				sptr->z += fx->pos.z_pos;
				sptr->Flags &= (~SP_FX);
			}
			else if (type == SP_ITEM)
			{
				item = &items[num];
				sptr->x += item->pos.x_pos;
				sptr->y += item->pos.y_pos;
				sptr->z += item->pos.z_pos;
				sptr->Flags &= (~SP_ITEM);
			}
		}
	}

}

long	GetFreeSpark()
{
	long		lp,eldest,free;
	SPARKS	*sptr;

	sptr = &spark[next_spark];
	for (free = next_spark,lp=0;lp<MAX_SPARKS;lp++)
	{
		if (sptr->On == 0)
		{
			next_spark = (free+1) & (MAX_SPARKS-1);
			return(free);
		}

		if (free == MAX_SPARKS-1)
		{
			sptr = &spark[0];
			free = 0;
		}
		else
		{
			free++;
			sptr++;
		}
	}

// Couldn't find a free spark slot so find the eldest.

	eldest = 0xfff;
	free = 0;
	sptr = &spark[0];
	for (lp=0;lp<MAX_SPARKS;lp++)
	{
		if (sptr->Life < eldest && sptr->Dynamic == -1)	// Steal the eldest slot that doesn't control a dynamic light.
		{
			free = lp;
			eldest = sptr->Life;
		}
		sptr++;
	}

	next_spark = (free+1) & (MAX_SPARKS-1);
	return(free);
}

void	InitialiseSparks()
{
	long		lp;
	SPARKS	*sptr;

	sptr = &spark[0];
	for (lp=0;lp<MAX_SPARKS;lp++)
	{
		sptr->On = 0;
		sptr->Dynamic = -1;
		sptr++;
	}
}

void UpdateSparks()
{
	long		lp,lp1;
	long		divmult;

	long		random;

	SPARKS	*sptr;

	sptr = &spark[0];

	for (lp=0;lp<MAX_SPARKS;lp++)
	{
		if (sptr->On == 0)
		{
			sptr++;
			continue;
		}

		sptr->Life--;
		if (sptr->Life == 0)
		{
			if (sptr->Dynamic != -1)
			{
				spark_dynamics[sptr->Dynamic].On = 0;	// Turn off dynamic light controller.
				sptr->Dynamic = -1;
			}
			sptr->On=0;
			sptr++;
			continue;
		}

		if ((sptr->sLife - sptr->Life) < sptr->ColFadeSpeed)	// Faded to colour already?
		{
			divmult = (65536*(sptr->sLife-sptr->Life)) / sptr->ColFadeSpeed;
			sptr->R = sptr->sR + (((sptr->dR - sptr->sR) * divmult)>>16);
			sptr->G = sptr->sG + (((sptr->dG - sptr->sG) * divmult)>>16);
			sptr->B = sptr->sB + (((sptr->dB - sptr->sB) * divmult)>>16);
		}
		else	if (sptr->Life < sptr->FadeToBlack)	// Fade to black yet?
		{
			divmult = 65536-((65536*(sptr->FadeToBlack-sptr->Life)) / sptr->FadeToBlack);
			sptr->R = (sptr->dR * divmult)>>16;
			sptr->G = (sptr->dG * divmult)>>16;
			sptr->B = (sptr->dB * divmult)>>16;
		}
		else
		{
			sptr->R = sptr->dR;
			sptr->G = sptr->dG;
			sptr->B = sptr->dB;
		}

		if (sptr->Flags & SP_EXPDEF) //&& sptr->TransType == COLSUB || sptr->TransType == COLADD)
		{
			if (	sptr->R < 16 && sptr->G < 16 && sptr->B < 16)
				sptr->Def = objects[EXPLOSION1].mesh_index+3;
			else if (	sptr->R < 32 && sptr->G < 32 && sptr->B < 32)
				sptr->Def = objects[EXPLOSION1].mesh_index+2;
			else if (	sptr->R < 48 && sptr->G < 48 && sptr->B < 48)
				sptr->Def = objects[EXPLOSION1].mesh_index+1;
			else
				sptr->Def = objects[EXPLOSION1].mesh_index;

		}
		if (((sptr->sLife - sptr->Life) == (sptr->extras>>3)) && (sptr->extras&7))	// Ready to trigger more?
		{
			for (lp1=0;lp1<(sptr->extras&7);lp1++)
			{
	  			TriggerExplosionSparks(sptr->x,sptr->y,sptr->z,(sptr->extras&7)-1,sptr->Dynamic);
				sptr->Dynamic = -1;
//				RUMBLE(0x6000, 0x6000, 15, 0x400, 30);
			}
			sptr->extras = 0;
		}

		divmult = (65536*(sptr->sLife-sptr->Life)) / sptr->sLife;

		sptr->Yvel+=sptr->Gravity;
		if (sptr->MaxYvel)
		{
			if ((sptr->Yvel < 0 && sptr->Yvel < (sptr->MaxYvel<<5)) ||
				(sptr->Yvel > 0 && sptr->Yvel > (sptr->MaxYvel<<5)))
				sptr->Yvel = sptr->MaxYvel<<5;
		}

		if (sptr->Friction&15)
		{
			sptr->Xvel-=(sptr->Xvel>>(sptr->Friction&15));
			sptr->Zvel-=(sptr->Zvel>>(sptr->Friction&15));
		}

		if ((sptr->Friction>>4)&15)
			sptr->Yvel-=(sptr->Yvel>>((sptr->Friction>>4)&15));

		sptr->x += sptr->Xvel>>5;
		sptr->y += sptr->Yvel>>5;
		sptr->z += sptr->Zvel>>5;

		if (sptr->Flags & SP_WIND)
			sptr->z += SmokeWind>>1;

		sptr->Width = sptr->sWidth + (((sptr->dWidth - sptr->sWidth) * divmult)>>16);
		sptr->Height = sptr->sHeight + (((sptr->dHeight - sptr->sHeight) * divmult)>>16);

		sptr++;
	}

// Update and trigger any dynamic lights associated with sparks.

	sptr = &spark[0];
	for (lp=0;lp<MAX_SPARKS;lp++)
	{
		if (sptr->On && sptr->Dynamic != -1)
		{
			long		r,g,b,falloff;
			long		x,y,z;
			SP_DYNAMIC	*sdptr;

			sdptr = &spark_dynamics[sptr->Dynamic];
			if (sdptr->Flags & SD_EXPLOSION)
			{
				random = GetRandomControl();

				x = sptr->x + ((random & 0xf)<<4);
				y = sptr->y + ((random & 0xf0) );
				z = sptr->z + ((random & 0xf00) >> 4);

				falloff = sptr->sLife - sptr->Life - 1;
				if (falloff < 2)
				{
					if (sdptr->Falloff < 28)
						sdptr->Falloff+=6;
					r = 31-(random&3)-(falloff);
					g = 31-(random&3)-(falloff<<1);
					b = 31-(random&3)-(falloff<<3);
				}
				else if (falloff < 4)
				{
					if (sdptr->Falloff < 28)
						sdptr->Falloff+=6;
					r = 31-(random&3)-(falloff);
					g = 16-(falloff);
					b = 16-(falloff<<2);
					if (b<0)
						b=0;
				}
				else
				{
					if (sdptr->Falloff > 0)
						sdptr->Falloff--;
					r = 28+(random&3);
					g = 16+((random>>4)&3);
					b = ((random>>8)&7);
				}
				TriggerDynamic(x,y,z,((sdptr->Falloff > 31) ? 31:sdptr->Falloff),r,g,b);
			}

		}
		sptr++;
	}
}

void TriggerRicochetSpark(GAME_VECTOR *pos,long angle,long size)
{
	long		lp1;
	long		tangle;
	SPARKS	*sptr;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 255;
	sptr->sG = 32+(GetRandomControl()&31);
	sptr->sB = 0;

	sptr->dR = 192;
	sptr->dG = 96+(GetRandomControl()&63);
	sptr->dB = 0;

	sptr->ColFadeSpeed = 8;
	sptr->FadeToBlack = 4;
	sptr->sLife = sptr->Life = 16;
	sptr->TransType = COLADD;
	sptr->Dynamic = -1;

	sptr->x = pos->x;
	sptr->y = pos->y;
	sptr->z = pos->z;
	sptr->Gravity = sptr->MaxYvel = 0;

	tangle = (angle + ((GetRandomControl()&1023)-511)) & 4095;
	sptr->Zvel = (((((short)rcossin_tbl[(tangle<<1)+1])))>>1);
	sptr->Xvel = (-((((short)rcossin_tbl[(tangle<<1)])))>>1);
	sptr->Yvel = (GetRandomControl()&511)-256;
	sptr->Friction = 3;
	sptr->Flags = SP_RICOCHET;
	sptr->Height = sptr->sHeight = 32;
	sptr->dHeight = 2;

	sptr->x += sptr->Xvel>>3;	// Make ricochet spark long.
	sptr->y += sptr->Yvel>>3;
	sptr->z += sptr->Zvel>>3;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 255;
	sptr->sG = 32+(GetRandomControl()&31);
	sptr->sB = 0;

	sptr->dR = 192;
	sptr->dG = 96+(GetRandomControl()&63);
	sptr->dB = 0;

	sptr->ColFadeSpeed = 8;
	sptr->FadeToBlack = 8;
	sptr->sLife = sptr->Life = 24;
	sptr->TransType = COLADD;
	sptr->Dynamic = -1;

	sptr->x = pos->x;
	sptr->y = pos->y;
	sptr->z = pos->z;
	tangle = (angle + ((GetRandomControl()&2047)-1024)) & 4095;
	sptr->Zvel = (((((short)rcossin_tbl[(tangle<<1)+1])))>>1);
	sptr->Xvel = (-((((short)rcossin_tbl[(tangle<<1)])))>>1);
	sptr->Yvel = ((GetRandomControl()&511)-384)<<1;
	sptr->Friction = 1;
	sptr->Flags = SP_SCALE;
	sptr->Scalar = 3;
	sptr->Gravity = ((GetRandomControl()&31)) + (abs(sptr->Yvel>>6));
	sptr->Width = sptr->sWidth = (GetRandomControl()&3)+4;
	sptr->dWidth = (GetRandomControl()&1)+1;
	sptr->Height = sptr->sHeight = (GetRandomControl()&3)+4;
	sptr->dHeight = (GetRandomControl()&1)+1;
	sptr->MaxYvel = 0;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	lp1 = 128+(GetRandomControl()&63);
	sptr->sR = lp1;
	sptr->sG = lp1;
	sptr->sB = lp1;

	sptr->dR = lp1>>1;
	sptr->dG = lp1>>1;
	sptr->dB = lp1>>1;

	sptr->ColFadeSpeed = 8;
	sptr->FadeToBlack = 16;
	sptr->sLife = sptr->Life = 28;
	sptr->TransType = COLSUB;
	sptr->Dynamic = -1;

	sptr->x = pos->x;
	sptr->y = pos->y;
	sptr->z = pos->z;
	tangle = (angle + ((GetRandomControl()&2047)-1023)) & 4095;
	sptr->Zvel = (((((short)rcossin_tbl[(tangle<<1)+1])))>>1);
	sptr->Xvel = (-((((short)rcossin_tbl[(tangle<<1)])))>>1);
	sptr->Yvel = ((GetRandomControl()&511)-384);
	sptr->Friction = 1|32;
	sptr->Flags = SP_SCALE;
	sptr->Scalar = 3;
	sptr->Gravity = ((GetRandomControl()&7)) + 4;
	sptr->Width = sptr->sWidth = (GetRandomControl()&3)+4;
	sptr->dWidth = (GetRandomControl()&1)+1;
	sptr->Height = sptr->sHeight = (GetRandomControl()&3)+4;
	sptr->dHeight = (GetRandomControl()&1)+1;
	sptr->MaxYvel = 0;
}


void TriggerFlareSparks(long x, long y, long z,long xv,long yv,long zv, long smoke)
{
	SPARKS	*sptr;
	SPARKS	*sptr1;
	long size;
	long		dx,dz;

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

	if (dx < -MAX_TRIGGER_RANGE || dx > MAX_TRIGGER_RANGE || dz < -MAX_TRIGGER_RANGE || dz > MAX_TRIGGER_RANGE)
		return;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 255;
	sptr->sG = 255;
	sptr->sB = 255;

	sptr->dR = 255;
	sptr->dG = (GetRandomControl()&127)+64;
	sptr->dB = 192-sptr->dG;

	sptr->ColFadeSpeed = 3;
	sptr->FadeToBlack = 5;
	sptr->sLife = sptr->Life = 10;
	sptr->TransType = COLADD;
	sptr->Dynamic = -1;

	sptr->x = x+(GetRandomControl()&7)-3;
	sptr->y = y+(GetRandomControl()&7)-3;
	sptr->z = z+(GetRandomControl()&7)-3;
	sptr->Xvel = xv+((GetRandomControl()&255)-128);
	sptr->Yvel = yv+((GetRandomControl()&255)-128);
	sptr->Zvel = zv+((GetRandomControl()&255)-128);
	sptr->Friction = 2|(2<<4);
	sptr->Flags = SP_SCALE;
	sptr->Scalar = 1;
	sptr->Width = sptr->sWidth = (GetRandomControl()&3)+4;
	sptr->dWidth = (GetRandomControl()&1)+1;
	sptr->Height = sptr->sHeight = (GetRandomControl()&3)+4;
	sptr->dHeight = (GetRandomControl()&1)+1;
	sptr->Gravity = sptr->MaxYvel = 0;

	if (smoke)
	{
		sptr1 = &spark[GetFreeSpark()];

		sptr1->On = 1;

		sptr1->sR = sptr->dR>>1;
		sptr1->sG = sptr->dG>>1;
		sptr1->sB = sptr->dB>>1;

		sptr1->dR = 32;
		sptr1->dG = 32;
		sptr1->dB = 32;

		sptr1->ColFadeSpeed = 8 + (GetRandomControl()&3);
		sptr1->FadeToBlack = 4;
		sptr1->sLife = sptr1->Life = (GetRandomControl()&7)+13;

		sptr1->TransType = COLADD;

		sptr1->extras = 0;
		sptr1->Dynamic = -1;

		sptr1->x = x+(xv>>5);
		sptr1->y = y+(yv>>5);
		sptr1->z = z+(zv>>5);
		sptr1->Xvel = xv+((GetRandomControl()&63)-32);
		sptr1->Yvel = yv;//-(GetRandomControl()&15)-16;
		sptr1->Zvel = zv+((GetRandomControl()&63)-32);
		sptr1->Friction = 4;

//#ifdef	PC_VERSION
		if (GetRandomControl()&1)
		{
			sptr1->Flags = SP_SCALE|SP_DEF|SP_ROTATE|SP_EXPDEF;
			sptr1->RotAng = GetRandomControl()&4095;
			if (GetRandomControl()&1)
				sptr1->RotAdd = -(GetRandomControl()&15)-16;
			else
				sptr1->RotAdd = (GetRandomControl()&15)+16;
		}
		else
			sptr1->Flags = SP_SCALE|SP_DEF|SP_EXPDEF;
//#endif

		sptr1->Def = objects[EXPLOSION1].mesh_index;
		sptr1->Scalar = 2;
		sptr1->Gravity = -(GetRandomControl()&3)-8;
		sptr1->MaxYvel = -(GetRandomControl()&3)-4;
		size = 24+(GetRandomControl()&15);
		sptr1->Width = sptr1->sWidth = size>>3;
		sptr1->dWidth = size;
 		sptr1->Height = sptr1->sHeight = size>>3;
		sptr1->dHeight = size;
	}
}

void TriggerExplosionSparks(long x, long y, long z,long extra_trigs, long dyn)
{
	long		lp1,fric;
	SPARKS	*sptr;
	SP_DYNAMIC	*sdptr;
	unsigned char	extra_tab[6] = {	0,4,7,10	};
	long		dx,dz;

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

	if (dx < -MAX_TRIGGER_RANGE || dx > MAX_TRIGGER_RANGE || dz < -MAX_TRIGGER_RANGE || dz > MAX_TRIGGER_RANGE)
		return;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 255;
	sptr->sG = 32+(GetRandomControl()&15);
	sptr->sB = 0;

	sptr->dR = 192+(GetRandomControl()&63);
	sptr->dG = 128+(GetRandomControl()&63);
	sptr->dB = 32;

	sptr->ColFadeSpeed = 8;
	sptr->FadeToBlack = 16;
	sptr->sLife = sptr->Life = (GetRandomControl()&7)+24;
	sptr->TransType = COLADD;

	fric = extra_tab[extra_trigs]+(GetRandomControl()&7)-4;
	sptr->extras = extra_trigs|(fric<<3);

	sptr->Dynamic = dyn;

	if (dyn == -2)	// Set off a dynamic light controller for explosion.
	{
		sdptr = &spark_dynamics[0];
		for (lp1=0;lp1<32;lp1++)
		{
			if (!sdptr->On)
			{
				sdptr->On = 1;
				sdptr->Falloff = 4;
				sdptr->Flags = SD_EXPLOSION;
				sptr->Dynamic = lp1;
				break;
			}
			sdptr++;
		}

		if (lp1 == 32)
			sptr->Dynamic = -1;
	}

	sptr->x = x+(GetRandomControl()&31)-16;
	sptr->y = y+(GetRandomControl()&31)-16;
	sptr->z = z+(GetRandomControl()&31)-16;
	sptr->Xvel = ((GetRandomControl()&4095)-2048);
	sptr->Yvel = ((GetRandomControl()&4095)-2048);
	sptr->Zvel = ((GetRandomControl()&4095)-2048);

	if (dyn==-2)
	{
		sptr->x = x+(GetRandomControl()&511)-256;
		sptr->y = y+(GetRandomControl()&511)-256;
		sptr->z = z+(GetRandomControl()&511)-256;
	}
	else
	{
		sptr->x = x+(GetRandomControl()&31)-16;
		sptr->y = y+(GetRandomControl()&31)-16;
		sptr->z = z+(GetRandomControl()&31)-16;
	}

	sptr->Friction = 3|(3<<4);

//#ifdef	PC_VERSION
	if (GetRandomControl()&1)
	{
		sptr->Flags = SP_SCALE|SP_DEF|SP_ROTATE|SP_EXPDEF;
		sptr->RotAng = GetRandomControl()&4095;
		sptr->RotAdd = (GetRandomControl()&255)-128;
	}
	else
		sptr->Flags = SP_SCALE|SP_DEF|SP_EXPDEF;
//#endif

	sptr->Def = objects[EXPLOSION1].mesh_index;
	sptr->Scalar = 3;
	sptr->Gravity = 0;
	fric = (GetRandomControl()&15)+40;
	sptr->Width = sptr->sWidth = fric;
	sptr->dWidth = fric<<1;
	fric += (GetRandomControl()&7)+8;
 	sptr->Height = sptr->sHeight = fric;
	sptr->dHeight = fric<<1;
	sptr->MaxYvel = 0;

	if (extra_trigs == 0)
		TriggerExplosionSmokeEnd(x, y, z);
	else
		TriggerExplosionSmoke(x, y, z);
}

void TriggerExplosionSmokeEnd(long x, long y, long z)
{
	long		size;
	SPARKS	*sptr;
	long		dx,dz;

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

	if (dx < -MAX_TRIGGER_RANGE || dx > MAX_TRIGGER_RANGE || dz < -MAX_TRIGGER_RANGE || dz > MAX_TRIGGER_RANGE)
		return;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 144;
	sptr->sG = 144;
	sptr->sB = 144;

	sptr->dR = 64;
	sptr->dG = 64;
	sptr->dB = 64;

	sptr->ColFadeSpeed = 8;
	sptr->FadeToBlack = 64;
	sptr->sLife = sptr->Life = (GetRandomControl()&31)+96;
	sptr->TransType = COLSUB;

	sptr->extras = 0;
	sptr->Dynamic = -1;

	sptr->x = x+(GetRandomControl()&31)-16;
	sptr->y = y+(GetRandomControl()&31)-16;
	sptr->z = z+(GetRandomControl()&31)-16;
	sptr->Xvel = ((GetRandomControl()&4095)-2048)>>2;
	sptr->Yvel = (GetRandomControl()&255)-128;
	sptr->Zvel = ((GetRandomControl()&4095)-2048)>>2;
	sptr->Friction = 6;

//#ifdef	PC_VERSION
	sptr->Flags = SP_SCALE|SP_DEF|SP_ROTATE|SP_EXPDEF;
	sptr->RotAng = GetRandomControl()&4095;
	if (GetRandomControl()&1)
		sptr->RotAdd = -(GetRandomControl()&15)-16;
	else
		sptr->RotAdd = (GetRandomControl()&15)+16;
//#endif

	sptr->Def = objects[EXPLOSION1].mesh_index;
	sptr->Scalar = 3;
	sptr->Gravity = -(GetRandomControl()&3)-3;
	sptr->MaxYvel = -(GetRandomControl()&3)-4;
	size = (GetRandomControl()&31)+128;
	sptr->Width = sptr->sWidth = size>>2;
	sptr->dWidth = size;
	size += (GetRandomControl()&31)+32;
 	sptr->Height = sptr->sHeight = size>>3;
	sptr->dHeight = size;
}

void TriggerExplosionSmoke(long x, long y, long z)
{
	long		size;
	SPARKS	*sptr;
	long		dx,dz;

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

	if (dx < -MAX_TRIGGER_RANGE || dx > MAX_TRIGGER_RANGE || dz < -MAX_TRIGGER_RANGE || dz > MAX_TRIGGER_RANGE)
		return;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 144;
	sptr->sG = 144;
	sptr->sB = 144;

	sptr->dR = 64;
	sptr->dG = 64;
	sptr->dB = 64;

	sptr->ColFadeSpeed = 2;
	sptr->FadeToBlack = 8;
	sptr->sLife = sptr->Life = (GetRandomControl()&3)+10;
	sptr->TransType = COLSUB;

	sptr->extras = 0;
	sptr->Dynamic = -1;

	sptr->x = x+(GetRandomControl()&511)-256;
	sptr->y = y+(GetRandomControl()&511)-256;
	sptr->z = z+(GetRandomControl()&511)-256;
	sptr->Xvel = ((GetRandomControl()&4095)-2048)>>2;
	sptr->Yvel = (GetRandomControl()&255)-128;
	sptr->Zvel = ((GetRandomControl()&4095)-2048)>>2;
	sptr->Friction = 6;

//#ifdef	PC_VERSION
	sptr->Flags = SP_SCALE|SP_DEF|SP_ROTATE|SP_EXPDEF;
	sptr->RotAng = GetRandomControl()&4095;
	sptr->RotAdd = (GetRandomControl()&15)+16;
//#endif

	sptr->Def = objects[EXPLOSION1].mesh_index;
	sptr->Scalar = 3;
	sptr->Gravity = -(GetRandomControl()&3)-3;
	sptr->MaxYvel = -(GetRandomControl()&3)-4;
	size = (GetRandomControl()&31)+128;
	sptr->Width = sptr->sWidth = size>>2;
	sptr->dWidth = size;
	size += (GetRandomControl()&31)+32;
 	sptr->Height = sptr->sHeight = size>>3;
	sptr->dHeight = size;
}

void TriggerFireSmoke(long x, long y, long z, long body_part, long type)
{
	long		size;
	SPARKS	*sptr;
	long		dx,dz;

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

	if (dx < -MAX_TRIGGER_RANGE || dx > MAX_TRIGGER_RANGE || dz < -MAX_TRIGGER_RANGE || dz > MAX_TRIGGER_RANGE)
		return;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 0;
	sptr->sG = 0;
	sptr->sB = 0;

	sptr->dR = 32;
	sptr->dG = 32;
	sptr->dB = 32;

	if (body_part!=-1)
	{
		sptr->ColFadeSpeed = 4 + (GetRandomControl()&3);
		sptr->FadeToBlack = 12;
		sptr->sLife = sptr->Life = (GetRandomControl()&3)+20;
	}
	else
	{
		sptr->ColFadeSpeed = 32 + (GetRandomControl()&7);
		sptr->FadeToBlack = 16;
		sptr->sLife = sptr->Life = (GetRandomControl()&15)+57;
	}

	sptr->TransType = COLADD;

	sptr->extras = 0;
	sptr->Dynamic = -1;

	sptr->x = x + ((GetRandomControl()&15)-8);
	sptr->y = y - (GetRandomControl()&127)-256;
	sptr->z = z + ((GetRandomControl()&15)-8);
	sptr->Xvel = ((GetRandomControl()&255)-128);
	sptr->Yvel = -(GetRandomControl()&15)-16;
	sptr->Zvel = ((GetRandomControl()&255)-128);
	sptr->Friction = 4;

//#ifdef	PC_VERSION
	if (GetRandomControl()&1)
	{
		sptr->Flags = SP_SCALE|SP_DEF|SP_ROTATE|SP_EXPDEF;
		sptr->RotAng = GetRandomControl()&4095;
		if (GetRandomControl()&1)
			sptr->RotAdd = -(GetRandomControl()&15)-16;
		else
			sptr->RotAdd = (GetRandomControl()&15)+16;
	}
	else
		sptr->Flags = SP_SCALE|SP_DEF|SP_EXPDEF;
//#endif

	sptr->Def = objects[EXPLOSION1].mesh_index;
	sptr->Scalar = 3;
	sptr->Gravity = -(GetRandomControl()&15)-16;
	sptr->MaxYvel = -(GetRandomControl()&7)-8;
	size = (GetRandomControl()&63)+64;
	sptr->Width = sptr->sWidth = size>>2;
	sptr->dWidth = size;
 	sptr->Height = sptr->sHeight = size>>2;
	sptr->dHeight = size;
}

void TriggerGunSmoke(long x, long y, long z, long xv, long yv, long zv, long initial, long weapon, long count)
{
	long		size;
	SPARKS	*sptr;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 0;
	sptr->sG = 0;
	sptr->sB = 0;

	sptr->dR = count<<2;
	sptr->dG = count<<2;
	sptr->dB = count<<2;

	sptr->ColFadeSpeed = 4;
	sptr->FadeToBlack = 32-(initial<<4);
	sptr->sLife = sptr->Life = (GetRandomControl()&3)+40;

	if (weapon == LG_PISTOLS || weapon == LG_MAGNUMS || weapon == LG_UZIS)
	{
		if (sptr->dR > 64)
		{
			sptr->dR = 64;
			sptr->dG = 64;
			sptr->dB = 64;
		}
	}

	sptr->TransType = COLADD;

	sptr->extras = 0;
	sptr->Dynamic = -1;

	sptr->x = x+(GetRandomControl()&31)-16;
	sptr->y = y+(GetRandomControl()&31)-16;
	sptr->z = z+(GetRandomControl()&31)-16;

	if (initial)
	{
		sptr->Xvel = ((GetRandomControl()&1023)-512)+xv;
		sptr->Yvel = ((GetRandomControl()&1023)-512)+yv;
		sptr->Zvel = ((GetRandomControl()&1023)-512)+zv;
	}
	else
	{
		sptr->Xvel = ((GetRandomControl()&511)-256)>>1;
		sptr->Yvel = ((GetRandomControl()&511)-256)>>1;
		sptr->Zvel = ((GetRandomControl()&511)-256)>>1;
	}
	sptr->Friction = 4;

//#ifdef	PC_VERSION
	if (GetRandomControl()&1)
	{
		sptr->Flags = SP_SCALE|SP_DEF|SP_ROTATE|SP_WIND|SP_EXPDEF;
		sptr->RotAng = GetRandomControl()&4095;
		if (GetRandomControl()&1)
			sptr->RotAdd = -(GetRandomControl()&15)-16;
		else
			sptr->RotAdd = (GetRandomControl()&15)+16;
	}
	else
		sptr->Flags = SP_SCALE|SP_DEF|SP_WIND|SP_EXPDEF;
//#endif

	sptr->Def = objects[EXPLOSION1].mesh_index;
	sptr->Scalar = 3;
	sptr->Gravity = -(GetRandomControl()&1)-2;
	sptr->MaxYvel = -(GetRandomControl()&1)-2;
	size = (GetRandomControl()&7)+24-((weapon != LG_ROCKET) ? 12:0);

	if (initial)
	{
		sptr->Width = sptr->sWidth = size>>1;
		sptr->dWidth = (size<<1)+8;
	}
	else
	{
		sptr->Width = sptr->sWidth = size>>2;
		sptr->dWidth = size;
	}

	if (initial)
	{
 		sptr->Height = sptr->sHeight = size>>1;
		sptr->dHeight = (size<<1)+8;
	}
	else
	{
 		sptr->Height = sptr->sHeight = size>>2;
		sptr->dHeight = size;
	}
}

void TriggerFireFlame(long x, long y, long z, long body_part, long type)
{
	long		size;
	SPARKS	*sptr;
	long		dx,dz;

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

	if (dx < -MAX_TRIGGER_RANGE || dx > MAX_TRIGGER_RANGE || dz < -MAX_TRIGGER_RANGE || dz > MAX_TRIGGER_RANGE)
		return;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	if (type != 2)
	{
		sptr->sR = 255;
		sptr->sG = 48+(GetRandomControl()&31);
		sptr->sB = 48;
	}
	else
	{
		sptr->sR = 48+(GetRandomControl()&31);
		sptr->sG = sptr->sR;
		sptr->sB = 192+(GetRandomControl()&63);
	}

	sptr->dR = 192+(GetRandomControl()&63);
	sptr->dG = 128+(GetRandomControl()&63);
	sptr->dB = 32;

	if (body_part != -1)
	{
		sptr->ColFadeSpeed = 8 + (GetRandomControl()&3);
		sptr->FadeToBlack = 16;
		sptr->sLife = sptr->Life = (GetRandomControl()&3)+28;
	}
	else
	{
		if (type != 2)
		{
			sptr->ColFadeSpeed = 20 + (GetRandomControl()&3);
			sptr->FadeToBlack = 8;
			sptr->sLife = sptr->Life = (GetRandomControl()&7)+40;
		}
		else
		{
			sptr->ColFadeSpeed = 5 + (GetRandomControl()&3);
			sptr->FadeToBlack = 6;
			sptr->sLife = sptr->Life = (GetRandomControl()&3)+16;
		}
	}

	sptr->TransType = COLADD;

	sptr->extras = 0;
	sptr->Dynamic = -1;

 	if (body_part != -1)	// Attached to Fx.
	{
		sptr->x = ((GetRandomControl()&31)-16);
		sptr->y = 0;
		sptr->z = ((GetRandomControl()&31)-16);
	}
	else
	{
		if (type != 2)
		{
			sptr->x = x + ((GetRandomControl()&31)-16);
			sptr->y = y;
			sptr->z = z + ((GetRandomControl()&31)-16);
		}
		else
		{
			sptr->x = x + ((GetRandomControl()&15)-8);
			sptr->y = y;
			sptr->z = z + ((GetRandomControl()&15)-8);
		}
	}

	if (type != 2)
	{
		sptr->Xvel = ((GetRandomControl()&255)-128);
		sptr->Yvel = -(GetRandomControl()&15)-16;
		sptr->Zvel = ((GetRandomControl()&255)-128);
		if (type == 1)
			sptr->Friction = 3|(3<<4);
		else
			sptr->Friction = 5;
	}
	else
	{
		sptr->Xvel = ((GetRandomControl()&31)-16);
		sptr->Yvel = -(GetRandomControl()&511)-1024;
		sptr->Zvel = ((GetRandomControl()&31)-16);
		sptr->Friction = 4|(4<<4);
	}

//#ifdef	PC_VERSION
	if (GetRandomControl()&1)
	{
		if (body_part != -1)	// Attached to Fx.
		{
			sptr->Flags = SP_SCALE|SP_DEF|SP_ROTATE|SP_FX|SP_EXPDEF;
			sptr->FxObj = body_part;
			sptr->Gravity = -(GetRandomControl()&63)-32;
			sptr->MaxYvel = -(GetRandomControl()&7)-24;
		}
		else
		{
			sptr->Gravity = -(GetRandomControl()&31)-16;
			sptr->MaxYvel = -(GetRandomControl()&7)-16;
			sptr->Flags = SP_SCALE|SP_DEF|SP_ROTATE|SP_EXPDEF;
		}
		sptr->RotAng = GetRandomControl()&4095;
		if (GetRandomControl()&1)
			sptr->RotAdd = -(GetRandomControl()&15)-16;
		else
			sptr->RotAdd = (GetRandomControl()&15)+16;
	}
	else
	{
		if (body_part != -1)	// Attached to Fx.
		{
			sptr->Flags = SP_SCALE|SP_DEF|SP_FX|SP_EXPDEF;
			sptr->FxObj = body_part;
			sptr->Gravity = -(GetRandomControl()&63)-32;
			sptr->MaxYvel = -(GetRandomControl()&7)-24;
		}
		else
		{
			sptr->Flags = SP_SCALE|SP_DEF|SP_EXPDEF;
			sptr->Gravity = -(GetRandomControl()&31)-16;
			sptr->MaxYvel = -(GetRandomControl()&7)-16;
		}
	}
//#else

	sptr->Def = objects[EXPLOSION1].mesh_index;
	sptr->Scalar = 2;
	if (type == 0)
		size = (GetRandomControl()&31)+128;
	else if (type == 1)
		size = (GetRandomControl()&31)+64;
	else
	{
		sptr->Gravity = sptr->MaxYvel = 0;
		size = (GetRandomControl()&31)+32;
	}
	sptr->Width = sptr->sWidth = size;
 	sptr->Height = sptr->sHeight = size;
	if (type != 2)
	{
		sptr->dWidth = size>>4;
		sptr->dHeight = size>>4;
	}
	else
	{
		sptr->dWidth = size>>2;
		sptr->dHeight = size>>2;
	}
}

void TriggerSideFlame(long x, long y, long z, long angle, long speed, long pilot)
{
	long		size,zv,xv;
	SPARKS	*sptr;
	long		dx,dz;

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

	if (dx < -MAX_TRIGGER_RANGE || dx > MAX_TRIGGER_RANGE || dz < -MAX_TRIGGER_RANGE || dz > MAX_TRIGGER_RANGE)
		return;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 48+(GetRandomControl()&31);
	sptr->sG = sptr->sR;
	sptr->sB = 192+(GetRandomControl()&63);
	sptr->dR = 192+(GetRandomControl()&63);
	sptr->dG = 128+(GetRandomControl()&63);
	sptr->dB = 32;

	sptr->ColFadeSpeed = 12 + (GetRandomControl()&3);
	sptr->FadeToBlack = 8;
	sptr->sLife = sptr->Life = (GetRandomControl()&7)+28;
	sptr->TransType = COLADD;
	sptr->extras = 0;
	sptr->Dynamic = -1;
	sptr->x = x + ((GetRandomControl()&31)-16);
	sptr->y = y + ((GetRandomControl()&31)-16);
	sptr->z = z + ((GetRandomControl()&31)-16);

	if (!pilot)
	{
		speed <<= 8;
		speed += (GetRandomControl()&511);
	}
	else
	{
		speed <<= 7;
		speed += (GetRandomControl()&31);
	}

	zv = (rcossin_tbl[angle+1]*speed) >> 11;
	xv = (rcossin_tbl[angle]*speed) >> 11;
	sptr->Xvel = xv + ((GetRandomControl()&127)-64);
	sptr->Yvel = -(GetRandomControl()&7)-6;
	sptr->Zvel = zv + ((GetRandomControl()&127)-64);

	sptr->Friction = 4;
	sptr->Flags = SP_SCALE|SP_DEF|SP_EXPDEF;
	sptr->Gravity = -(GetRandomControl()&15)-8;
	sptr->MaxYvel = -(GetRandomControl()&7)-8;
	sptr->Def = objects[EXPLOSION1].mesh_index;
	sptr->Scalar = 3;
	size = (GetRandomControl()&31)+128;
	if (pilot)
		size >>= 2;
	sptr->Width = sptr->sWidth = size>>1;
 	sptr->Height = sptr->sHeight = size>>1;
	sptr->dWidth = size;
	sptr->dHeight = size;
}

void TriggerAlertLight(long x, long y, long z, long r, long g, long b, long angle, short room_no)
{
	long			sin,cos;
	GAME_VECTOR	src,target;

	src.x = x;
	src.y = y;
	src.z = z;

	GetFloor(x, y, z, (short *) &room_no);
	src.room_number = room_no;

	sin = ((short)rcossin_tbl[angle<<1])<<1;
	cos = ((short)rcossin_tbl[(angle<<1)+1])<<1;

	target.x = x+sin;
	target.y = y;
	target.z = z+cos;

	if (!(LOS(&src,&target)) )	// Hit anything?
		TriggerDynamic(target.x, target.y, target.z, 16, r, g, b);
}

void TriggerGunShell(short leftright, long shelltype, long weapon)
{
	FX_INFO 		*fx;
	PHD_VECTOR 	pos;
	short 	fx_number,temp;

	if (leftright == LEFT_HAND)
	{
		switch (weapon)
		{
			case LG_PISTOLS:
				pos.x = -12;
				pos.y = (PISTOLS_YOFF>>2)+16;
				pos.z = PISTOLS_ZOFF;
				break;
			case LG_MAGNUMS:
				pos.x = -16;
				pos.y = MAGNUMS_YOFF>>2;
				pos.z = MAGNUMS_ZOFF;
				break;
			case LG_UZIS:
				pos.x = -16;
				pos.y = UZIS_YOFF>>2;
				pos.z = UZIS_ZOFF;
				break;
		}

		GetLaraHandAbsPosition(&pos,LEFT_HAND);	// Get X, Y & Z coordinates.
	}
	else		// RIGHT HAND.
	{
		switch (weapon)
		{
			case LG_PISTOLS:
				pos.x = 8;
				pos.y = (PISTOLS_YOFF>>2)+16;
				pos.z = PISTOLS_ZOFF;
				break;
			case LG_MAGNUMS:
				pos.x = 16;
				pos.y = MAGNUMS_YOFF>>2;
				pos.z = MAGNUMS_ZOFF;
				break;
			case LG_UZIS:
				pos.x = 8;
				pos.y = UZIS_YOFF>>2;
				pos.z = UZIS_ZOFF;
				break;
			case LG_M16:
				pos.x = 16;
				pos.y = (M16_YOFF>>1)-112;
				pos.z = M16_ZOFF-32;
				break;
			case LG_SHOTGUN:
				pos.x = 16;
				pos.y = SHOTGUN_YOFF>>1;
				pos.z = SHOTGUN_ZOFF;
				break;
		}

		GetLaraHandAbsPosition(&pos,RIGHT_HAND);	// Get X, Y & Z coordinates.
	}

	if (weapon == LG_SHOTGUN)
		TriggerGunSmoke(pos.x, pos.y, pos.z, 0,0,0,0,weapon, 24);
	else
		TriggerGunSmoke(pos.x, pos.y, pos.z, 0,0,0,0,weapon, 16);

	fx_number = CreateEffect(lara_item->room_number);
	if (fx_number != NO_ITEM)
	{
		fx = &effects[fx_number];
		fx->pos.x_pos = pos.x;
		fx->pos.y_pos = pos.y;
		fx->pos.z_pos = pos.z;
		fx->room_number = lara_item->room_number;
		fx->pos.y_rot = 0;
		fx->pos.x_rot = 0;
		fx->pos.z_rot = GetRandomControl();
		fx->speed = 8 + (GetRandomControl() & 63);
		fx->fallspeed = - 48 - (GetRandomControl() & 7);
		fx->object_number = shelltype;
		fx->frame_number = objects[fx->object_number].mesh_index;
		fx->shade = 0x2000;
		fx->counter = (GetRandomControl()&1) + 1;	// Number of bounces (1 or 2).
		if (leftright == LEFT_HAND)
		{
			fx->flag1 = lara.left_arm.y_rot + lara_item->pos.y_rot - 0x4800 + (GetRandomControl()&0xfff);
		}
		else
		{
			if (weapon == LG_SHOTGUN)
			{
				fx->flag1 = lara.left_arm.y_rot + lara_item->pos.y_rot + lara.torso_y_rot + 0x2800 - (GetRandomControl()&0xfff);
				fx->pos.y_rot += lara.left_arm.y_rot + lara_item->pos.y_rot + lara.torso_y_rot;
				if (fx->speed < 24)
					fx->speed += 24;
			}
			else if (weapon == LG_M16)
			{
				fx->flag1 = lara.left_arm.y_rot + lara_item->pos.y_rot + lara.torso_y_rot + 0x4800 - (GetRandomControl()&0xfff);
				fx->pos.y_rot += lara.left_arm.y_rot + lara_item->pos.y_rot + lara.torso_y_rot;
			}
			else
				fx->flag1 = lara.left_arm.y_rot + lara_item->pos.y_rot + 0x4800 - (GetRandomControl()&0xfff);
		}
	}

}

void ControlGunShell(short fx_number)
{
	FX_INFO 		*fx;
	FLOOR_INFO 	*floor;
	long 	height, ceiling, ox,oy,oz;
	short 	room_number;

	fx = &effects[fx_number];

	ox = fx->pos.x_pos;
	oy = fx->pos.y_pos;
	oz = fx->pos.z_pos;

	fx->pos.y_rot += (ONE_DEGREE*fx->speed);
	fx->pos.x_rot += (ONE_DEGREE*((fx->speed>>1)+7));
	fx->pos.z_rot += (ONE_DEGREE*23);
	fx->pos.z_pos += (fx->speed * phd_cos(fx->flag1)) >> (W2V_SHIFT+1);
	fx->pos.x_pos += (fx->speed * phd_sin(fx->flag1)) >> (W2V_SHIFT+1);
	fx->fallspeed += GRAVITY;
	fx->pos.y_pos += fx->fallspeed;

	room_number = fx->room_number;
	floor = GetFloor(fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos, &room_number);

	if (room_number != fx->room_number)
		EffectNewRoom(fx_number, room_number);

	/* Remove if passed into water */
	if (room[room_number].flags & UNDERWATER)
	{
		SetupRipple(fx->pos.x_pos,room[room_number].y,fx->pos.z_pos,-8-(GetRandomControl()&3),1);
		KillEffect(fx_number);
		return;
	}

	/* Bounce off ceiling */
	ceiling = GetCeiling(floor, fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos);
	if (fx->pos.y_pos < ceiling)
	{
//  		SoundEffect(105, &fx->pos, 0);

		fx->counter--;
		fx->speed -= 4;
		if (fx->counter < 0 || fx->speed < 8)
		{
			KillEffect(fx_number);
			return;
		}

		fx->fallspeed = -fx->fallspeed;
		fx->pos.y_pos = ceiling;
	}

	/* Absorbed by floor */
	height = GetHeight(floor, fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos);
	if (fx->pos.y_pos >= height)
	{
//		SoundEffect(105, &fx->pos, 0);
		fx->speed -= 8;
		fx->counter--;
		if (fx->counter < 0 || fx->speed < 8)
		{
			KillEffect(fx_number);
			return;
		}

		if (oy > height)
		{
			fx->flag1 += -0x8000;

			/* Put shell back in its last position */
			fx->pos.x_pos = ox;
			fx->pos.z_pos = oz;
		}
		else
			fx->fallspeed = -fx->fallspeed>>1;

		fx->pos.y_pos = oy;
	}

	room_number = fx->room_number;
	floor = GetFloor(fx->pos.x_pos, fx->pos.y_pos, fx->pos.z_pos, &room_number);

	if (room_number != fx->room_number)
		EffectNewRoom(fx_number, room_number);

}

void TriggerShotgunSparks(long x, long y, long z,long xv,long yv,long zv)
{
	SPARKS	*sptr;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 255;
	sptr->sG = 255;
	sptr->sB = 0;

	sptr->dR = 255;
	sptr->dG = (GetRandomControl()&127)+64;
	sptr->dB = 0;

	sptr->ColFadeSpeed = 3;
	sptr->FadeToBlack = 5;
	sptr->sLife = sptr->Life = 10;
	sptr->TransType = COLADD;
	sptr->Dynamic = -1;

	sptr->x = x+(GetRandomControl()&7)-3;
	sptr->y = y+(GetRandomControl()&7)-3;
	sptr->z = z+(GetRandomControl()&7)-3;
	sptr->Xvel = xv+((GetRandomControl()&511)-256);
	sptr->Yvel = yv+((GetRandomControl()&511)-256);
	sptr->Zvel = zv+((GetRandomControl()&511)-256);
	sptr->Friction = 0;
	sptr->Flags = SP_SCALE;
	sptr->Scalar = 2;
	sptr->Width = sptr->sWidth = (GetRandomControl()&3)+4;
	sptr->dWidth = 1;
	sptr->Height = sptr->sHeight = (GetRandomControl()&3)+4;
	sptr->dHeight = 1;
	sptr->Gravity = sptr->MaxYvel = 0;
}

void TriggerRocketFlame(long x, long y, long z, long xv, long yv, long zv, long item_no)
{
	long		size;
	SPARKS	*sptr;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 48+(GetRandomControl()&31);
	sptr->sG = sptr->sR;
	sptr->sB = 192+(GetRandomControl()&63);

	sptr->dR = 192+(GetRandomControl()&63);
	sptr->dG = 128+(GetRandomControl()&63);
	sptr->dB = 32;

	sptr->ColFadeSpeed = 12 + (GetRandomControl()&3);
	sptr->FadeToBlack = 12;
	sptr->sLife = sptr->Life = (GetRandomControl()&3)+28;

	sptr->TransType = COLADD;

	sptr->extras = 0;
	sptr->Dynamic = -1;

	sptr->x = x+((GetRandomControl()&31)-16);
	sptr->y = y;
	sptr->z = z+((GetRandomControl()&31)-16);

	sptr->Xvel = xv;
	sptr->Yvel = yv;
	sptr->Zvel = zv;
	sptr->Friction = 3|(3<<4);

//#ifdef	PC_VERSION
	if (GetRandomControl()&1)
	{
		sptr->Flags = SP_SCALE|SP_DEF|SP_ROTATE|SP_ITEM|SP_WIND|SP_EXPDEF;
		sptr->FxObj = item_no;
		sptr->RotAng = GetRandomControl()&4095;
		if (GetRandomControl()&1)
			sptr->RotAdd = -(GetRandomControl()&15)-16;
		else
			sptr->RotAdd = (GetRandomControl()&15)+16;
	}
	else
	{
		sptr->Flags = SP_SCALE|SP_DEF|SP_ITEM|SP_WIND|SP_EXPDEF;
		sptr->FxObj = item_no;
	}
//#endif

	sptr->Gravity = 0;
	sptr->MaxYvel = 0;

	sptr->Def = objects[EXPLOSION1].mesh_index;
	sptr->Scalar = 2;
	size = (GetRandomControl()&7)+32;
	sptr->Width = sptr->sWidth = size;
	sptr->dWidth = 2;
 	sptr->Height = sptr->sHeight = size;
	sptr->dHeight = 2;
}

void TriggerRocketSmoke(long x, long y, long z, long body_part)
{
	long		size;
	SPARKS	*sptr;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 0;
	sptr->sG = 0;
	sptr->sB = 0;

	sptr->dR = 64;
	sptr->dG = 64;
	sptr->dB = 64;

	sptr->ColFadeSpeed = 4 + (GetRandomControl()&3);
	sptr->FadeToBlack = 12;
	sptr->sLife = sptr->Life = (GetRandomControl()&3)+20;

	sptr->TransType = COLADD;

	sptr->extras = 0;
	sptr->Dynamic = -1;

	sptr->x = x + ((GetRandomControl()&15)-8);
	sptr->y = y + ((GetRandomControl()&15)-8);
	sptr->z = z + ((GetRandomControl()&15)-8);
	sptr->Xvel = ((GetRandomControl()&255)-128);
	sptr->Yvel = -(GetRandomControl()&3)-4;
	sptr->Zvel = ((GetRandomControl()&255)-128);
	sptr->Friction = 4;

//#ifdef	PC_VERSION
	if (GetRandomControl()&1)
	{
		sptr->Flags = SP_SCALE|SP_DEF|SP_ROTATE|SP_EXPDEF;
		sptr->RotAng = GetRandomControl()&4095;
		if (GetRandomControl()&1)
			sptr->RotAdd = -(GetRandomControl()&15)-16;
		else
			sptr->RotAdd = (GetRandomControl()&15)+16;
	}
	else
		sptr->Flags = SP_SCALE|SP_DEF|SP_EXPDEF;
//#endif

	sptr->Def = objects[EXPLOSION1].mesh_index;
	sptr->Scalar = 3;
	sptr->Gravity = -(GetRandomControl()&3)-4;
	sptr->MaxYvel = -(GetRandomControl()&3)-4;
	size = (GetRandomControl()&7)+32;
	sptr->Width = sptr->sWidth = size>>2;
	sptr->dWidth = size;
 	sptr->Height = sptr->sHeight = size>>2;
	sptr->dHeight = size;
}

void TriggerBlood(long x, long y, long z,long angle, long num)
{
	long		lp1;
	long		tangle,tspeed;
	SPARKS	*sptr;

	for (lp1=0;lp1<num;lp1++)
	{
		sptr = &spark[GetFreeSpark()];

		sptr->On = 1;
		sptr->sR = 224;
		sptr->sG = 0;
		sptr->sB = 32;

		sptr->dR = 192;
		sptr->dG = 0;
		sptr->dB = 24;

		sptr->ColFadeSpeed = 8;
		sptr->FadeToBlack = 8;
		sptr->sLife = sptr->Life = 24;
		sptr->TransType = SEMITRANS;
		sptr->Dynamic = -1;

		sptr->x = x+((GetRandomControl()&31)-16);
		sptr->y = y+((GetRandomControl()&31)-16);
		sptr->z = z+((GetRandomControl()&31)-16);
		tangle = (angle + ((GetRandomControl()&31)-16)) & 4095;
		tspeed = rand()&15;
		sptr->Zvel = (rcossin_tbl[(tangle<<1)+1] * tspeed) >> 5;
		sptr->Xvel = (-rcossin_tbl[(tangle<<1)] * tspeed) >> 5;
		sptr->Yvel = -((GetRandomControl()&255)+128);
		sptr->Friction = 4;
		sptr->Flags = 0;
		sptr->Scalar = 3;
		sptr->Gravity = ((GetRandomControl()&31)+31);
		sptr->Width = sptr->sWidth = 2;
		sptr->dWidth = 2-(GetRandomControl()&1);
		sptr->Height = sptr->sHeight = 2;
		sptr->dHeight = 2-(GetRandomControl()&1);
		sptr->MaxYvel = 0;
		sptr++;
	}

}

void TriggerBloodD(long x, long y, long z,long angle, long num)
{
	long		lp1;
	long		tangle,tspeed;
	SPARKS	*sptr;

	for (lp1=0;lp1<num;lp1++)
	{
		sptr = &spark[GetFreeSpark()];

		sptr->On = 1;
		sptr->sR = 224;
		sptr->sG = 0;
		sptr->sB = 32;

		sptr->dR = 192;
		sptr->dG = 0;
		sptr->dB = 24;

		sptr->ColFadeSpeed = 8;
		sptr->FadeToBlack = 8;
		sptr->sLife = sptr->Life = 24;
		sptr->TransType = SEMITRANS;
		sptr->Dynamic = -1;

		sptr->x = x+((GetRandomDraw()&31)-16);
		sptr->y = y+((GetRandomDraw()&31)-16);
		sptr->z = z+((GetRandomDraw()&31)-16);
		tangle = (angle + ((GetRandomDraw()&31)-16)) & 4095;
		tspeed = rand()&15;
		sptr->Zvel = (rcossin_tbl[(tangle<<1)+1] * tspeed) >> 5;
		sptr->Xvel = (-rcossin_tbl[(tangle<<1)] * tspeed) >> 5;
		sptr->Yvel = -((GetRandomDraw()&255)+128);
		sptr->Friction = 4;
		sptr->Flags = 0;
		sptr->Scalar = 3;
		sptr->Gravity = ((GetRandomDraw()&31)+31);
		sptr->Width = sptr->sWidth = 2;
		sptr->dWidth = 2-(GetRandomDraw()&1);
		sptr->Height = sptr->sHeight = 2;
		sptr->dHeight = 2-(GetRandomDraw()&1);
		sptr->MaxYvel = 0;
		sptr++;
	}

}

void SetupSplash(SPLASH_SETUP	*spl)
{
	SPLASH_STRUCT	*sptr;
	SPLASH_VERTS	*svptr;
	long		lp,vlp;

	sptr = &splashes[0];

	for (lp=0;lp<MAX_SPLASHES;lp++)
	{
		if (!(sptr->flags & SPL_ON))
		{
			sptr->flags = SPL_ON|SPL_TRANS;	// Turn splash on.
			sptr->x = spl->x;
			sptr->y = spl->y;
			sptr->z = spl->z;
			sptr->life = 63;

			svptr = &sptr->sv[0];
//
//	Inner ring Bottom.
//
			for (vlp=0;vlp<8;vlp++)
			{
				svptr->wx = (spl->InnerXZoff * SplashRings[vlp][0])<<1;
				svptr->wz = (spl->InnerXZoff * SplashRings[vlp][1])<<1;
				svptr->wy = 0;
				svptr->xv = (spl->InnerXZvel * SplashRings[vlp][0])/12;
				svptr->zv = (spl->InnerXZvel * SplashRings[vlp][1])/12;
				svptr->yv = 0;
				svptr->oxv = svptr->xv>>3;
				svptr->ozv = svptr->zv>>3;
				svptr->friction = spl->InnerFriction-2;
				svptr->gravity = 0;
				svptr++;
			}
//
//	Inner ring Top.
//
			for (vlp=0;vlp<8;vlp++)
			{
				svptr->wx = ((spl->InnerXZoff+spl->InnerXZsize) * SplashRings[vlp][0])<<1;
				svptr->wz = ((spl->InnerXZoff+spl->InnerXZsize) * SplashRings[vlp][1])<<1;
				svptr->wy = spl->InnerYsize;
				svptr->xv = (spl->InnerXZvel * SplashRings[vlp][0])>>3;
				svptr->zv = (spl->InnerXZvel * SplashRings[vlp][1])>>3;
				svptr->yv = spl->InnerYvel;
				svptr->oxv = svptr->xv>>3;
				svptr->ozv = svptr->zv>>3;
				svptr->friction = spl->InnerFriction;
				svptr->gravity = spl->InnerGravity;
				svptr++;
			}

//
//	Middle ring Bottom.
//
			for (vlp=0;vlp<8;vlp++)
			{
				svptr->wx = (spl->MiddleXZoff * SplashRings[vlp][0])<<1;
				svptr->wz = (spl->MiddleXZoff * SplashRings[vlp][1])<<1;
				svptr->wy = 0;
				svptr->xv = (spl->MiddleXZvel * SplashRings[vlp][0])/12;
				svptr->zv = (spl->MiddleXZvel * SplashRings[vlp][1])/12;
				svptr->yv = 0;
				svptr->oxv = svptr->xv>>3;
				svptr->ozv = svptr->zv>>3;
				svptr->friction = spl->MiddleFriction-2;
				svptr->gravity = 0;
				svptr++;
			}

//
//	Middle ring Top.
//
			for (vlp=0;vlp<8;vlp++)
			{
				svptr->wx = ((spl->MiddleXZoff+spl->MiddleXZsize) * SplashRings[vlp][0])<<1;
				svptr->wz = ((spl->MiddleXZoff+spl->MiddleXZsize) * SplashRings[vlp][1])<<1;
				svptr->wy = spl->MiddleYsize;
				svptr->xv = (spl->MiddleXZvel * SplashRings[vlp][0])>>3;
				svptr->zv = (spl->MiddleXZvel * SplashRings[vlp][1])>>3;
				svptr->yv = spl->MiddleYvel;
				svptr->oxv = svptr->xv>>3;
				svptr->ozv = svptr->zv>>3;
				svptr->friction = spl->MiddleFriction;
				svptr->gravity = spl->MiddleGravity;
				svptr++;
			}

//
//	Outer ring Bottom.
//
			for (vlp=0;vlp<8;vlp++)
			{
				svptr->wx = (spl->OuterXZoff * SplashRings[vlp][0])<<1;
				svptr->wz = (spl->OuterXZoff * SplashRings[vlp][1])<<1;
				svptr->wy = 0;
				svptr->xv = (spl->OuterXZvel * SplashRings[vlp][0])/12;
				svptr->zv = (spl->OuterXZvel * SplashRings[vlp][1])/12;
				svptr->yv = 0;
				svptr->oxv = svptr->xv>>3;
				svptr->ozv = svptr->zv>>3;
				svptr->friction = spl->OuterFriction-2;
				svptr->gravity = 0;
				svptr++;
			}

//
//	Outer ring top.
//
			for (vlp=0;vlp<8;vlp++)
			{
				svptr->wx = ((spl->OuterXZoff+spl->OuterXZsize) * SplashRings[vlp][0])<<1;
				svptr->wz = ((spl->OuterXZoff+spl->OuterXZsize) * SplashRings[vlp][1])<<1;
				svptr->wy = 0;
				svptr->xv = (spl->OuterXZvel * SplashRings[vlp][0])>>3;
				svptr->zv = (spl->OuterXZvel * SplashRings[vlp][1])>>3;
				svptr->yv = 0;
				svptr->oxv = svptr->xv>>3;
				svptr->ozv = svptr->zv>>3;
				svptr->friction = spl->OuterFriction;
				svptr->gravity = 0;
				svptr++;
			}

			break;
		}
		sptr++;
	}
}

void UpdateSplashes()
{
	RIPPLE_STRUCT	*rptr;
	SPLASH_STRUCT	*sptr;
	SPLASH_VERTS	*svptr;
	long		lp,vlp,oyv,declife;
	long		veladd;

	sptr = &splashes[0];

	for (lp=0;lp<MAX_SPLASHES;lp++)
	{
		if (sptr->flags & SPL_ON)
		{
			svptr = &sptr->sv[0];
			declife = 0;

			for (vlp=0;vlp<48;vlp++)
			{
				svptr->wx += svptr->xv>>2;
				svptr->wy += svptr->yv>>6;
				svptr->wz += svptr->zv>>2;

				svptr->xv -= (svptr->xv>>svptr->friction);
				svptr->zv -= (svptr->zv>>svptr->friction);

				if (svptr->oxv < 0 && svptr->xv > svptr->oxv)
					svptr->xv = svptr->oxv;
				else if (svptr->oxv > 0 && svptr->xv < svptr->oxv)
					svptr->xv = svptr->oxv;
				else if (svptr->ozv < 0 && svptr->zv > svptr->ozv)
					svptr->zv = svptr->ozv;
				else if (svptr->ozv > 0 && svptr->zv < svptr->ozv)
					svptr->zv = svptr->ozv;
				oyv = svptr->yv;
				svptr->yv += svptr->gravity<<2;
				if (svptr->yv > 0x7000)
					svptr->yv = 0x7000;
				if (svptr->wy > 0)
				{
					if (vlp<16)
						sptr->flags |= SPL_RIPPLEINNER;
					else if (vlp<32)
						sptr->flags |= SPL_RIPPLEMIDDLE;
					svptr->wy = 0;
					declife = 1;
				}
				svptr++;
			}

			if (declife)
			{
				sptr->life--;
				if (sptr->life == 0)
					sptr->flags = 0;
			}
		}
		sptr++;
	}

	rptr = &ripples[0];
	for (lp=0;lp<MAX_RIPPLES;lp++)
	{
		if (rptr->flags & SPL_ON)
		{
			if (rptr->size < 254)
				rptr->size+=2;

			if (!rptr->init)
			{
				rptr->life-=2;
				if (rptr->life>250)
					rptr->flags = 0;	// Turn ripple off if ran out of life.
			}
			else	if (rptr->init < rptr->life)
			{
				rptr->init+=4;
				if (rptr->init >= rptr->life)
					rptr->init = 0;
			}
		}
		rptr++;
	}
}

void SetupRipple(long x, long y, long z, long size, long moretrans)
{
	RIPPLE_STRUCT	*rptr;
	long			lp;

	rptr = &ripples[0];

	for (lp=0;lp<MAX_RIPPLES;lp++)
	{
		if (!(rptr->flags & SPL_ON))
		{
			if (size < 0)
			{
				if (moretrans)
					rptr->flags = SPL_ON|SPL_TRANS|SPL_MORETRANS;
				else
					rptr->flags = SPL_ON|SPL_TRANS;
				size = -size;
			}
			else
				rptr->flags = SPL_ON;

			rptr->life = 48+(GetRandomControl()&15);
			rptr->init = 1;
			rptr->size = size;
			rptr->x = x + (GetRandomControl()&127) - 64;
			rptr->y = y;
			rptr->z = z + (GetRandomControl()&127) - 64;
			break;
		}
		rptr++;
	}
}


void TriggerUnderwaterBlood(long x, long y, long z, long size)
{
	RIPPLE_STRUCT	*rptr;
	long			lp;

	rptr = &ripples[0];

	for (lp=0;lp<MAX_RIPPLES;lp++)
	{
		if (!(rptr->flags & SPL_ON))
		{
			rptr->flags = SPL_ON|SPL_TRANS|SPL_MORETRANS|SPL_BLOOD;

			rptr->life = 240+(GetRandomControl()&7);
			rptr->init = 1;
			rptr->size = size;
			rptr->x = x + (GetRandomControl()&63) - 32;
			rptr->y = y;
			rptr->z = z + (GetRandomControl()&63) - 32;
			break;
		}
		rptr++;
	}
}

void TriggerUnderwaterBloodD(long x, long y, long z, long size)
{
	RIPPLE_STRUCT	*rptr;
	long			lp;

	rptr = &ripples[0];

	for (lp=0;lp<MAX_RIPPLES;lp++)
	{
		if (!(rptr->flags & SPL_ON))
		{
			rptr->flags = SPL_ON|SPL_TRANS|SPL_MORETRANS|SPL_BLOOD;

			rptr->life = 240+(GetRandomDraw()&7);
			rptr->init = 1;
			rptr->size = size;
			rptr->x = x + (GetRandomDraw()&63) - 32;
			rptr->y = y;
			rptr->z = z + (GetRandomDraw()&63) - 32;
			break;
		}
		rptr++;
	}
}

void TriggerWaterfallMist(long x, long y, long z, long angle)
{
	long		xsize, zsize, tangle, dist, lp;
	long		dist_tab[4] = {	512,171,-171,-512	};
	SPARKS	*sptr;

	for (lp=0;lp<4;lp++)
	{
		sptr = &spark[GetFreeSpark()];

		sptr->On = 1;
		sptr->sR = 128;
		sptr->sG = 128;
		sptr->sB = 128;

		sptr->dR = 192;
		sptr->dG = 192;
		sptr->dB = 192;

		sptr->ColFadeSpeed = 2;
		sptr->FadeToBlack = 4;	// 8
		sptr->sLife = sptr->Life = 6+(GetRandomControl()&3);

		sptr->TransType = COLADD;

		sptr->extras = 0;
		sptr->Dynamic = -1;

		dist = dist_tab[lp]+(GetRandomControl()&31)-16;
		tangle = (angle+1024)&4095;
		xsize = (rcossin_tbl[(tangle<<1)] * dist) >> 12;
		zsize = (rcossin_tbl[(tangle<<1)+1] * dist) >> 12;
		sptr->x = x + xsize + ((GetRandomControl()&15)-8);
		sptr->y = y + ((GetRandomControl()&15)-8);
		sptr->z = z + zsize + ((GetRandomControl()&15)-8);
		sptr->Xvel = (rcossin_tbl[(angle<<1)]) >> 12;
		sptr->Zvel = (rcossin_tbl[(angle<<1)+1]) >> 12;
		sptr->Yvel = 0;
		sptr->Friction = 3;

		sptr->Flags = SP_SCALE|SP_DEF|SP_EXPDEF;

		sptr->Def = objects[EXPLOSION1].mesh_index;
		sptr->Scalar = 6;
		sptr->Gravity = 0;
		sptr->MaxYvel = 0;
		xsize = (GetRandomControl()&7)+12;
		sptr->Width = sptr->sWidth = xsize>>1;
		sptr->dWidth = xsize;
 		sptr->Height = sptr->sHeight = xsize>>1;
		sptr->dHeight = xsize;
	}
}

void UpdateBats()
{
	long sfx=0;
	long			lp;
	BAT_STRUCT	*bptr;

	bptr = &bats[0];

	for (lp=0;lp<MAX_BATS;lp++)
	{
		if (bptr->flags & B_ON)
		{
			bptr->x -= (((rcossin_tbl[(bptr->angle<<1)+1])*(bptr->speed))>>14);
			bptr->y -= GetRandomControl()&3;
			bptr->z += (((rcossin_tbl[(bptr->angle<<1)])*(bptr->speed))>>14);
			bptr->WingYoff+=11;
			bptr->WingYoff &= 63;
			if (bptr->life < 128)	// After flown straight for a while, change direction erratically.
			{
				bptr->y -= (lp>>1)+4;
				if ((GetRandomControl()&3) == 0)
				{
					bptr->angle += (GetRandomControl()&255)-128;
					bptr->angle &= 4095;
					bptr->speed += (GetRandomControl()&3);
				}
			}

			bptr->speed+=12;
			if (bptr->speed > 300)
				bptr->speed=300;

			if (bptr->life)
			{
				bptr->life--;
				if (!bptr->life)
					bptr->flags = 0;
			}

#if 0
			if (!sfx)
			{
				PHD_3DPOS pos;

				pos.x_pos = bptr->x;
				pos.y_pos = bptr->y;
				pos.z_pos = bptr->z;
				pos.x_rot = 0;
				pos.y_rot = bptr->angle;
				pos.z_rot = 0;

//				if (bptr->WingYoff < 11)
					SoundEffect(335, &pos, 0);

				sfx = 1;
			}
#endif
		}
		bptr++;
	}
}

void BatEmitterControl(short item_number)
{
	ITEM_INFO	*item;

	item = &items[item_number];

	if (item->active)
	{
		TriggerBats(item->pos.x_pos,item->pos.y_pos,item->pos.z_pos,item->pos.y_rot>>4);
		KillItem(item_number);
		BatsTriggered = 1;
	}
}

void TriggerBats(long x, long y, long z, long angle)
{
	long			lp;
	BAT_STRUCT	*bptr;

	angle -= 0x400;
	angle &= 4095;

	bptr = &bats[0];
	for (lp=0;lp<MAX_BATS;lp++)
	{
		bptr->x = x+(GetRandomControl()&511)-256;
		bptr->y = y+256-(GetRandomControl()&255);
		bptr->z = z+(GetRandomControl()&511)-256;
		bptr->angle = (angle + (GetRandomControl()&127) - 64) & 4095;
		bptr->speed = (GetRandomControl()&31)+64;
		bptr->WingYoff = GetRandomControl()&63;
		bptr->flags |= B_ON;
		bptr->life = 144 + (GetRandomControl()&7);
		bptr++;
	}
}

void TriggerStaticFlame(long x, long y, long z, long size)
{
	SPARKS	*sptr;
	long		dx,dz;

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

	if (dx < -MAX_TRIGGER_RANGE || dx > MAX_TRIGGER_RANGE || dz < -MAX_TRIGGER_RANGE || dz > MAX_TRIGGER_RANGE)
		return;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = sptr->dR = 192+(GetRandomControl()&63);
	sptr->sG = sptr->dG = 128+(GetRandomControl()&63);
	sptr->sB = sptr->dB = 64;

	sptr->ColFadeSpeed = 2;
	sptr->FadeToBlack = 0;
	sptr->sLife = sptr->Life = 2;
	sptr->TransType = COLADD;
	sptr->extras = 0;
	sptr->Dynamic = -1;
	sptr->x = x + ((GetRandomControl()&7)-4);
	sptr->y = y;
	sptr->z = z + ((GetRandomControl()&7)-4);
	sptr->Xvel = sptr->Yvel = sptr->Zvel = sptr->Friction = sptr->Gravity = sptr->MaxYvel = 0;
	sptr->Flags = SP_SCALE|SP_DEF;
	sptr->Def = objects[EXPLOSION1].mesh_index;
	sptr->Scalar = 2;
	sptr->Width = sptr->sWidth = size;
	sptr->dWidth = size;
 	sptr->Height = sptr->sHeight = size;
	sptr->dHeight = size;
}


void TriggerDartSmoke(long x, long y, long z, long xv, long zv, long hit)
{
	long		size;
	SPARKS	*sptr;
	long		dx,dz;

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

	if (dx < -MAX_TRIGGER_RANGE || dx > MAX_TRIGGER_RANGE || dz < -MAX_TRIGGER_RANGE || dz > MAX_TRIGGER_RANGE)
		return;

	sptr = &spark[GetFreeSpark()];

	sptr->On = 1;
	sptr->sR = 16;
	sptr->sG = 8;
	sptr->sB = 4;

	sptr->dR = 64;
	sptr->dG = 48;
	sptr->dB = 32;

	sptr->ColFadeSpeed = 4;
	sptr->FadeToBlack = 4;
	sptr->sLife = sptr->Life = (GetRandomControl()&3)+16;

	sptr->TransType = COLADD;

	sptr->extras = 0;
	sptr->Dynamic = -1;

	sptr->x = x + ((GetRandomControl()&31)-16);
	sptr->y = y + ((GetRandomControl()&31)-16);
	sptr->z = z + ((GetRandomControl()&31)-16);
	sptr->Xvel = -xv+((GetRandomControl()&255)-128);
	sptr->Yvel = -(GetRandomControl()&3)-4;
	sptr->Zvel = -zv+((GetRandomControl()&255)-128);
	sptr->Friction = 3;

//#ifdef	PC_VERSION
	if (GetRandomControl()&1)
	{
		sptr->Flags = SP_SCALE|SP_DEF|SP_ROTATE|SP_EXPDEF;
		sptr->RotAng = GetRandomControl()&4095;
		if (GetRandomControl()&1)
			sptr->RotAdd = -(GetRandomControl()&15)-16;
		else
			sptr->RotAdd = (GetRandomControl()&15)+16;
	}
	else
		sptr->Flags = SP_SCALE|SP_DEF|SP_EXPDEF;
//#endif

	sptr->Def = objects[EXPLOSION1].mesh_index;
	sptr->Scalar = 3;
	sptr->Gravity = -(GetRandomControl()&3)-4;
	sptr->MaxYvel = -(GetRandomControl()&3)-4;
	size = (GetRandomControl()&15)+24;
	if (hit)
		size>>=2;
	sptr->Width = sptr->sWidth = size>>2;
	sptr->dWidth = size;
 	sptr->Height = sptr->sHeight = size>>2;
	sptr->dHeight = size;
}

void KillAllCurrentItems(short item_number)
{
	KillEverythingFlag = 1;
}

void KillEverything()
{
	sint16 		item_num,nex;

// Kill all items.

	item_num = next_item_active;
	while ( item_num!=NO_ITEM )
	{
		nex = items[item_num].next_active;
		if (items[item_num].object_number != LARA && items[item_num].object_number != FLARE && items[item_num].active)
			KillItem(item_num);
		item_num = nex;
	}

// Kill all effects.

	item_num = next_fx_active;
	while ( item_num!=NO_ITEM )
	{
		nex = effects[item_num].next_active;
		if ( objects[ effects[item_num].object_number ].control && !(effects[item_num].object_number == FLAME && effects[item_num].counter < 0))
			KillEffect(item_num);
		item_num = nex;
	}

// Kill all fish.

	for (item_num=0;item_num<MAX_FISH;item_num++)
		lead_info[item_num].on = 0;

	KillEverythingFlag = 0;
}
