/* ================ CG_AddFragment ================ */ void CG_AddFragment( localEntity_t *le ) { vec3_t newOrigin; trace_t trace; refEntity_t *re; float flameAlpha = 0.0; // TTimo: init vec3_t flameDir; qboolean hasFlame = qfalse; int i; // Ridah re = &le->refEntity; if (!re->fadeStartTime || re->fadeEndTime < le->endTime) { if (le->endTime - cg.time > 5000) { re->fadeStartTime = le->endTime - 5000; } else { re->fadeStartTime = le->endTime - 1000; } re->fadeEndTime = le->endTime; } // Ridah, flaming gibs if (le->onFireStart && (le->onFireStart < cg.time && le->onFireEnd > cg.time)) { hasFlame = qtrue; // calc the alpha flameAlpha = 1.0 - ((float)(cg.time - le->onFireStart)/(float)(le->onFireEnd - le->onFireStart)); if (flameAlpha < 0.0) flameAlpha = 0.0; if (flameAlpha > 1.0) flameAlpha = 1.0; trap_S_AddLoopingSound( -1, le->refEntity.origin, vec3_origin, cgs.media.flameCrackSound, (int)(20.0*flameAlpha) ); } //----(SA) added if(le->leFlags & LEF_SMOKING) { float alpha; refEntity_t flash; // create a little less smoke // TODO: FIXME: this is not quite right, because it'll become fps dependant - in a bad way. // the slower the fps, the /more/ smoke there'll be, probably driving the fps lower. if(!(rand()%5)) { alpha = 1.0 - ((float)(cg.time - le->startTime)/(float)(le->endTime - le->startTime)); alpha *= 0.25f; memset (&flash, 0, sizeof (flash)); CG_PositionEntityOnTag( &flash, &le->refEntity, "tag_flash", 0, NULL); CG_ParticleImpactSmokePuffExtended(cgs.media.smokeParticleShader, flash.origin, 1000, 8, 20, 20, alpha); } } //----(SA) end if ( le->pos.trType == TR_STATIONARY ) { int t; // Ridah, add the flame if (hasFlame) { refEntity_t backupEnt; backupEnt = le->refEntity; VectorClear( flameDir ); flameDir[2] = 1; le->refEntity.shaderRGBA[3] = (unsigned char)(255.0*flameAlpha); VectorCopy( flameDir, le->refEntity.fireRiseDir ); le->refEntity.customShader = cgs.media.onFireShader; trap_R_AddRefEntityToScene( &le->refEntity ); le->refEntity.customShader = cgs.media.onFireShader2; trap_R_AddRefEntityToScene( &le->refEntity ); le->refEntity = backupEnt; } t = le->endTime - cg.time; trap_R_AddRefEntityToScene( &le->refEntity ); return; } else if ( le->pos.trType == TR_GRAVITY_PAUSED ) { int t; // Ridah, add the flame if (hasFlame) { refEntity_t backupEnt; backupEnt = le->refEntity; VectorClear( flameDir ); flameDir[2] = 1; le->refEntity.shaderRGBA[3] = (unsigned char)(255.0*flameAlpha); VectorCopy( flameDir, le->refEntity.fireRiseDir ); le->refEntity.customShader = cgs.media.onFireShader; trap_R_AddRefEntityToScene( &le->refEntity ); le->refEntity.customShader = cgs.media.onFireShader2; trap_R_AddRefEntityToScene( &le->refEntity ); le->refEntity = backupEnt; } t = le->endTime - cg.time; trap_R_AddRefEntityToScene( &le->refEntity ); // trace a line from previous position down, to see if I should start falling again VectorCopy(le->refEntity.origin, newOrigin); newOrigin [2] -= 5; CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_MISSILECLIP ); if(trace.fraction == 1.0) // it's clear, start moving again { VectorClear(le->pos.trDelta); VectorClear(le->angles.trDelta); le->pos.trType = TR_GRAVITY; // nothing below me, start falling again } else return; } // calculate new position BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin ); if (hasFlame) { // calc the flame dir VectorSubtract( le->refEntity.origin, newOrigin, flameDir ); if (VectorLength( flameDir ) == 0) { flameDir[2] = 1; // play a burning sound when not moving trap_S_AddLoopingSound( 0, newOrigin, vec3_origin, cgs.media.flameSound, (int)(0.3*255.0*flameAlpha) ); } else { VectorNormalize( flameDir ); // play a flame blow sound when moving trap_S_AddLoopingSound( 0, newOrigin, vec3_origin, cgs.media.flameBlowSound, (int)(0.3*255.0*flameAlpha) ); } } // trace a line from previous position to new position CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID ); if ( trace.fraction == 1.0 ) { // still in free fall VectorCopy( newOrigin, le->refEntity.origin ); if ( le->leFlags & LEF_TUMBLE || le->angles.trType == TR_LINEAR) { vec3_t angles; BG_EvaluateTrajectory( &le->angles, cg.time, angles ); AnglesToAxis( angles, le->refEntity.axis ); if (le->sizeScale && le->sizeScale != 1.0) { for (i=0;i<3;i++) VectorScale( le->refEntity.axis[i], le->sizeScale, le->refEntity.axis[i] ); } } // Ridah, add the flame if (hasFlame) { refEntity_t backupEnt; backupEnt = le->refEntity; le->refEntity.shaderRGBA[3] = (unsigned char)(255.0*flameAlpha); VectorCopy( flameDir, le->refEntity.fireRiseDir ); le->refEntity.customShader = cgs.media.onFireShader; trap_R_AddRefEntityToScene( &le->refEntity ); le->refEntity.customShader = cgs.media.onFireShader2; trap_R_AddRefEntityToScene( &le->refEntity ); le->refEntity = backupEnt; } trap_R_AddRefEntityToScene( &le->refEntity ); // add a blood trail if ( le->leBounceSoundType == LEBS_BLOOD ) { CG_BloodTrail( le ); } return; } // if it is in a nodrop zone, remove it // this keeps gibs from waiting at the bottom of pits of death // and floating levels if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) { CG_FreeLocalEntity( le ); return; } // do a bouncy sound CG_FragmentBounceSound( le, &trace ); // reflect the velocity on the trace plane CG_ReflectVelocity( le, &trace ); // break on contact? if (le->breakCount) { clientInfo_t *ci; int clientNum; localEntity_t *nle; vec3_t dir; clientNum = le->ownerNum; if ( clientNum < 0 || clientNum >= MAX_CLIENTS ) { CG_Error( "Bad clientNum on player entity"); } ci = &cgs.clientinfo[ clientNum ]; // spawn some new fragments for (i=0;i<=le->breakCount;i++) { nle = CG_AllocLocalEntity(); memcpy( &(nle->leType), &(le->leType), sizeof(localEntity_t) - 2*sizeof(localEntity_t *) ); if (nle->breakCount-- < 2) nle->refEntity.hModel = ci->gibModels[rand()%2]; else nle->refEntity.hModel = ci->gibModels[rand()%4]; // make it smaller nle->endTime = cg.time + 5000 + rand()%2000; nle->sizeScale *= 0.8; if (nle->sizeScale < 0.7) { nle->sizeScale = 0.7; nle->leBounceSoundType = 0; } // move us a bit VectorNormalize2( nle->pos.trDelta, dir ); VectorMA( trace.endpos, 4.0*le->sizeScale*i, dir, nle->pos.trBase ); // randomize vel a bit VectorMA( nle->pos.trDelta, VectorLength(nle->pos.trDelta)*0.3, bytedirs[rand()%NUMVERTEXNORMALS], nle->pos.trDelta ); } // we're done CG_FreeLocalEntity( le ); return; } if (le->pos.trType == TR_STATIONARY && le->leMarkType == LEMT_BLOOD) { // RF, disabled for performance reasons in boss1 //if (le->leBounceSoundType) // CG_BloodPool (le, cgs.media.bloodPool, &trace); // leave a mark if (le->leMarkType) CG_FragmentBounceMark( le, &trace ); } // Ridah, add the flame if (hasFlame) { refEntity_t backupEnt; backupEnt = le->refEntity; le->refEntity.shaderRGBA[3] = (unsigned char)(255.0*flameAlpha); VectorCopy( flameDir, le->refEntity.fireRiseDir ); le->refEntity.customShader = cgs.media.onFireShader; trap_R_AddRefEntityToScene( &le->refEntity ); le->refEntity.customShader = cgs.media.onFireShader2; trap_R_AddRefEntityToScene( &le->refEntity ); le->refEntity = backupEnt; } trap_R_AddRefEntityToScene( &le->refEntity ); }
void CG_ParticleImpactSmokePuff(qhandle_t pshader, vec3_t origin) { CG_ParticleImpactSmokePuffExtended(pshader, origin, 500, 20, 20, 30, 0.25f, 8.f); }