コード例 #1
0
ファイル: g_weapon.c プロジェクト: wtfbbqhax/thz
// this should match CG_ShotgunPattern
void ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, gentity_t *ent )
{
  int        i;
  float      r, u;
  vec3_t    end;
  vec3_t    forward, right, up;
  trace_t    tr;
  gentity_t  *traceEnt;

  // derive the right and up vectors from the forward vector, because
  // the client won't have any other information
  VectorNormalize2( origin2, forward );
  PerpendicularVector( right, forward );
  CrossProduct( forward, right, up );

  // generate the "random" spread pattern
  for( i = 0; i < SHOTGUN_PELLETS; i++ )
  {
    r = Q_crandom( &seed ) * SHOTGUN_SPREAD * 16;
    u = Q_crandom( &seed ) * SHOTGUN_SPREAD * 16;
    VectorMA( origin, 8192 * 16, forward, end );
    VectorMA( end, r, right, end );
    VectorMA( end, u, up, end );

    trap_Trace( &tr, origin, NULL, NULL, end, ent->s.number, MASK_SHOT );
    traceEnt = &g_entities[ tr.entityNum ];

    // send bullet impact
    if( !( tr.surfaceFlags & SURF_NOIMPACT ) )
    {
      if( traceEnt->takedamage )
        G_Damage( traceEnt, ent, ent, forward, tr.endpos,  SHOTGUN_DMG, 0, MOD_SHOTGUN );
    }
  }
}
コード例 #2
0
ファイル: g_weapon.c プロジェクト: lally/ioquake
// this should match CG_ShotgunPattern
void ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, gentity_t *ent ) {
	int			i;
	float		r, u;
	vec3_t		end;
	vec3_t		forward, right, up;
	int			oldScore;
	qboolean	hitClient = qfalse;

	// derive the right and up vectors from the forward vector, because
	// the client won't have any other information
	VectorNormalize2( origin2, forward );
	PerpendicularVector( right, forward );
	CrossProduct( forward, right, up );

	oldScore = ent->client->ps.persistant[PERS_SCORE];

	// generate the "random" spread pattern
	for ( i = 0 ; i < DEFAULT_SHOTGUN_COUNT ; i++ ) {
		r = Q_crandom( &seed ) * DEFAULT_SHOTGUN_SPREAD * 16;
		u = Q_crandom( &seed ) * DEFAULT_SHOTGUN_SPREAD * 16;
		VectorMA( origin, 8192 * 16, forward, end);
		VectorMA (end, r, right, end);
		VectorMA (end, u, up, end);
		if( ShotgunPellet( origin, end, ent ) && !hitClient ) {
			hitClient = qtrue;
			ent->client->accuracy_hits++;
		}
	}
}
コード例 #3
0
ファイル: p_weapon.cpp プロジェクト: codetwister/qfusion
/*
* G_LocalSpread
*/
static void G_LocalSpread( vec3_t angles, int spread, int seed )
{
	float r, u;
	vec3_t axis[3], dir;
	double alpha;
	double s;

	if( spread <= 0 )
		return;

	seed &= 255;

	alpha = M_PI * Q_crandom( &seed ); // [-PI ..+PI]
	s = fabs( Q_crandom( &seed ) ); // [0..1]

	r = s * cos( alpha ) * spread;
	u = s * sin( alpha ) * spread;

	AngleVectors( angles, axis[0], axis[1], axis[2] );

	VectorMA( vec3_origin, 8192, axis[0], dir );
	VectorMA( dir, r, axis[1], dir );
	VectorMA( dir, u, axis[2], dir );

	VecToAngles( dir, angles );
}
コード例 #4
0
ファイル: g_weapon.cpp プロジェクト: ShaitanShootout/BM
static void G_Fire_RandomPattern( edict_t *self, vec3_t start, vec3_t dir, int *seed, int count, 
	int hspread, int vspread, int range, float damage, int kick, int stun, int dflags, int mod, int timeDelta )
{
	int i;
	float r;
	float u;
	trace_t trace;

	for( i = 0; i < count; i++ )
	{
		r = Q_crandom( seed ) * hspread;
		u = Q_crandom( seed ) * vspread;

		GS_TraceBullet( &trace, start, dir, r, u, range, ENTNUM( self ), timeDelta );
		if( trace.ent != -1 )
		{
			if( game.edicts[trace.ent].takedamage )
			{
				G_Damage( &game.edicts[trace.ent], self, self, dir, dir, trace.endpos, damage, kick, stun, dflags, mod );
			}
			else
			{
				if( !( trace.surfFlags & SURF_NOIMPACT ) )
				{
				}
			}
		}
	}
}
コード例 #5
0
ファイル: g_weapon.c プロジェクト: ElderPlayerX/Afterwards
/*
================
Shotgun_Pattern
================
*/
void ShotgunPattern( vec3_t origin, vec3_t origin2, gentity_t *ent ) {
	int			i;
	float		r, u;
	vec3_t		end;
	vec3_t		forward, right, up;
	int			randomSeed;

	// derive the right and up vectors from the forward vector, because
	// the client won't have any other information
	VectorNormalize2( origin2, forward );
	PerpendicularVector( right, forward );
	CrossProduct( forward, right, up );

	randomSeed = ent->client->ps.randomSeed;
	// generate the "random" spread pattern
	for ( i = 0 ; i < weLi[ent->s.weapon].recoil_shot ; i++ ) {
		r = Q_crandom( &randomSeed ) * weLi[ent->s.weapon].spread_recoil * 16;
		u = Q_crandom( &randomSeed ) * weLi[ent->s.weapon].spread_recoil * 16;
		VectorMA( origin, 8192 * 16, forward, end);
		VectorMA (end, r, right, end);
		VectorMA (end, u, up, end);

		ShotgunPellet( origin, end, ent );
	}
}
コード例 #6
0
ファイル: weapon.c プロジェクト: icanhas/yantar
/* this should match CG_ShotgunPattern */
void
ShotgunPattern(Vec3 origin, Vec3 origin2, int seed, Gentity *ent)
{
	int i;
	float r, u;
	Vec3 end;
	Vec3 forward, right, up;
	qbool hitClient = qfalse;

	/* derive the right and up vectors from the forward vector, because
	 * the client won't have any other information */
	norm2v3(origin2, forward);
	perpv3(right, forward);
	crossv3(forward, right, up);

	/* generate the "random" spread pattern */
	for(i = 0; i < DEFAULT_SHOTGUN_COUNT; i++){
		r = Q_crandom(&seed) * DEFAULT_SHOTGUN_SPREAD * 16;
		u = Q_crandom(&seed) * DEFAULT_SHOTGUN_SPREAD * 16;
		saddv3(origin, 8192 * 16, forward, end);
		saddv3 (end, r, right, end);
		saddv3 (end, u, up, end);
		if(ShotgunPellet(origin, end, ent) && !hitClient){
			hitClient = qtrue;
			ent->client->accuracy_hits++;
		}
	}
}
コード例 #7
0
ファイル: g_weapon.c プロジェクト: coltongit/3wctf
// this should match CG_ShotgunPattern
void ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, gentity_t *ent ) {
	int			i;
	float		r, u;
	vec3_t		end;
	vec3_t		forward, right, up;
	qboolean	hitPlayer = qfalse;

	// derive the right and up vectors from the forward vector, because
	// the client won't have any other information
	VectorNormalize2( origin2, forward );
	PerpendicularVector( right, forward );
	CrossProduct( forward, right, up );

	// backward-reconcile the other clients
	G_DoTimeShiftFor( ent );

	// generate the "random" spread pattern
	for ( i = 0 ; i < DEFAULT_SHOTGUN_COUNT ; i++ ) {
		r = Q_crandom( &seed ) * DEFAULT_SHOTGUN_SPREAD * 16;
		u = Q_crandom( &seed ) * DEFAULT_SHOTGUN_SPREAD * 16;
		VectorMA( origin, 8192 * 16, forward, end);
		VectorMA (end, r, right, end);
		VectorMA (end, u, up, end);
		if( ShotgunPellet( origin, end, ent ) && !hitPlayer ) {
			hitPlayer = qtrue;
			ent->player->accuracy_hits++;
		}
	}

	// put them back
	G_UndoTimeShiftFor( ent );
}
コード例 #8
0
ファイル: g_weapon.c プロジェクト: ElderPlayerX/Afterwards
void Bullet_Fire (gentity_t *ent, float spread, int damage, meansOfDeath_t MOD ) {
	trace_t		tr;
	vec3_t		end;
	float		r;
	float		u;
	gentity_t	*tent;
	gentity_t	*traceEnt;
	int			passent;
	int			randomSeed;

	randomSeed = ent->client->ps.randomSeed;
	r = Q_crandom( &randomSeed ) * M_PI * 2.0f;
	u = sin(r) * Q_crandom( &randomSeed ) * spread * 16;
	r = cos(r) * Q_crandom( &randomSeed ) * spread * 16;
	VectorMA (muzzle, 8192*16, forward, end);
	VectorMA (end, r, right, end);
	VectorMA (end, u, up, end);

	passent = ent->s.number;

	trap_Trace (&tr, muzzle, NULL, NULL, end, passent, MASK_SHOT);
	if ( tr.surfaceFlags & SURF_NOIMPACT ) {
		return;
	}

	traceEnt = &g_entities[ tr.entityNum ];

	// send bullet impact
	if ( traceEnt->takedamage && traceEnt->client ) {
		// compensate for lag effects
		if ( level.delagWeapons && ent->client && !(ent->r.svFlags & SVF_BOT) ) {
			VectorSubtract( traceEnt->client->saved.currentOrigin, traceEnt->r.currentOrigin, end );
			VectorAdd( tr.endpos, end, tr.endpos );
		}
		// snap the endpos to integers, but nudged towards the line
		SnapVectorTowards( tr.endpos, muzzle );

		// create impact entity
		tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_FLESH );
		tent->s.eventParm = traceEnt->s.number;
	} else {
		// snap the endpos to integers, but nudged towards the line
		SnapVectorTowards( tr.endpos, muzzle );

		tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_WALL );
		tent->s.eventParm = DirToByte( tr.plane.normal );
	}
	tent->s.otherEntityNum = ent->s.number;

	if ( traceEnt->takedamage) {
			G_Damage( traceEnt, ent, ent, forward, tr.endpos,
				damage, 0, MOD);
	}
}
コード例 #9
0
/*
================
Keep this in sync with ShotgunPattern in CGAME!
================
*/
static void ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, gentity_t *self )
{
	int       i;
	float     r, u, a;
	vec3_t    end;
	vec3_t    forward, right, up;
	trace_t   tr;
	gentity_t *traceEnt;

	// derive the right and up vectors from the forward vector, because
	// the client won't have any other information
	VectorNormalize2( origin2, forward );
	PerpendicularVector( right, forward );
	CrossProduct( forward, right, up );

	// generate the "random" spread pattern
	for ( i = 0; i < SHOTGUN_PELLETS; i++ )
	{
		r = Q_crandom( &seed ) * M_PI;
		a = Q_random( &seed ) * SHOTGUN_SPREAD * 16;

		u = sin( r ) * a;
		r = cos( r ) * a;

		VectorMA( origin, SHOTGUN_RANGE, forward, end );
		VectorMA( end, r, right, end );
		VectorMA( end, u, up, end );

		trap_Trace( &tr, origin, nullptr, nullptr, end, self->s.number, MASK_SHOT, 0 );
		traceEnt = &g_entities[ tr.entityNum ];

		traceEnt->entity->Damage((float)SHOTGUN_DMG, self, Vec3::Load(tr.endpos),
		                         Vec3::Load(forward), 0, (meansOfDeath_t)MOD_SHOTGUN);
	}
}
コード例 #10
0
ファイル: g_weapon.c プロジェクト: themuffinator/fnq3
// this should match CG_ShotgunPattern
void ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, gentity_t *ent ) {
	int			i;
	float		r, u;
	vec3_t		end;
	vec3_t		forward, right, up;
	qboolean	hitClient = qfalse;

//unlagged - attack prediction #2
	// use this for testing
	/*
	if ( g_unlagged.integer )
		Com_Printf( "Server seed: %d\n", seed );
		*/
//-unlagged - attack prediction #2

	// derive the right and up vectors from the forward vector, because
	// the client won't have any other information
	VectorNormalize2( origin2, forward );
	PerpendicularVector( right, forward );
	CrossProduct( forward, right, up );

//unlagged - backward reconciliation #2
	// backward-reconcile the other clients
	if ( g_unlagged.integer )
		G_DoTimeShiftFor( ent );
//-unlagged - backward reconciliation #2

	// generate the "random" spread pattern
	for ( i = 0 ; i < DEFAULT_SHOTGUN_COUNT ; i++ ) {
		r = Q_crandom( &seed ) * DEFAULT_SHOTGUN_SPREAD * 16;
		u = Q_crandom( &seed ) * DEFAULT_SHOTGUN_SPREAD * 16;
		VectorMA( origin, 8192 * 16, forward, end);
		VectorMA (end, r, right, end);
		VectorMA (end, u, up, end);
		if( ShotgunPellet( origin, end, ent ) && !hitClient ) {
			hitClient = qtrue;
			ent->client->accuracy_hits++;
		}
	}

//unlagged - backward reconciliation #2
	// put them back
	if ( g_unlagged.integer )
		G_UndoTimeShiftFor( ent );
//-unlagged - backward reconciliation #2
}
コード例 #11
0
ファイル: g_weapon.c プロジェクト: Kaperstone/warsow
/*
* W_Fire_Bullet
*/
void W_Fire_Bullet( edict_t *self, vec3_t start, vec3_t angles, int seed, int range, int spread, float damage, int knockback, int stun, int mod, int timeDelta )
{
	vec3_t dir;
	edict_t *event;
	float r, u;
	double alpha, s;
	trace_t trace;
	int dmgflags = DAMAGE_STUN_CLAMP|DAMAGE_KNOCKBACK_SOFT;

	if( GS_Instagib() )
		damage = 9999;

	AngleVectors( angles, dir, NULL, NULL );

	// send the event
	event = G_SpawnEvent( EV_FIRE_BULLET, seed, start );
	event->s.ownerNum = ENTNUM( self );
	event->r.svflags = SVF_TRANSMITORIGIN2;
	VectorScale( dir, 4096, event->s.origin2 ); // DirToByte is too inaccurate
	event->s.weapon = WEAP_MACHINEGUN;
	if( mod == MOD_MACHINEGUN_S )
		event->s.weapon |= EV_INVERSE;

	// circle shape
	alpha = M_PI * Q_crandom( &seed ); // [-PI ..+PI]
	s = fabs( Q_crandom( &seed ) ); // [0..1]
	r = s * cos( alpha ) * spread;
	u = s * sin( alpha ) * spread;

	GS_TraceBullet( &trace, start, dir, r, u, range, ENTNUM( self ), timeDelta );
	if( trace.ent != -1 )
	{
		if( game.edicts[trace.ent].takedamage )
		{
			G_Damage( &game.edicts[trace.ent], self, self, dir, dir, trace.endpos, damage, knockback, stun, dmgflags, mod );
		}
		else
		{
			if( !( trace.surfFlags & SURF_NOIMPACT ) )
			{
			}
		}
	}
}
コード例 #12
0
ファイル: cg_events.c プロジェクト: hettoo/racesow
static void CG_Event_FireMachinegun( vec3_t origin, vec3_t dir, int weapon, int firemode, int seed, int owner )
{
	float r, u;
	double alpha, s;
	trace_t trace, *water_trace;
	gs_weapon_definition_t *weapondef = GS_GetWeaponDef( weapon );
	firedef_t *firedef = ( firemode ) ? &weapondef->firedef : &weapondef->firedef_weak;
	int range = firedef->timeout, spread = firedef->spread;

	// circle shape
	alpha = M_PI * Q_crandom( &seed ); // [-PI ..+PI]
	s = fabs( Q_crandom( &seed ) ); // [0..1]
	r = s * cos( alpha ) * spread;
	u = s * sin( alpha ) * spread;

	water_trace = GS_TraceBullet( &trace, origin, dir, r, u, range, owner, 0 );
	if( water_trace )
	{
		if( !VectorCompare( water_trace->endpos, origin ) )
			CG_LeadWaterSplash( water_trace );
	}

	if( trace.ent != -1 && !( trace.surfFlags & SURF_NOIMPACT ) )
	{
		CG_BulletImpact( &trace );

		if( !water_trace )
		{
			if( trace.surfFlags & SURF_FLESH ||
				( trace.ent > 0 && cg_entities[trace.ent].current.type == ET_PLAYER ) ||
				( trace.ent > 0 && cg_entities[trace.ent].current.type == ET_CORPSE ) )
			{
				// flesh impact sound
			}
			else
				trap_S_StartFixedSound( CG_MediaSfx( cgs.media.sfxRic[ rand()&2 ] ), trace.endpos, CHAN_AUTO, cg_volume_effects->value, ATTN_STATIC );
		}
	}

	if( water_trace )
		CG_LeadBubbleTrail( &trace, water_trace->endpos );
}
コード例 #13
0
ファイル: cg_weapons.c プロジェクト: ZdrytchX/cuboid
/*
================
CG_ShotgunPattern

Perform the same traces the server did to locate the
hit splashes
================
*/
static void CG_ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, int otherEntNum )
{
  int       i;
  float     r, u;
  vec3_t    end;
  vec3_t    forward, right, up;
  trace_t   tr;

  // derive the right and up vectors from the forward vector, because
  // the client won't have any other information
  VectorNormalize2( origin2, forward );
  PerpendicularVector( right, forward );
  CrossProduct( forward, right, up );

  // generate the "random" spread pattern
  for( i = 0; i < SHOTGUN_PELLETS; i++ )
  {
    r = Q_crandom( &seed ) * SHOTGUN_SPREAD * 16;
    u = Q_crandom( &seed ) * SHOTGUN_SPREAD * 16;
    VectorMA( origin, 8192 * 16, forward, end );
    VectorMA( end, r, right, end );
    VectorMA( end, u, up, end );

    CG_Trace( &tr, origin, NULL, NULL, end, otherEntNum, MASK_SHOT );

    if( !( tr.surfaceFlags & SURF_NOIMPACT ) )
    {
      if( cg_entities[ tr.entityNum ].currentState.eType == ET_PLAYER ||
          cg_entities[ tr.entityNum ].currentState.eType == ET_BUILDABLE )
        CG_MissileHitEntity( WP_SHOTGUN, WPM_PRIMARY, tr.endpos, tr.plane.normal, tr.entityNum, 0 );
      else if( tr.surfaceFlags & SURF_METALSTEPS )
        CG_MissileHitWall( WP_SHOTGUN, WPM_PRIMARY, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_METAL, 0 );
      else
        CG_MissileHitWall( WP_SHOTGUN, WPM_PRIMARY, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_DEFAULT, 0 );
    }
  }
}
コード例 #14
0
ファイル: g_weapon.cpp プロジェクト: Picmip/qfusion
/*
* W_Fire_Bullet
*/
void W_Fire_Bullet( edict_t *self, vec3_t start, vec3_t fv, vec3_t rv, vec3_t uv, int seed, int range, 
	int hspread, int vspread, float damage, int knockback, int stun, int mod, int timeDelta ) {
	edict_t *event;
	float r, u;
	double alpha, s;
	trace_t trace;
	int dmgflags = DAMAGE_STUN_CLAMP | DAMAGE_KNOCKBACK_SOFT;

	if( GS_Instagib() ) {
		damage = 9999;
	}

	// send the event
	event = G_SpawnEvent( EV_FIRE_BULLET, seed, start );
	event->s.ownerNum = ENTNUM( self );
	VectorCopy( fv, event->s.origin2 );
	VectorCopy( rv, event->s.origin3 );
	event->s.weapon = WEAP_MACHINEGUN;
	event->s.firemode = ( mod == MOD_MACHINEGUN_S ) ? FIRE_MODE_STRONG : FIRE_MODE_WEAK;

	// circle shape
	alpha = M_PI * Q_crandom( &seed ); // [-PI ..+PI]
	s = fabs( Q_crandom( &seed ) ); // [0..1]
	r = s * cos( alpha ) * hspread;
	u = s * sin( alpha ) * vspread;

	GS_TraceBullet( &trace, start, fv, rv, uv, r, u, range, ENTNUM( self ), timeDelta );
	if( trace.ent != -1 ) {
		if( game.edicts[trace.ent].takedamage ) {
			G_Damage( &game.edicts[trace.ent], self, self, fv, fv, trace.endpos, damage, knockback, stun, dmgflags, mod );
		} else {
			if( !( trace.surfFlags & SURF_NOIMPACT ) ) {
			}
		}
	}
}
コード例 #15
0
ファイル: cg_events.c プロジェクト: hettoo/racesow
/*
* CG_FireLead
*/
static void CG_FireLead( int self, vec3_t start, vec3_t axis[3], int hspread, int vspread, int *seed, trace_t *trace )
{
	trace_t	tr;
	vec3_t dir;
	vec3_t end;
	float r;
	float u;
	vec3_t water_start;
	qboolean water = qfalse;
	int content_mask = MASK_SHOT | MASK_WATER;

#if 1
	// circle
	double alpha = M_PI *Q_crandom( seed ); // [-PI ..+PI]
	double s = fabs( Q_crandom( seed ) ); // [0..1]
	r = s *cos( alpha )*hspread;
	u = s *sin( alpha )*vspread;
#else
	// square
	r = Q_crandom( seed ) * hspread;
	u = Q_crandom( seed ) * vspread;
#endif

	VectorMA( start, 8192, axis[0], end );
	VectorMA( end, r, axis[1], end );
	VectorMA( end, u, axis[2], end );

	if( CG_PointContents( start ) & MASK_WATER )
	{
		water = qtrue;
		VectorCopy( start, water_start );
		content_mask &= ~MASK_WATER;
	}

	CG_Trace( &tr, start, vec3_origin, vec3_origin, end, self, content_mask );

	// see if we hit water
	if( tr.contents & MASK_WATER )
	{
		water = qtrue;
		VectorCopy( tr.endpos, water_start );

		if( !VectorCompare( start, tr.endpos ) )
		{
			vec3_t forward, right, up;

			CG_LeadWaterSplash( &tr );

			// change bullet's course when it enters water
			VectorSubtract( end, start, dir );
			VecToAngles( dir, dir );
			AngleVectors( dir, forward, right, up );
#if 1
			// circle
			alpha = M_PI *Q_crandom( seed ); // [-PI ..+PI]
			s = fabs( Q_crandom( seed ) ); // [0..1]
			r = s *cos( alpha )*hspread*1.5;
			u = s *sin( alpha )*vspread*1.5;
#else
			r = Q_crandom( seed ) * hspread * 2;
			u = Q_crandom( seed ) * vspread * 2;
#endif
			VectorMA( water_start, 8192, forward, end );
			VectorMA( end, r, right, end );
			VectorMA( end, u, up, end );
		}

		// re-trace ignoring water this time
		CG_Trace( &tr, water_start, vec3_origin, vec3_origin, end, self, MASK_SHOT );
	}

	// save the final trace
	*trace = tr;

	// if went through water, determine where the end and make a bubble trail
	if( water )
		CG_LeadBubbleTrail( trace, water_start );
}
コード例 #16
0
ファイル: g_weapon.c プロジェクト: Kaperstone/warsow
/*
* W_Fire_Lead
* the seed is important to be as pointer for cgame prediction accuracy
*/
static void W_Fire_Lead( edict_t *self, vec3_t start, vec3_t aimdir, vec3_t axis[3], int damage, 
						int knockback, int stun, int hspread, int vspread, int *seed, int dflags,
						int mod, int timeDelta )
{
	trace_t	tr;
	vec3_t dir;
	vec3_t end;
	float r;
	float u;
	vec3_t water_start;
	int content_mask = MASK_SHOT | MASK_WATER;

	G_Trace4D( &tr, self->s.origin, NULL, NULL, start, self, MASK_SHOT, timeDelta );
	if( !( tr.fraction < 1.0 ) )
	{
#if 1
		// circle
		double alpha = M_PI * Q_crandom( seed ); // [-PI ..+PI]
		double s = fabs( Q_crandom( seed ) ); // [0..1]
		r = s * cos( alpha ) * hspread;
		u = s * sin( alpha ) * vspread;
#else
		// square
		r = Q_crandom( seed ) * hspread;
		u = Q_crandom( seed ) * vspread;
#endif
		VectorMA( start, 8192, axis[0], end );
		VectorMA( end, r, axis[1], end );
		VectorMA( end, u, axis[2], end );

		if( G_PointContents4D( start, timeDelta ) & MASK_WATER )
		{
			VectorCopy( start, water_start );
			content_mask &= ~MASK_WATER;
		}

		G_Trace4D( &tr, start, NULL, NULL, end, self, content_mask, timeDelta );

		// see if we hit water
		if( tr.contents & MASK_WATER )
		{
			VectorCopy( tr.endpos, water_start );

			if( !VectorCompare( start, tr.endpos ) )
			{
				vec3_t forward, right, up;

				// change bullet's course when it enters water
				VectorSubtract( end, start, dir );
				VecToAngles( dir, dir );
				AngleVectors( dir, forward, right, up );
#if 1
				// circle
				alpha = M_PI *Q_crandom( seed ); // [-PI ..+PI]
				s = fabs( Q_crandom( seed ) ); // [0..1]
				r = s *cos( alpha )*hspread*1.5;
				u = s *sin( alpha )*vspread*1.5;
#else
				r = Q_crandom( seed ) * hspread * 2;
				u = Q_crandom( seed ) * vspread * 2;
#endif
				VectorMA( water_start, 8192, forward, end );
				VectorMA( end, r, right, end );
				VectorMA( end, u, up, end );
			}

			// re-trace ignoring water this time
			G_Trace4D( &tr, water_start, NULL, NULL, end, self, MASK_SHOT, timeDelta );
		}
	}

	// send gun puff / flash
	if( tr.fraction < 1.0 && tr.ent != -1 )
	{
		if( game.edicts[tr.ent].takedamage )
		{
			G_Damage( &game.edicts[tr.ent], self, self, aimdir, aimdir, tr.endpos, tr.plane.normal, damage, knockback, stun, dflags, mod );
		}
		else
		{
			if( !( tr.surfFlags & SURF_NOIMPACT ) )
			{
			}
		}
	}
}
コード例 #17
0
ファイル: g_weapon.c プロジェクト: themuffinator/fnq3
void Bullet_Fire (gentity_t *ent, float spread, int damage, int mod ) {
	trace_t		tr;
	vec3_t		end;
#ifdef MISSIONPACK
	vec3_t		impactpoint, bouncedir;
#endif
	float		r;
	float		u;
	gentity_t	*tent;
	gentity_t	*traceEnt;
	int			i, passent;

	damage *= s_quadFactor;

//unlagged - attack prediction #2
	if ( g_unlagged.integer ) {
		// we have to use something now that the client knows in advance
		int	seed = ent->client->attackTime % 256;

		// this has to match what's on the client
		r = Q_random(&seed) * M_PI * 2.0f;
		u = sin(r) * Q_crandom(&seed) * spread * 16;
		r = cos(r) * Q_crandom(&seed) * spread * 16;
	} else {
		r = random() * M_PI * 2.0f;
		u = sin(r) * crandom() * spread * 16;
		r = cos(r) * crandom() * spread * 16;
	}
//-unlagged - attack prediction #2

	VectorMA (muzzle, 8192*16, forward, end);
	VectorMA (end, r, right, end);
	VectorMA (end, u, up, end);

	passent = ent->s.number;
	for (i = 0; i < 10; i++) {

//unlagged - backward reconciliation #2
		// backward-reconcile the other clients
		if ( g_unlagged.integer )
			G_DoTimeShiftFor( ent );
//-unlagged - backward reconciliation #2

		trap_Trace (&tr, muzzle, NULL, NULL, end, passent, MASK_SHOT);

//unlagged - backward reconciliation #2
		// put them back
		if ( g_unlagged.integer )
			G_UndoTimeShiftFor( ent );
//-unlagged - backward reconciliation #2

		if ( tr.surfaceFlags & SURF_NOIMPACT ) {
			return;
		}

		traceEnt = &g_entities[ tr.entityNum ];

		// snap the endpos to integers, but nudged towards the line
		SnapVectorTowards( tr.endpos, muzzle );

		// send bullet impact
		if ( traceEnt->takedamage && traceEnt->client ) {
			tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_FLESH );
			tent->s.eventParm = traceEnt->s.number;
//unlagged - attack prediction #2
			// we need the client number to determine whether or not to
			// suppress this event
			if ( g_unlagged.integer )
				tent->s.clientNum = ent->s.clientNum;
//-unlagged - attack prediction #2
			if( LogAccuracyHit( traceEnt, ent ) ) {
				ent->client->accuracy_hits++;
			}
		} else {
			tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_WALL );
			tent->s.eventParm = DirToByte( tr.plane.normal );
//unlagged - attack prediction #2
			// we need the client number to determine whether or not to
			// suppress this event
			if ( g_unlagged.integer )
				tent->s.clientNum = ent->s.clientNum;
//-unlagged - attack prediction #2
		}
		tent->s.otherEntityNum = ent->s.number;

		if ( traceEnt->takedamage) {
#ifdef MISSIONPACK
			if ( traceEnt->client && traceEnt->client->invulnerabilityTime > level.time ) {
				if (G_InvulnerabilityEffect( traceEnt, forward, tr.endpos, impactpoint, bouncedir )) {
					G_BounceProjectile( muzzle, impactpoint, bouncedir, end );
					VectorCopy( impactpoint, muzzle );
					// the player can hit him/herself with the bounced rail
					passent = ENTITYNUM_NONE;
				}
				else {
					VectorCopy( tr.endpos, muzzle );
					passent = traceEnt->s.number;
				}
				continue;
			}
			else {
#endif
				G_Damage( traceEnt, ent, ent, forward, tr.endpos,
					damage, DAMAGE_COMBAT, mod);
#ifdef MISSIONPACK
			}
#endif
		}
		break;
	}
}