// 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 ); } } }
// 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++; } } }
/* * 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 ); }
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 ) ) { } } } } }
/* ================ 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 ); } }
/* 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++; } } }
// 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 ); }
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); } }
/* ================ 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); } }
// 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 }
/* * 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 ) ) { } } } }
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 ); }
/* ================ 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 ); } } }
/* * 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 ) ) { } } } }
/* * 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 ); }
/* * 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 ) ) { } } } }
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; } }