/* ========================== CG_FlakEffect ========================== */ void CG_FlakEffect( centity_t * cent, entityState_t * es ) { localEntity_t * smoke; vec3_t pos, velocity; int i, temp, puff_size; static int seed = 0x92; puff_size = availableWeapons[es->weaponIndex].damageRadius / 10; VectorCopy( cent->lerpOrigin, pos ); // draw base temp = availableWeapons[es->weaponIndex].damageRadius * 0.5; for(i = 0; i <= 30; i++) { VectorCopy(cent->lerpOrigin, pos); pos[0] += (temp - (temp * -1) + 1) * Q_random( &seed ) + (temp * -1); pos[1] += (temp - (temp * -1) + 1) * Q_random( &seed ) + (temp * -1); pos[2] += (temp - (temp * -1) + 1) * Q_random( &seed ) + (temp * -1); velocity[0] = (5 - (-5) + 1) * Q_random(&seed) + -5; velocity[1] = (5 - (-5) + 1) * Q_random(&seed) + -5; smoke = CG_SmokePuff( pos, velocity, puff_size, 0.0f, 0.0f, 0.0f, 0.7f, 10000, cg.time, 8000, LEF_PUFF_DONT_SCALE, cgs.media.smokePuffShader ); } }
/* ================ 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); } }
/* ===================== CG_SmokePuff Adds a smoke puff or blood trail localEntity. it would be nice to have an acceleration vector for this as well. big velocity vector with a negative acceleration for deceleration, etc. (breath could then come out of a guys mouth at the rate he's walking/running and it would slow down once it's created) ===================== */ localEntity_t *CG_SmokePuff(const vec3_t p, const vec3_t vel, float radius, float r, float g, float b, float a, float duration, int startTime, int fadeInTime, int leFlags, qhandle_t hShader) { static int seed = 0x92; localEntity_t *le; refEntity_t *re; le = CG_AllocLocalEntity(); le->leFlags = leFlags; le->radius = radius; re = &le->refEntity; re->rotation = Q_random(&seed) * 360; re->radius = radius; re->shaderTime = startTime / 1000.0f; le->leType = LE_MOVE_SCALE_FADE; le->startTime = startTime; le->endTime = startTime + duration; le->fadeInTime = fadeInTime; if (fadeInTime > startTime) { le->lifeRate = 1.0 / (le->endTime - le->fadeInTime); } else { le->lifeRate = 1.0 / (le->endTime - le->startTime); } le->color[0] = r; le->color[1] = g; le->color[2] = b; le->color[3] = a; le->pos.trType = TR_LINEAR; le->pos.trTime = startTime; VectorCopy(vel, le->pos.trDelta); VectorCopy(p, le->pos.trBase); VectorCopy(p, re->origin); re->customShader = hShader; re->shaderRGBA[0] = le->color[0] * 0xff; re->shaderRGBA[1] = le->color[1] * 0xff; re->shaderRGBA[2] = le->color[2] * 0xff; re->shaderRGBA[3] = 0xff; re->reType = RT_SPRITE; re->radius = le->radius; return le; }
/* ===================== CG_SmokePuff Adds a smoke puff or blood trail localEntity. ===================== */ localEntity_t *CG_SmokePuff( const vec3_t p, const vec3_t vel, float radius, float r, float g, float b, float a, float duration, int startTime, int leFlags, qhandle_t hShader ) { static int seed = 0x92; localEntity_t *le; refEntity_t *re; le = CG_AllocLocalEntity(); le->leFlags = leFlags; le->data.sprite.radius = radius; re = &le->refEntity; re->data.sprite.rotation = Q_random( &seed ) * 360; re->data.sprite.radius = radius; re->shaderTime = startTime * 0.001f; le->leType = LE_MOVE_SCALE_FADE; le->startTime = startTime; le->endTime = startTime + duration; le->lifeRate = 1.0 / ( le->endTime - le->startTime ); le->color[0] = r; le->color[1] = g; le->color[2] = b; le->color[3] = a; le->pos.trType = TR_LINEAR; le->pos.trTime = startTime; VectorCopy( vel, le->pos.trDelta ); VectorCopy( p, le->pos.trBase ); VectorCopy( p, re->origin ); re->customShader = hShader; // rage pro can't alpha fade, so use a different shader if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) { re->customShader = cgs.media.smokePuffRageProShader; re->shaderRGBA[0] = 0xff; re->shaderRGBA[1] = 0xff; re->shaderRGBA[2] = 0xff; re->shaderRGBA[3] = 0xff; } else { re->shaderRGBA[0] = le->color[0] * 0xff; re->shaderRGBA[1] = le->color[1] * 0xff; re->shaderRGBA[2] = le->color[2] * 0xff; re->shaderRGBA[3] = 0xff; } re->reType = RT_SPRITE; re->data.sprite.radius = le->data.sprite.radius; return le; }
/* ================ 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, NULL, NULL, end, self->s.number, MASK_SHOT ); traceEnt = &g_entities[ tr.entityNum ]; // do the damage if ( !( tr.surfaceFlags & SURF_NOIMPACT ) ) { if ( traceEnt->takedamage ) { G_Damage( traceEnt, self, self, forward, tr.endpos, SHOTGUN_DMG, 0, MOD_SHOTGUN ); } } } }
float Q_crandom( int *seed ) { return 2.0f * (Q_random( seed ) - 0.5f); }
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; } }