Source/ThunderBeast/QuakeToon/game/g_weapon.c
static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int te_impact, int hspread, int vspread, int mod)
{
	trace_t		tr;
	vec3_t		dir;
	vec3_t		forward, right, up;
	vec3_t		end;
	float		r;
	float		u;
	vec3_t		water_start;
	qboolean	water = false;
	int			content_mask = MASK_SHOT | MASK_WATER;

	tr = gi.trace (self->s.origin, NULL, NULL, start, self, MASK_SHOT);
	if (!(tr.fraction < 1.0))
	{
		vectoangles (aimdir, dir);
		AngleVectors (dir, forward, right, up);

		r = crandom()*hspread;
		u = crandom()*vspread;
		VectorMA (start, 8192, forward, end);
		VectorMA (end, r, right, end);
		VectorMA (end, u, up, end);

		if (gi.pointcontents (start) & MASK_WATER)
		{
			water = true;
			VectorCopy (start, water_start);
			content_mask &= ~MASK_WATER;
		}

		tr = gi.trace (start, NULL, NULL, end, self, content_mask);

		// see if we hit water
		if (tr.contents & MASK_WATER)
		{
			int		color;

			water = true;
			VectorCopy (tr.endpos, water_start);

			if (!VectorCompare (start, tr.endpos))
			{
				if (tr.contents & CONTENTS_WATER)
				{
					if (strcmp(tr.surface->name, "*brwater") == 0)
						color = SPLASH_BROWN_WATER;
					else
						color = SPLASH_BLUE_WATER;
				}
				else if (tr.contents & CONTENTS_SLIME)
					color = SPLASH_SLIME;
				else if (tr.contents & CONTENTS_LAVA)
					color = SPLASH_LAVA;
				else
					color = SPLASH_UNKNOWN;

				if (color != SPLASH_UNKNOWN)
				{
					gi.WriteByte (svc_temp_entity);
					gi.WriteByte (TE_SPLASH);
					gi.WriteByte (8);
					gi.WritePosition (tr.endpos);
					gi.WriteDir (tr.plane.normal);
					gi.WriteByte (color);
					gi.multicast (tr.endpos, MULTICAST_PVS);
				}

				// change bullet's course when it enters water
				VectorSubtract (end, start, dir);
				vectoangles (dir, dir);
				AngleVectors (dir, forward, right, up);
				r = crandom()*hspread*2;
				u = crandom()*vspread*2;
				VectorMA (water_start, 8192, forward, end);
				VectorMA (end, r, right, end);
				VectorMA (end, u, up, end);
			}

			// re-trace ignoring water this time
			tr = gi.trace (water_start, NULL, NULL, end, self, MASK_SHOT);
		}
	}

	// send gun puff / flash
	if (!((tr.surface) && (tr.surface->flags & SURF_SKY)))
	{
		if (tr.fraction < 1.0)
		{
			if (tr.ent->takedamage)
			{
				T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_BULLET, mod);
			}
			else
			{
				if (strncmp (tr.surface->name, "sky", 3) != 0)
				{
					gi.WriteByte (svc_temp_entity);
					gi.WriteByte (te_impact);
					gi.WritePosition (tr.endpos);
					gi.WriteDir (tr.plane.normal);
					gi.multicast (tr.endpos, MULTICAST_PVS);

					if (self->client)
						PlayerNoise(self, tr.endpos, PNOISE_IMPACT);
				}
			}
		}
	}

	// if went through water, determine where the end and make a bubble trail
	if (water)
	{
		vec3_t	pos;

		VectorSubtract (tr.endpos, water_start, dir);
		VectorNormalize (dir);
		VectorMA (tr.endpos, -2, dir, pos);
		if (gi.pointcontents (pos) & MASK_WATER)
			VectorCopy (pos, tr.endpos);
		else
			tr = gi.trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER);

		VectorAdd (water_start, tr.endpos, pos);
		VectorScale (pos, 0.5, pos);

		gi.WriteByte (svc_temp_entity);
		gi.WriteByte (TE_BUBBLETRAIL);
		gi.WritePosition (water_start);
		gi.WritePosition (tr.endpos);
		gi.multicast (pos, MULTICAST_PVS);
	}
}
/*
=================
fire_lead

This is an internal support routine used for bullet/pellet based weapons.
=================
*/
fire_lead
This is an internal support routine used for bullet/pellet based weapons.
fire_lead This is an internal support routine used for bullet / pellet based weapons .
static void fire_lead (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int te_impact, int hspread, int vspread, int mod)
{
	trace_t		tr;
	vec3_t		dir;
	vec3_t		forward, right, up;
	vec3_t		end;
	float		r;
	float		u;
	vec3_t		water_start;
	qboolean	water = false;
	int			content_mask = MASK_SHOT | MASK_WATER;
	tr = gi.trace (self->s.origin, NULL, NULL, start, self, MASK_SHOT);
	if (!(tr.fraction < 1.0))
	{
		vectoangles (aimdir, dir);
		AngleVectors (dir, forward, right, up);
		r = crandom()*hspread;
		u = crandom()*vspread;
		VectorMA (start, 8192, forward, end);
		VectorMA (end, r, right, end);
		VectorMA (end, u, up, end);
		if (gi.pointcontents (start) & MASK_WATER)
		{
			water = true;
			VectorCopy (start, water_start);
			content_mask &= ~MASK_WATER;
		}
		tr = gi.trace (start, NULL, NULL, end, self, content_mask);
		if (tr.contents & MASK_WATER)
		{
			int		color;
			water = true;
			VectorCopy (tr.endpos, water_start);
			if (!VectorCompare (start, tr.endpos))
			{
				if (tr.contents & CONTENTS_WATER)
				{
					if (strcmp(tr.surface->name, "*brwater") == 0)
						color = SPLASH_BROWN_WATER;
					else
						color = SPLASH_BLUE_WATER;
				}
				else if (tr.contents & CONTENTS_SLIME)
					color = SPLASH_SLIME;
				else if (tr.contents & CONTENTS_LAVA)
					color = SPLASH_LAVA;
				else
					color = SPLASH_UNKNOWN;
				if (color != SPLASH_UNKNOWN)
				{
					gi.WriteByte (svc_temp_entity);
					gi.WriteByte (TE_SPLASH);
					gi.WriteByte (8);
					gi.WritePosition (tr.endpos);
					gi.WriteDir (tr.plane.normal);
					gi.WriteByte (color);
					gi.multicast (tr.endpos, MULTICAST_PVS);
				}
				VectorSubtract (end, start, dir);
				vectoangles (dir, dir);
				AngleVectors (dir, forward, right, up);
				r = crandom()*hspread*2;
				u = crandom()*vspread*2;
				VectorMA (water_start, 8192, forward, end);
				VectorMA (end, r, right, end);
				VectorMA (end, u, up, end);
			}
			tr = gi.trace (water_start, NULL, NULL, end, self, MASK_SHOT);
		}
	}
	if (!((tr.surface) && (tr.surface->flags & SURF_SKY)))
	{
		if (tr.fraction < 1.0)
		{
			if (tr.ent->takedamage)
			{
				T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_BULLET, mod);
			}
			else
			{
				if (strncmp (tr.surface->name, "sky", 3) != 0)
				{
					gi.WriteByte (svc_temp_entity);
					gi.WriteByte (te_impact);
					gi.WritePosition (tr.endpos);
					gi.WriteDir (tr.plane.normal);
					gi.multicast (tr.endpos, MULTICAST_PVS);
					if (self->client)
						PlayerNoise(self, tr.endpos, PNOISE_IMPACT);
				}
			}
		}
	}
	if (water)
	{
		vec3_t	pos;
		VectorSubtract (tr.endpos, water_start, dir);
		VectorNormalize (dir);
		VectorMA (tr.endpos, -2, dir, pos);
		if (gi.pointcontents (pos) & MASK_WATER)
			VectorCopy (pos, tr.endpos);
		else
			tr = gi.trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER);
		VectorAdd (water_start, tr.endpos, pos);
		VectorScale (pos, 0.5, pos);
		gi.WriteByte (svc_temp_entity);
		gi.WriteByte (TE_BUBBLETRAIL);
		gi.WritePosition (water_start);
		gi.WritePosition (tr.endpos);
		gi.multicast (pos, MULTICAST_PVS);
	}
}
static void fire_lead ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int kick , int te_impact , int hspread , int vspread , int mod ) { trace_t tr ; vec3_t dir ; vec3_t forward , right , up ; vec3_t end ; float r ; float u ; vec3_t water_start ; qboolean water = false ; int content_mask = MASK_SHOT | MASK_WATER ; tr = gi . trace ( self -> s . origin , NULL , NULL , start , self , MASK_SHOT ) ; if ( ! ( tr . fraction < 1.0 ) ) { vectoangles ( aimdir , dir ) ; AngleVectors ( dir , forward , right , up ) ; r = crandom ( ) * hspread ; u = crandom ( ) * vspread ; VectorMA ( start , 8192 , forward , end ) ; VectorMA ( end , r , right , end ) ; VectorMA ( end , u , up , end ) ; if ( gi . pointcontents ( start ) & MASK_WATER ) { water = true ; VectorCopy ( start , water_start ) ; content_mask &= ~ MASK_WATER ; } tr = gi . trace ( start , NULL , NULL , end , self , content_mask ) ; if ( tr . contents & MASK_WATER ) { int color ; water = true ; VectorCopy ( tr . endpos , water_start ) ; if ( ! VectorCompare ( start , tr . endpos ) ) { if ( tr . contents & CONTENTS_WATER ) { if ( strcmp ( tr . surface -> name , " " ) == 0 ) color = SPLASH_BROWN_WATER ; else color = SPLASH_BLUE_WATER ; } else if ( tr . contents & CONTENTS_SLIME ) color = SPLASH_SLIME ; else if ( tr . contents & CONTENTS_LAVA ) color = SPLASH_LAVA ; else color = SPLASH_UNKNOWN ; if ( color != SPLASH_UNKNOWN ) { gi . WriteByte ( svc_temp_entity ) ; gi . WriteByte ( TE_SPLASH ) ; gi . WriteByte ( 8 ) ; gi . WritePosition ( tr . endpos ) ; gi . WriteDir ( tr . plane . normal ) ; gi . WriteByte ( color ) ; gi . multicast ( tr . endpos , MULTICAST_PVS ) ; } VectorSubtract ( end , start , dir ) ; vectoangles ( dir , dir ) ; AngleVectors ( dir , forward , right , up ) ; r = crandom ( ) * hspread * 2 ; u = crandom ( ) * vspread * 2 ; VectorMA ( water_start , 8192 , forward , end ) ; VectorMA ( end , r , right , end ) ; VectorMA ( end , u , up , end ) ; } tr = gi . trace ( water_start , NULL , NULL , end , self , MASK_SHOT ) ; } } if ( ! ( ( tr . surface ) && ( tr . surface -> flags & SURF_SKY ) ) ) { if ( tr . fraction < 1.0 ) { if ( tr . ent -> takedamage ) { T_Damage ( tr . ent , self , self , aimdir , tr . endpos , tr . plane . normal , damage , kick , DAMAGE_BULLET , mod ) ; } else { if ( strncmp ( tr . surface -> name , " " , 3 ) != 0 ) { gi . WriteByte ( svc_temp_entity ) ; gi . WriteByte ( te_impact ) ; gi . WritePosition ( tr . endpos ) ; gi . WriteDir ( tr . plane . normal ) ; gi . multicast ( tr . endpos , MULTICAST_PVS ) ; if ( self -> client ) PlayerNoise ( self , tr . endpos , PNOISE_IMPACT ) ; } } } } if ( water ) { vec3_t pos ; VectorSubtract ( tr . endpos , water_start , dir ) ; VectorNormalize ( dir ) ; VectorMA ( tr . endpos , -2 , dir , pos ) ; if ( gi . pointcontents ( pos ) & MASK_WATER ) VectorCopy ( pos , tr . endpos ) ; else tr = gi . trace ( pos , NULL , NULL , water_start , tr . ent , MASK_WATER ) ; VectorAdd ( water_start , tr . endpos , pos ) ; VectorScale ( pos , 0.5 , pos ) ; gi . WriteByte ( svc_temp_entity ) ; gi . WriteByte ( TE_BUBBLETRAIL ) ; gi . WritePosition ( water_start ) ; gi . WritePosition ( tr . endpos ) ; gi . multicast ( pos , MULTICAST_PVS ) ; } }
fire_lead
This is an internal support routine used for bullet/pellet based weapons.
fire_lead This is an internal support routine used for bullet / pellet based weapons .
// see if we hit water // change bullet's course when it enters water // re-trace ignoring water this time // send gun puff / flash // if went through water, determine where the end and make a bubble trail