/* ============== CG_TileClear Clear around a sized down screen ============== */ void CG_TileClear( void ) { int top, bottom, left, right; int w, h; refdef_t *refdef = CG_GetRefdef(); w = cgs.glconfig.vidWidth; h = cgs.glconfig.vidHeight; if ( refdef->x == 0 && refdef->y == 0 && refdef->width == w && refdef->height == h ) { return; // full screen rendering } top = refdef->y; bottom = top + refdef->height - 1; left = refdef->x; right = left + refdef->width - 1; // clear above view screen CG_TileClearBox( 0, 0, w, top, media.gfx.interface.backTile ); // clear below view screen CG_TileClearBox( 0, bottom, w, h - bottom, media.gfx.interface.backTile ); // clear left of view screen CG_TileClearBox( 0, top, left, bottom - top + 1, media.gfx.interface.backTile ); // clear right of view screen CG_TileClearBox( right, top, w - right, bottom - top + 1, media.gfx.interface.backTile ); }
// This is just an optimized CG_AddMoveScaleFade for blood mists that drift down, fade out, and are emoved if the view // passes through them. // There are often 100+ of these, so it needs to be simple. static void CG_AddFallScaleFade( localEntity_t *le ) { refEntity_t *re; float c; vector3 delta; float len; refdef_t *refdef = CG_GetRefdef(); re = &le->refEntity; // fade time c = (le->endTime - cg.time) * le->lifeRate; re->shaderRGBA[3] = 0xff * c * le->color[3]; re->origin.z = le->pos.trBase.z - (1.0f - c) * le->pos.trDelta.z; re->radius = le->radius * (1.0f - c) + 16; // if the view would be "inside" the sprite, kill the sprite // so it doesn't add too much overdraw VectorSubtract( &re->origin, &refdef->vieworg, &delta ); len = VectorLength( &delta ); if ( len < le->radius ) { CG_FreeLocalEntity( le ); return; } SE_R_AddRefEntityToScene( re, MAX_CLIENTS ); }
static void CG_AddPuff( localEntity_t *le ) { refEntity_t *re; float c; vector3 delta; float len; refdef_t *refdef = CG_GetRefdef(); re = &le->refEntity; // fade / grow time c = (le->endTime - cg.time) / (float)(le->endTime - le->startTime); re->shaderRGBA[0] = le->color[0] * c; re->shaderRGBA[1] = le->color[1] * c; re->shaderRGBA[2] = le->color[2] * c; if ( !(le->leFlags & LEF_PUFF_DONT_SCALE) ) { re->radius = le->radius * (1.0f - c) + 8; } BG_EvaluateTrajectory( &le->pos, cg.time, &re->origin ); // if the view would be "inside" the sprite, kill the sprite // so it doesn't add too much overdraw VectorSubtract( &re->origin, &refdef->vieworg, &delta ); len = VectorLength( &delta ); if ( len < le->radius ) { CG_FreeLocalEntity( le ); return; } SE_R_AddRefEntityToScene( re, MAX_CLIENTS ); }
void CG_ExplosionEffects( vector3 *origin, float intensity, int radius, int time ) { //FIXME: When exactly is the vieworg calculated in relation to the rest of the frame?s vector3 dir; float dist, intensityScale; float realIntensity; refdef_t *refdef = CG_GetRefdef(); VectorSubtract( &refdef->vieworg, origin, &dir ); dist = VectorNormalize( &dir ); //Use the dir to add kick to the explosion if ( dist > radius ) return; intensityScale = 1 - ( dist / (float) radius ); realIntensity = intensity * intensityScale; CGCam_Shake( realIntensity, time ); }
static void CG_Viewpos_f( void ) { refdef_t *refdef = CG_GetRefdef(); trap->Print( "%s (%i %i %i) : %i\n", cgs.mapname, (int)refdef->vieworg.x, (int)refdef->vieworg.y, (int)refdef->vieworg.z, (int)refdef->viewangles.yaw ); }
void CG_AddScorePlum( localEntity_t *le ) { refEntity_t *re; vector3 origin, delta, dir, vec, up = { 0, 0, 1 }; float c, len; int i, score, digits[10], numdigits, negative; refdef_t *refdef = CG_GetRefdef(); re = &le->refEntity; c = (le->endTime - cg.time) * le->lifeRate; score = le->radius; if ( score < 0 ) { re->shaderRGBA[0] = 0xff; re->shaderRGBA[1] = 0x11; re->shaderRGBA[2] = 0x11; } else { re->shaderRGBA[0] = 0xff; re->shaderRGBA[1] = 0xff; re->shaderRGBA[2] = 0xff; if ( score >= 50 ) { re->shaderRGBA[1] = 0; } else if ( score >= 20 ) { re->shaderRGBA[0] = re->shaderRGBA[1] = 0; } else if ( score >= 10 ) { re->shaderRGBA[2] = 0; } else if ( score >= 2 ) { re->shaderRGBA[0] = re->shaderRGBA[2] = 0; } } if ( c < 0.25f ) re->shaderRGBA[3] = 0xff * 4 * c; else re->shaderRGBA[3] = 0xff; re->radius = NUMBER_SIZE / 2; VectorCopy( &le->pos.trBase, &origin ); origin.z += 110 - c * 100; VectorSubtract( &refdef->vieworg, &origin, &dir ); CrossProduct( &dir, &up, &vec ); VectorNormalize( &vec ); VectorMA( &origin, -10 + 20 * sinf( c * 2 * M_PI ), &vec, &origin ); // if the view would be "inside" the sprite, kill the sprite // so it doesn't add too much overdraw VectorSubtract( &origin, &refdef->vieworg, &delta ); len = VectorLength( &delta ); if ( len < 20 ) { CG_FreeLocalEntity( le ); return; } negative = qfalse; if ( score < 0 ) { negative = qtrue; score = -score; } for ( numdigits = 0; !(numdigits && !score); numdigits++ ) { digits[numdigits] = score % 10; score = score / 10; } if ( negative ) { digits[numdigits] = 10; numdigits++; } for ( i = 0; i < numdigits; i++ ) { VectorMA( &origin, (float)(((float)numdigits / 2) - i) * NUMBER_SIZE, &vec, &re->origin ); re->customShader = media.gfx.interface.numbers[digits[numdigits - 1 - i]]; SE_R_AddRefEntityToScene( re, MAX_CLIENTS ); } }
// Add the weapon, and flash for the player's view void CG_AddViewWeapon( playerState_t *ps ) { // no gun if in third person view or a camera is active if ( ps->persistant[PERS_TEAM] == TEAM_SPECTATOR || ps->pm_type == PM_INTERMISSION || cg.renderingThirdPerson ) { return; } const int weap = cg_fakeGun.integer ? cg_fakeGun.integer : ps->weapon; float desiredFov = 0.0f; if ( !cg.renderingThirdPerson && (cg_trueGuns.integer || weap == WP_SABER || weap == WP_MELEE) && cg_trueFOV.value && cg.predictedPlayerState.pm_type != PM_SPECTATOR && cg.predictedPlayerState.pm_type != PM_INTERMISSION ) { desiredFov = cg_fovViewmodel.integer ? cg_fovViewmodel.value : cg_trueFOV.value; } else { desiredFov = cg_fovViewmodel.integer ? cg_fovViewmodel.value : cg_fov.value; } desiredFov = Q_clampi( 1, desiredFov, 180 ); // allow the gun to be completely removed if ( !cg_fakeGun.integer && (!cg_drawGun.integer || cg.predictedPlayerState.zoomMode || cg_trueGuns.integer || weap == WP_SABER || weap == WP_MELEE) ) { return; } // don't draw if testing a gun model if ( cg.testGun ) { return; } centity_t *cent = &cg_entities[cg.predictedPlayerState.clientNum]; CG_RegisterWeapon( weap ); refEntity_t hand; memset( &hand, 0, sizeof(hand) ); // set up gun position vector3 angles; CG_CalculateWeaponPosition( &hand.origin, &angles ); refdef_t *refdef = CG_GetRefdef(); VectorMA( &hand.origin, cg.gunAlign.x, &refdef->viewaxis[0], &hand.origin ); VectorMA( &hand.origin, cg.gunAlign.y, &refdef->viewaxis[1], &hand.origin ); VectorMA( &hand.origin, cg.gunAlign.z, &refdef->viewaxis[2], &hand.origin ); AnglesToAxis( &angles, hand.axis ); if ( cg_fovViewmodel.integer ) { float fracDistFOV, fracWeapFOV; float fov = desiredFov; if ( cg_fovAspectAdjust.integer ) { // Based on LordHavoc's code for Darkplaces // http://www.quakeworld.nu/forum/topic/53/what-does-your-qw-look-like/page/30 const float baseAspect = 0.75f; // 3/4 const float aspect = (float)cgs.glconfig.vidWidth / (float)cgs.glconfig.vidHeight; fov = atanf( tanf( desiredFov*M_PI / 360.0f ) * baseAspect*aspect )*360.0f / M_PI; } fracDistFOV = tanf( refdef->fov_x * M_PI / 360.0f ); fracWeapFOV = (1.0f / fracDistFOV) * tanf( fov * M_PI / 360.0f ); VectorScale( &hand.axis[0], fracWeapFOV, &hand.axis[0] ); } // map torso animations to weapon animations if ( cg_debugGunFrame.integer ) { // development tool hand.frame = hand.oldframe = cg_debugGunFrame.integer; hand.backlerp = 0; } else { float currentFrame; // get clientinfo for animation map clientInfo_t *ci = nullptr; if ( cent->currentState.eType == ET_NPC ) { if ( !cent->npcClient ) { return; } ci = cent->npcClient; } else { ci = &cgs.clientinfo[cent->currentState.clientNum]; } // smoother first-person anims by eezstreet http://jkhub.org/topic/1499-/ // actually ported from SP #if 1 // Sil's fix trap->G2API_GetBoneFrame( cent->ghoul2, "lower_lumbar", cg.time, ¤tFrame, cgs.gameModels, 0 ); hand.frame = CG_MapTorsoToWeaponFrame( ci, ceilf( currentFrame ), cent->currentState.torsoAnim ); hand.oldframe = CG_MapTorsoToWeaponFrame( ci, floorf( currentFrame ), cent->currentState.torsoAnim ); hand.backlerp = 1.0f - (currentFrame - floorf( currentFrame )); #else // basejka style hand.frame = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.frame, cent->currentState.torsoAnim ); hand.oldframe = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.oldFrame, cent->currentState.torsoAnim ); hand.backlerp = cent->pe.torso.backlerp; #endif // Handle the fringe situation where oldframe is invalid if ( hand.frame == -1 ) { hand.frame = 0; hand.oldframe = 0; hand.backlerp = 0; } else if ( hand.oldframe == -1 ) { hand.oldframe = hand.frame; hand.backlerp = 0; } } weaponInfo_t *wi = &cg_weapons[weap]; hand.hModel = wi->handsModel; hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON; // add everything onto the hand CG_AddPlayerWeapon( &hand, ps, &cg_entities[cg.predictedPlayerState.clientNum], ps->persistant[PERS_TEAM], &angles, qfalse ); }
qboolean CG_CalcMuzzlePoint( int entityNum, vector3 *muzzle ) { vector3 forward, right, gunpoint; centity_t *cent; int anim; refdef_t *refdef = CG_GetRefdef(); if ( entityNum == cg.snap->ps.clientNum ) { // I'm not exactly sure why we'd be rendering someone else's crosshair, but hey. int weapontype = cg.snap->ps.weapon; vector3 weaponMuzzle; centity_t *pEnt = &cg_entities[cg.predictedPlayerState.clientNum]; VectorCopy( &WP_MuzzlePoint[weapontype], &weaponMuzzle ); if ( weapontype == WP_DISRUPTOR || weapontype == WP_STUN_BATON || weapontype == WP_MELEE || weapontype == WP_SABER ) VectorClear( &weaponMuzzle ); if ( cg.renderingThirdPerson ) { VectorCopy( &pEnt->lerpOrigin, &gunpoint ); AngleVectors( &pEnt->lerpAngles, &forward, &right, NULL ); } else { VectorCopy( &refdef->vieworg, &gunpoint ); AngleVectors( &refdef->viewangles, &forward, &right, NULL ); } if ( weapontype == WP_EMPLACED_GUN && cg.snap->ps.emplacedIndex ) { centity_t *gunEnt = &cg_entities[cg.snap->ps.emplacedIndex]; if ( gunEnt ) { vector3 pitchConstraint; VectorCopy( &gunEnt->lerpOrigin, &gunpoint ); gunpoint.z += 46; if ( cg.renderingThirdPerson ) VectorCopy( &pEnt->lerpAngles, &pitchConstraint ); else VectorCopy( &refdef->viewangles, &pitchConstraint ); if ( pitchConstraint.pitch > 40 ) pitchConstraint.pitch = 40; AngleVectors( &pitchConstraint, &forward, &right, NULL ); } } VectorCopy( &gunpoint, muzzle ); VectorMA( muzzle, weaponMuzzle.x, &forward, muzzle ); VectorMA( muzzle, weaponMuzzle.y, &right, muzzle ); if ( weapontype == WP_EMPLACED_GUN && cg.snap->ps.emplacedIndex ) { // ... } else if ( cg.renderingThirdPerson ) muzzle->z += cg.snap->ps.viewheight + weaponMuzzle.z; else muzzle->z += weaponMuzzle.z; return qtrue; } cent = &cg_entities[entityNum]; if ( !cent->currentValid ) return qfalse; VectorCopy( ¢->currentState.pos.trBase, muzzle ); AngleVectors( ¢->currentState.apos.trBase, &forward, NULL, NULL ); anim = cent->currentState.legsAnim; if ( anim == BOTH_CROUCH1WALK || anim == BOTH_CROUCH1IDLE ) muzzle->z += CROUCH_VIEWHEIGHT; else muzzle->z += DEFAULT_VIEWHEIGHT; VectorMA( muzzle, 14, &forward, muzzle ); return qtrue; }
static void CG_CalculateWeaponPosition( vector3 *origin, vector3 *angles ) { float scale, fracsin; int delta; refdef_t *refdef = CG_GetRefdef(); VectorCopy( &refdef->vieworg, origin ); VectorCopy( &refdef->viewangles, angles ); // on odd legs, invert some angles if ( cg.bobcycle & 1 ) scale = -cg.xyspeed; else scale = cg.xyspeed; // gun angles from bobbing if ( cg_gunBobEnable.integer ) { angles->pitch += cg.xyspeed * cg.bobfracsin * cg.gunBob.pitch; angles->yaw += scale * cg.bobfracsin * cg.gunBob.yaw; angles->roll += scale * cg.bobfracsin * cg.gunBob.roll; // drop the weapon when landing delta = cg.time - cg.landTime; if ( delta < LAND_DEFLECT_TIME ) origin->z += cg.landChange*0.25f * delta / LAND_DEFLECT_TIME; else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) origin->z += cg.landChange*0.25f * (LAND_DEFLECT_TIME + LAND_RETURN_TIME - delta) / LAND_RETURN_TIME; #if 0 // drop the weapon when stair climbing delta = cg.time - cg.stepTime; if ( delta < STEP_TIME/2 ) origin->z -= cg.stepChange*0.25f * delta / (STEP_TIME/2); else if ( delta < STEP_TIME ) origin->z -= cg.stepChange*0.25f * (STEP_TIME - delta) / (STEP_TIME/2); #endif } // idle drift if ( cg_gunIdleDriftEnable.integer ) { scale = cg.xyspeed + 40; fracsin = sinf( cg.time * cg.gunIdleDrift.speed ); angles->pitch += scale * fracsin * cg.gunIdleDrift.amount.pitch; angles->yaw += scale * fracsin * cg.gunIdleDrift.amount.yaw; angles->roll += scale * fracsin * cg.gunIdleDrift.amount.roll; } if ( cg_gunMomentumEnable.integer ) { // sway viewmodel when changing viewangles static vector3 previousAngles{}; vector3 deltaAngles; AnglesSubtract( angles, &previousAngles, &deltaAngles ); VectorScale( &deltaAngles, 1.0f, &deltaAngles ); const double f = std::abs( 1.0 / (double)cg_gunMomentumDamp.value ); const double y = (double)cg_gunMomentumInterval.value; const double dampRatio = 1.0 / std::pow( f, y ); VectorMA( &previousAngles, dampRatio, &deltaAngles, angles ); VectorCopy( angles, &previousAngles ); // move viewmodel downwards when jumping etc static float previousOriginZ = 0.0f; const float deltaZ = origin->z - previousOriginZ; if ( deltaZ > 0.0f ) { origin->z = origin->z - deltaZ * cg_gunMomentumFall.value; } previousOriginZ = origin->z; } }
void CG_SurfaceExplosion( vector3 *origin, vector3 *normal, float radius, float shake_speed, qboolean smoke ) { localEntity_t *le; //FXTrail *particle; vector3 direction, new_org; vector3 velocity = { 0, 0, 0 }; vector3 temp_org, temp_vel; float scale, dscale; int i, numSparks; refdef_t *refdef = CG_GetRefdef(); //Sparks numSparks = 16 + (random() * 16.0f); for ( i = 0; i < numSparks; i++ ) { scale = 0.25f + (random() * 2.0f); dscale = -scale*0.5; /* particle = FX_AddTrail( origin, NULL, NULL, 32.0f, -64.0f, scale, -scale, 1.0f, 0.0f, 0.25f, 4000.0f, cgs.media.sparkShader, rand() & FXF_BOUNCE); if ( particle == NULL ) return; FXE_Spray( normal, 500, 150, 1.0f, 768 + (rand() & 255), (FXPrimitive *) particle );*/ } //Smoke //Move this out a little from the impact surface VectorMA( origin, 4, normal, &new_org ); VectorSet( &velocity, 0.0f, 0.0f, 16.0f ); for ( i = 0; i < 4; i++ ) { VectorSet( &temp_org, new_org.x + (crandom() * 16.0f), new_org.y + (crandom() * 16.0f), new_org.z + (random() * 4.0f) ); VectorSet( &temp_vel, velocity.x + (crandom() * 8.0f), velocity.y + (crandom() * 8.0f), velocity.z + (crandom() * 8.0f) ); /* FX_AddSprite( temp_org, temp_vel, NULL, 64.0f + (random() * 32.0f), 16.0f, 1.0f, 0.0f, 20.0f + (crandom() * 90.0f), 0.5f, 1500.0f, cgs.media.smokeShader, FXF_USE_ALPHA_CHAN );*/ } //Core of the explosion //Orient the explosions to face the camera VectorSubtract( &refdef->vieworg, origin, &direction ); VectorNormalize( &direction ); //Tag the last one with a light le = CG_MakeExplosion( origin, &direction, cgs.media.explosionModel, 6, cgs.media.surfaceExplosionShader, 500, qfalse, radius * 0.02f + (random() * 0.3f), 0); le->light = 150; VectorSet( &le->lightColor, 0.9f, 0.8f, 0.5f ); for ( i = 0; i < NUM_EXPLOSIONS-1; i ++) { VectorSet( &new_org, (origin->x + (16 + (crandom() * 8))*crandom()), (origin->y + (16 + (crandom() * 8))*crandom()), (origin->z + (16 + (crandom() * 8))*crandom()) ); le = CG_MakeExplosion( &new_org, &direction, cgs.media.explosionModel, 6, cgs.media.surfaceExplosionShader, 300 + (rand() & 99), qfalse, radius * 0.05f + (crandom() *0.3f), 0); } //Shake the camera CG_ExplosionEffects( origin, shake_speed, 350, 750 ); // The level designers wanted to be able to turn the smoke spawners off. The rationale is that they // want to blow up catwalks and such that fall down...when that happens, it shouldn't really leave a mark // and a smoke spewer at the explosion point... if ( smoke ) { VectorMA( origin, -8, normal, &temp_org ); // FX_AddSpawner( temp_org, normal, NULL, NULL, 100, random()*25.0f, 5000.0f, (void *) CG_SmokeSpawn ); //Impact mark //FIXME: Replace mark //CG_ImpactMark( cgs.media.burnMarkShader, origin, normal, random()*360, 1,1,1,1, qfalse, 8, qfalse ); } }
/* ===================== CG_AddParticleToScene ===================== */ void CG_AddParticleToScene (cparticle_t *p, vector3 *org, float alpha) { vector3 point; polyVert_t verts[4]; float width; float height; float time, time2; float ratio; float invratio; vector3 color; polyVert_t TRIverts[3]; vector3 rright2, rup2; refdef_t *refdef = CG_GetRefdef(); if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) {// create a front facing polygon if (p->type != P_WEATHER_FLURRY) { if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) { if (org->z > p->end) { p->time = cg.time; VectorCopy (org, &p->org); // Ridah, fixes rare snow flakes that flicker on the ground p->org.z = ( p->start + crandom () * 4 ); if (p->type == P_BUBBLE_TURBULENT) { p->vel.x = crandom() * 4; p->vel.y = crandom() * 4; } } } else { if (org->z < p->end) { p->time = cg.time; VectorCopy (org, &p->org); // Ridah, fixes rare snow flakes that flicker on the ground while (p->org.z < p->end) { p->org.z += (p->start - p->end); } if (p->type == P_WEATHER_TURBULENT) { p->vel.x = crandom() * 16; p->vel.y = crandom() * 16; } } } // Rafael snow pvs check if (!p->link) return; p->alpha = 1; } // Ridah, had to do this or MAX_POLYS is being exceeded in village1.bsp if (Distance( &cg.snap->ps.origin, org ) > 1024) { return; } // done. if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) { VectorMA (org, -p->height, &pvup, &point); VectorMA (&point, -p->width, &pvright, &point); VectorCopy (&point, &verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = 255 * p->alpha; VectorMA (org, -p->height, &pvup, &point); VectorMA (&point, p->width, &pvright, &point); VectorCopy (&point, &verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = 255 * p->alpha; VectorMA (org, p->height, &pvup, &point); VectorMA (&point, p->width, &pvright, &point); VectorCopy (&point, &verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = 255 * p->alpha; VectorMA (org, p->height, &pvup, &point); VectorMA (&point, -p->width, &pvright, &point); VectorCopy (&point, &verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = 255 * p->alpha; } else { VectorMA (org, -p->height, &pvup, &point); VectorMA (&point, -p->width, &pvright, &point); VectorCopy( &point, &TRIverts[0].xyz ); TRIverts[0].st[0] = 1; TRIverts[0].st[1] = 0; TRIverts[0].modulate[0] = 255; TRIverts[0].modulate[1] = 255; TRIverts[0].modulate[2] = 255; TRIverts[0].modulate[3] = 255 * p->alpha; VectorMA (org, p->height, &pvup, &point); VectorMA (&point, -p->width, &pvright, &point); VectorCopy (&point, &TRIverts[1].xyz); TRIverts[1].st[0] = 0; TRIverts[1].st[1] = 0; TRIverts[1].modulate[0] = 255; TRIverts[1].modulate[1] = 255; TRIverts[1].modulate[2] = 255; TRIverts[1].modulate[3] = 255 * p->alpha; VectorMA (org, p->height, &pvup, &point); VectorMA (&point, p->width, &pvright, &point); VectorCopy (&point, &TRIverts[2].xyz); TRIverts[2].st[0] = 0; TRIverts[2].st[1] = 1; TRIverts[2].modulate[0] = 255; TRIverts[2].modulate[1] = 255; TRIverts[2].modulate[2] = 255; TRIverts[2].modulate[3] = 255 * p->alpha; } } else if (p->type == P_SPRITE) { vector3 rr, ru; vector3 rotate_ang; VectorSet (&color, 1.0, 1.0, 0.5); time = cg.time - p->time; time2 = p->endtime - p->time; ratio = time / time2; width = p->width + ( ratio * ( p->endwidth - p->width) ); height = p->height + ( ratio * ( p->endheight - p->height) ); if (p->roll) { vectoangles( &refdef->viewaxis[0], &rotate_ang ); rotate_ang.roll += p->roll; AngleVectors ( &rotate_ang, NULL, &rr, &ru); } if (p->roll) { VectorMA (org, -height, &ru, &point); VectorMA (&point, -width, &rr, &point); } else { VectorMA (org, -height, &pvup, &point); VectorMA (&point, -width, &pvright, &point); } VectorCopy (&point, &verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = 255; if (p->roll) { VectorMA (&point, 2*height, &ru, &point); } else { VectorMA (&point, 2*height, &pvup, &point); } VectorCopy (&point, &verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = 255; if (p->roll) { VectorMA (&point, 2*width, &rr, &point); } else { VectorMA (&point, 2*width, &pvright, &point); } VectorCopy (&point, &verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = 255; if (p->roll) { VectorMA (&point, -2*height, &ru, &point); } else { VectorMA (&point, -2*height, &pvup, &point); } VectorCopy (&point, &verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = 255; } else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT) {// create a front rotating facing polygon if ( p->type == P_SMOKE_IMPACT && Distance( &cg.snap->ps.origin, org ) > 1024) { return; } if (p->color == BLOODRED) VectorSet (&color, 0.22f, 0.0f, 0.0f); else if (p->color == GREY75) { float len; float greyit; float val; len = Distance (&cg.snap->ps.origin, org); if (!len) len = 1; val = 4096/len; greyit = 0.25 * val; if (greyit > 0.5) greyit = 0.5; VectorSet (&color, greyit, greyit, greyit); } else VectorSet (&color, 1.0, 1.0, 1.0); time = cg.time - p->time; time2 = p->endtime - p->time; ratio = time / time2; if (cg.time > p->startfade) { invratio = 1 - ( (cg.time - p->startfade) / (p->endtime - p->startfade) ); if (p->color == EMISIVEFADE) { float fval; fval = (invratio * invratio); if (fval < 0) fval = 0; VectorSet (&color, fval , fval , fval ); } invratio *= p->alpha; } else invratio = 1 * p->alpha; if (invratio > 1) invratio = 1; width = p->width + ( ratio * ( p->endwidth - p->width) ); height = p->height + ( ratio * ( p->endheight - p->height) ); if (p->type != P_SMOKE_IMPACT) { vector3 temp; vectoangles (&rforward, &temp); p->accumroll += p->roll; temp.roll += p->accumroll * 0.1; AngleVectors ( &temp, NULL, &rright2, &rup2); } else { VectorCopy (&rright, &rright2); VectorCopy (&rup, &rup2); } if (p->rotate) { VectorMA (org, -height, &rup2, &point); VectorMA (&point, -width, &rright2, &point); } else { VectorMA (org, -p->height, &pvup, &point); VectorMA (&point, -p->width, &pvright, &point); } VectorCopy (&point, &verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255 * color.r; verts[0].modulate[1] = 255 * color.g; verts[0].modulate[2] = 255 * color.b; verts[0].modulate[3] = 255 * invratio; if (p->rotate) { VectorMA (org, -height, &rup2, &point); VectorMA (&point, width, &rright2, &point); } else { VectorMA (org, -p->height, &pvup, &point); VectorMA (&point, p->width, &pvright, &point); } VectorCopy (&point, &verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255 * color.r; verts[1].modulate[1] = 255 * color.g; verts[1].modulate[2] = 255 * color.b; verts[1].modulate[3] = 255 * invratio; if (p->rotate) { VectorMA (org, height, &rup2, &point); VectorMA (&point, width, &rright2, &point); } else { VectorMA (org, p->height, &pvup, &point); VectorMA (&point, p->width, &pvright, &point); } VectorCopy (&point, &verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255 * color.r; verts[2].modulate[1] = 255 * color.g; verts[2].modulate[2] = 255 * color.b; verts[2].modulate[3] = 255 * invratio; if (p->rotate) { VectorMA (org, height, &rup2, &point); VectorMA (&point, -width, &rright2, &point); } else { VectorMA (org, p->height, &pvup, &point); VectorMA (&point, -p->width, &pvright, &point); } VectorCopy (&point, &verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255 * color.r; verts[3].modulate[1] = 255 * color.g; verts[3].modulate[2] = 255 * color.b; verts[3].modulate[3] = 255 * invratio; } else if (p->type == P_BLEED) { vector3 rr, ru; vector3 rotate_ang; float alpha; alpha = p->alpha; if (p->roll) { vectoangles( &refdef->viewaxis[0], &rotate_ang ); rotate_ang.roll += p->roll; AngleVectors ( &rotate_ang, NULL, &rr, &ru); } else { VectorCopy (&pvup, &ru); VectorCopy (&pvright, &rr); } VectorMA (org, -p->height, &ru, &point); VectorMA (&point, -p->width, &rr, &point); VectorCopy (&point, &verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 111; verts[0].modulate[1] = 19; verts[0].modulate[2] = 9; verts[0].modulate[3] = 255 * alpha; VectorMA (org, -p->height, &ru, &point); VectorMA (&point, p->width, &rr, &point); VectorCopy (&point, &verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 111; verts[1].modulate[1] = 19; verts[1].modulate[2] = 9; verts[1].modulate[3] = 255 * alpha; VectorMA (org, p->height, &ru, &point); VectorMA (&point, p->width, &rr, &point); VectorCopy (&point, &verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 111; verts[2].modulate[1] = 19; verts[2].modulate[2] = 9; verts[2].modulate[3] = 255 * alpha; VectorMA (org, p->height, &ru, &point); VectorMA (&point, -p->width, &rr, &point); VectorCopy (&point, &verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 111; verts[3].modulate[1] = 19; verts[3].modulate[2] = 9; verts[3].modulate[3] = 255 * alpha; } else if (p->type == P_FLAT_SCALEUP) { float width, height; float sinR, cosR; if (p->color == BLOODRED) VectorSet (&color, 1, 1, 1); else VectorSet (&color, 0.5, 0.5, 0.5); time = cg.time - p->time; time2 = p->endtime - p->time; ratio = time / time2; width = p->width + ( ratio * ( p->endwidth - p->width) ); height = p->height + ( ratio * ( p->endheight - p->height) ); if (width > p->endwidth) width = p->endwidth; if (height > p->endheight) height = p->endheight; sinR = height * sin(DEG2RAD(p->roll)) * sqrt(2.0f); cosR = width * cos(DEG2RAD(p->roll)) * sqrt(2.0f); VectorCopy (org, &verts[0].xyz); verts[0].xyz.x -= sinR; verts[0].xyz.y -= cosR; verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255 * color.r; verts[0].modulate[1] = 255 * color.g; verts[0].modulate[2] = 255 * color.b; verts[0].modulate[3] = 255; VectorCopy (org, &verts[1].xyz); verts[1].xyz.x -= cosR; verts[1].xyz.y += sinR; verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255 * color.r; verts[1].modulate[1] = 255 * color.g; verts[1].modulate[2] = 255 * color.b; verts[1].modulate[3] = 255; VectorCopy (org, &verts[2].xyz); verts[2].xyz.x += sinR; verts[2].xyz.y += cosR; verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255 * color.r; verts[2].modulate[1] = 255 * color.g; verts[2].modulate[2] = 255 * color.b; verts[2].modulate[3] = 255; VectorCopy (org, &verts[3].xyz); verts[3].xyz.x += cosR; verts[3].xyz.y -= sinR; verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255 * color.r; verts[3].modulate[1] = 255 * color.g; verts[3].modulate[2] = 255 * color.b; verts[3].modulate[3] = 255; } else if (p->type == P_FLAT) { VectorCopy (org, &verts[0].xyz); verts[0].xyz.x -= p->height; verts[0].xyz.y -= p->width; verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = 255; VectorCopy (org, &verts[1].xyz); verts[1].xyz.x -= p->height; verts[1].xyz.y += p->width; verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = 255; VectorCopy (org, &verts[2].xyz); verts[2].xyz.x += p->height; verts[2].xyz.y += p->width; verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = 255; VectorCopy (org, &verts[3].xyz); verts[3].xyz.x += p->height; verts[3].xyz.y -= p->width; verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = 255; } // Ridah else if (p->type == P_ANIM) { vector3 rr, ru; vector3 rotate_ang; int i, j; time = cg.time - p->time; time2 = p->endtime - p->time; ratio = time / time2; if (ratio >= 1.0f) { ratio = 0.9999f; } width = p->width + ( ratio * ( p->endwidth - p->width) ); height = p->height + ( ratio * ( p->endheight - p->height) ); // if we are "inside" this sprite, don't draw if (Distance( &cg.snap->ps.origin, org ) < width/1.5) { return; } i = p->shaderAnim; j = (int)floor(ratio * shaderAnimCounts[p->shaderAnim]); p->pshader = shaderAnims[i][j]; if (p->roll) { vectoangles( &refdef->viewaxis[0], &rotate_ang ); rotate_ang.roll += p->roll; AngleVectors ( &rotate_ang, NULL, &rr, &ru); } if (p->roll) { VectorMA (org, -height, &ru, &point); VectorMA (&point, -width, &rr, &point); } else { VectorMA (org, -height, &pvup, &point); VectorMA (&point, -width, &pvright, &point); } VectorCopy (&point, &verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = 255; if (p->roll) VectorMA (&point, 2*height, &ru, &point); else VectorMA (&point, 2*height, &pvup, &point); VectorCopy (&point, &verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = 255; if (p->roll) VectorMA (&point, 2*width, &rr, &point); else VectorMA (&point, 2*width, &pvright, &point); VectorCopy (&point, &verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = 255; if (p->roll) VectorMA (&point, -2*height, &ru, &point); else VectorMA (&point, -2*height, &pvup, &point); VectorCopy (&point, &verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = 255; } // done. if (!p->pshader) { // (SA) temp commented out for DM // trap->Print ("CG_AddParticleToScene type %d p->pshader == ZERO\n", p->type); return; } if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY) trap->R_AddPolysToScene( p->pshader, 3, TRIverts, 1 ); else trap->R_AddPolysToScene( p->pshader, 4, verts, 1 ); }
/* =============== CG_AddParticles =============== */ void CG_AddParticles (void) { cparticle_t *p, *next; float alpha; float time, time2; vector3 org; int color; cparticle_t *active, *tail; int type; vector3 rotate_ang; refdef_t *refdef = CG_GetRefdef(); if (!initparticles) CG_ClearParticles (); VectorCopy( &refdef->viewaxis[0], &pvforward ); VectorCopy( &refdef->viewaxis[1], &pvright ); VectorCopy( &refdef->viewaxis[2], &pvup ); vectoangles( &refdef->viewaxis[0], &rotate_ang ); roll += ((cg.time - oldtime) * 0.1) ; rotate_ang.roll += (roll*0.9); AngleVectors ( &rotate_ang, &rforward, &rright, &rup); oldtime = cg.time; active = NULL; tail = NULL; for (p=active_particles ; p ; p=next) { next = p->next; time = (cg.time - p->time)*0.001; alpha = p->alpha + time*p->alphavel; if (alpha <= 0) { // faded out p->next = free_particles; free_particles = p; p->type = 0; p->color = 0; p->alpha = 0; continue; } if (p->type == P_SMOKE || p->type == P_ANIM || p->type == P_BLEED || p->type == P_SMOKE_IMPACT) { if (cg.time > p->endtime) { p->next = free_particles; free_particles = p; p->type = 0; p->color = 0; p->alpha = 0; continue; } } if (p->type == P_WEATHER_FLURRY) { if (cg.time > p->endtime) { p->next = free_particles; free_particles = p; p->type = 0; p->color = 0; p->alpha = 0; continue; } } if (p->type == P_FLAT_SCALEUP_FADE) { if (cg.time > p->endtime) { p->next = free_particles; free_particles = p; p->type = 0; p->color = 0; p->alpha = 0; continue; } } if ((p->type == P_BAT || p->type == P_SPRITE) && p->endtime < 0) { // temporary sprite CG_AddParticleToScene (p, &p->org, alpha); p->next = free_particles; free_particles = p; p->type = 0; p->color = 0; p->alpha = 0; continue; } p->next = NULL; if (!tail) active = tail = p; else { tail->next = p; tail = p; } if (alpha > 1.0) alpha = 1; color = p->color; time2 = time*time; org.x = p->org.x + p->vel.x*time + p->accel.x*time2; org.y = p->org.y + p->vel.y*time + p->accel.y*time2; org.z = p->org.z + p->vel.z*time + p->accel.z*time2; type = p->type; CG_AddParticleToScene (p, &org, alpha); } active_particles = active; }
/* ============== CG_DamageFeedback ============== */ void CG_DamageFeedback( int yawByte, int pitchByte, int damage ) { float left, front, up; float kick; int health; float scale; vector3 dir; vector3 angles; float dist; float yaw, pitch; refdef_t *refdef = CG_GetRefdef(); // show the attacking player's head and name in corner cg.attackerTime = cg.time; // the lower on health you are, the greater the view kick will be health = cg.snap->ps.stats[STAT_HEALTH]; if ( health < 40 ) { scale = 1; } else { scale = 40.0 / health; } kick = damage * scale; if (kick < 5) kick = 5; if (kick > 10) kick = 10; // if yaw and pitch are both 255, make the damage always centered (falling, etc) if ( yawByte == 255 && pitchByte == 255 ) { cg.damageX = 0; cg.damageY = 0; cg.v_dmg_roll = 0; cg.v_dmg_pitch = -kick; } else { // positional pitch = pitchByte / 255.0 * 360; yaw = yawByte / 255.0 * 360; angles.pitch = pitch; angles.yaw = yaw; angles.roll = 0; AngleVectors( &angles, &dir, NULL, NULL ); VectorSubtract( &vec3_origin, &dir, &dir ); front = DotProduct (&dir, &refdef->viewaxis[0] ); left = DotProduct (&dir, &refdef->viewaxis[1] ); up = DotProduct (&dir, &refdef->viewaxis[2] ); dir.x = front; dir.y = left; dir.z = 0; dist = VectorLength( &dir ); if ( dist < 0.1 ) { dist = 0.1f; } cg.v_dmg_roll = kick * left; cg.v_dmg_pitch = -kick * front; if ( front <= 0.1 ) { front = 0.1f; } cg.damageX = -left / front; cg.damageY = up / dist; } // clamp the position if ( cg.damageX > 1.0 ) { cg.damageX = 1.0; } if ( cg.damageX < - 1.0 ) { cg.damageX = -1.0; } if ( cg.damageY > 1.0 ) { cg.damageY = 1.0; } if ( cg.damageY < - 1.0 ) { cg.damageY = -1.0; } // don't let the screen flashes vary as much if ( kick > 10 ) { kick = 10; } cg.damageValue = kick; cg.v_dmg_time = cg.time + DAMAGE_TIME; cg.damageTime = cg.snap->serverTime; //JLFRUMBLE #ifdef _XBOX extern void FF_XboxShake(float intensity, int duration); extern void FF_XboxDamage(int damage, float xpos); //FF_XboxShake(kick, 500); FF_XboxDamage(damage, -left); #endif }