/* * CG_AddLocalEntities */ void CG_AddLocalEntities( void ) { #define FADEINFRAMES 2 int f; lentity_t *le, *next, *hnode; entity_t *ent; float scale, frac, fade, time, scaleIn, fadeIn; float backlerp; vec3_t angles; time = cg.frameTime; backlerp = 1.0f - cg.lerpfrac; hnode = &cg_localents_headnode; for( le = hnode->next; le != hnode; le = next ) { next = le->next; frac = ( cg.time - le->start ) * 0.01f; f = ( int )floor( frac ); clamp_low( f, 0 ); // it's time to DIE if( f >= le->frames - 1 ) { le->type = LE_FREE; CG_FreeLocalEntity( le ); continue; } if( le->frames > 1 ) { scale = 1.0f - frac / ( le->frames - 1 ); scale = bound( 0.0f, scale, 1.0f ); fade = scale * 255.0f; // quick fade in, if time enough if( le->frames > FADEINFRAMES * 2 ) { scaleIn = frac / (float)FADEINFRAMES; clamp( scaleIn, 0.0f, 1.0f ); fadeIn = scaleIn * 255.0f; } else fadeIn = 255.0f; } else { scale = 1.0f; fade = 255.0f; fadeIn = 255.0f; } ent = &le->ent; if( le->light && scale ) CG_AddLightToScene( ent->origin, le->light * scale, le->lightcolor[0], le->lightcolor[1], le->lightcolor[2], NULL ); if( le->type == LE_LASER ) { CG_QuickPolyBeam( ent->origin, ent->origin2, ent->radius, ent->customShader ); // wsw : jalfixme: missing the color (comes inside ent->skinnum) continue; } if( le->type == LE_DASH_SCALE ) { if( f < 1 ) ent->scale = 0.2 * frac; else { VecToAngles( ent->axis[1], angles ); ent->axis[1][1] += 0.005f *sin( DEG2RAD ( angles[YAW] ) ); //length ent->axis[1][0] += 0.005f *cos( DEG2RAD ( angles[YAW] ) ); //length ent->axis[0][1] += 0.008f *cos( DEG2RAD ( angles[YAW] ) ); //width ent->axis[0][0] -= 0.008f *sin( DEG2RAD ( angles[YAW] ) ); //width ent->axis[2][2] -= 0.052f; //height if( ent->axis[2][2] <= 0 ) { le->type = LE_FREE; CG_FreeLocalEntity( le ); } } } if( le->type == LE_DASH_SCALE_2 ) { if( f < 1 ) ent->scale = 0.25 * frac; else { VecToAngles( ent->axis[1], angles ); ent->axis[1][1] += 0.005f *sin( DEG2RAD ( angles[YAW] ) ); //length ent->axis[1][0] += 0.005f *cos( DEG2RAD ( angles[YAW] ) ); //length ent->axis[0][1] += 0.008f *cos( DEG2RAD ( angles[YAW] ) ); //width ent->axis[0][0] -= 0.008f *sin( DEG2RAD ( angles[YAW] ) ); //width ent->axis[2][2] -= 0.018f; //height ent->origin[1] -= 0.6f *sin( DEG2RAD ( angles[YAW] ) ); //velocity ent->origin[0] -= 0.6f *cos( DEG2RAD ( angles[YAW] ) ); //velocity if( ent->axis[2][2] <= 0 ) { le->type = LE_FREE; CG_FreeLocalEntity( le ); } } } if( le->type == LE_PUFF_SCALE ) { if( frac < 1 ) ent->scale = 7.0f*frac; else ent->scale = 7.0f - 4.0f*( frac-1 ); if( ent->scale < 0 ) { le->type = LE_FREE; CG_FreeLocalEntity( le ); } } if( le->type == LE_PUFF_SCALE_2 ) { if( le->frames - f < 4 ) ent->scale = 1.0f - 1.0f * ( frac - abs( 4-le->frames ) )/4; } if( le->type == LE_PUFF_SHRINK ) { if( frac < 3 ) ent->scale = 1.0f - 0.2f * frac/4; else { ent->scale = 0.8 - 0.8*( frac-3 )/3; VectorScale( le->velocity, 0.85f, le->velocity ); } } if( le->type == LE_EXPLOSION_TRACER ) { if( cg.time - ent->rotation > 10.0f ) { ent->rotation = cg.time; if( ent->radius - 16*frac > 4 ) CG_Explosion_Puff( ent->origin, ent->radius-16*frac, le->frames - f ); } } switch( le->type ) { case LE_NO_FADE: break; case LE_RGB_FADE: fade = min( fade, fadeIn ); ent->shaderRGBA[0] = ( qbyte )( fade * le->color[0] ); ent->shaderRGBA[1] = ( qbyte )( fade * le->color[1] ); ent->shaderRGBA[2] = ( qbyte )( fade * le->color[2] ); break; case LE_SCALE_ALPHA_FADE: fade = min( fade, fadeIn ); ent->scale = 1.0f + 1.0f / scale; ent->scale = min( ent->scale, 5.0f ); ent->shaderRGBA[3] = ( qbyte )( fade * le->color[3] ); break; case LE_INVERSESCALE_ALPHA_FADE: fade = min( fade, fadeIn ); ent->scale = scale + 0.1f; clamp( ent->scale, 0.1f, 1.0f ); ent->shaderRGBA[3] = ( qbyte )( fade * le->color[3] ); break; case LE_ALPHA_FADE: fade = min( fade, fadeIn ); ent->shaderRGBA[3] = ( qbyte )( fade * le->color[3] ); break; default: break; } ent->backlerp = backlerp; if( le->bounce ) { trace_t trace; vec3_t next_origin; VectorMA( ent->origin, time, le->velocity, next_origin ); CG_Trace( &trace, ent->origin, debris_mins, debris_maxs, next_origin, 0, MASK_SOLID ); // remove the particle when going out of the map if( ( trace.contents & CONTENTS_NODROP ) || ( trace.surfFlags & SURF_SKY ) ) { le->frames = 0; } else if( trace.fraction != 1.0 ) // found solid { float dot; vec3_t vel; float xzyspeed; // Reflect velocity VectorSubtract( next_origin, ent->origin, vel ); dot = -2 *DotProduct( vel, trace.plane.normal ); VectorMA( vel, dot, trace.plane.normal, le->velocity ); //put new origin in the impact point, but move it out a bit along the normal VectorMA( trace.endpos, 1, trace.plane.normal, ent->origin ); //the entity has not speed enough. Stop checks xzyspeed = sqrt( le->velocity[0]*le->velocity[0] + le->velocity[1]*le->velocity[1] + le->velocity[2]*le->velocity[2] ); if( xzyspeed * time < 1.0f ) { trace_t traceground; vec3_t ground_origin; //see if we have ground VectorCopy( ent->origin, ground_origin ); ground_origin[2] += ( debris_mins[2] - 4 ); CG_Trace( &traceground, ent->origin, debris_mins, debris_maxs, ground_origin, 0, MASK_SOLID ); if( traceground.fraction != 1.0 ) { le->bounce = qfalse; VectorClear( le->velocity ); VectorClear( le->accel ); if( le->type == LE_EXPLOSION_TRACER ) { // blx le->type = LE_FREE; CG_FreeLocalEntity( le ); } } } else VectorScale( le->velocity, le->bounce * time, le->velocity ); } else { VectorCopy( ent->origin, ent->origin2 ); VectorCopy( next_origin, ent->origin ); } } else { VectorCopy( ent->origin, ent->origin2 ); VectorMA( ent->origin, time, le->velocity, ent->origin ); } VectorCopy( ent->origin, ent->lightingOrigin ); VectorMA( le->velocity, time, le->accel, le->velocity ); CG_AddEntityToScene( ent ); } }
/* * CG_AddLocalEntities */ void CG_AddLocalEntities( void ) { #define FADEINFRAMES 2 int f; lentity_t *le, *next, *hnode; entity_t *ent; float scale, frac, fade, time, scaleIn, fadeIn; float backlerp; vec3_t angles; time = cg.frameTime; backlerp = 1.0f - cg.lerpfrac; hnode = &cg_localents_headnode; for( le = hnode->next; le != hnode; le = next ) { next = le->next; frac = ( cg.time - le->start ) * 0.01f; f = ( int )floor( frac ); clamp_low( f, 0 ); // it's time to DIE if( f >= le->frames - 1 ) { le->type = LE_FREE; CG_FreeLocalEntity( le ); continue; } if( le->frames > 1 ) { scale = 1.0f - frac / ( le->frames - 1 ); scale = bound( 0.0f, scale, 1.0f ); fade = scale * 255.0f; // quick fade in, if time enough if( le->frames > FADEINFRAMES * 2 ) { scaleIn = frac / (float)FADEINFRAMES; clamp( scaleIn, 0.0f, 1.0f ); fadeIn = scaleIn * 255.0f; } else fadeIn = 255.0f; } else { scale = 1.0f; fade = 255.0f; fadeIn = 255.0f; } ent = &le->ent; if( le->light && scale ) CG_AddLightToScene( ent->origin, le->light * scale, le->lightcolor[0], le->lightcolor[1], le->lightcolor[2] ); if( le->type == LE_LASER ) { CG_QuickPolyBeam( ent->origin, ent->origin2, ent->radius, ent->customShader ); // wsw : jalfixme: missing the color (comes inside ent->skinnum) continue; } if( le->type == LE_DASH_SCALE ) { if( f < 1 ) ent->scale = 0.15 * frac; else { VecToAngles( &ent->axis[AXIS_RIGHT], angles ); ent->axis[1*3+1] += 0.005f *sin( DEG2RAD ( angles[YAW] ) ); //length ent->axis[1*3+0] += 0.005f *cos( DEG2RAD ( angles[YAW] ) ); //length ent->axis[0*3+1] += 0.008f *cos( DEG2RAD ( angles[YAW] ) ); //width ent->axis[0*3+0] -= 0.008f *sin( DEG2RAD ( angles[YAW] ) ); //width ent->axis[2*3+2] -= 0.052f; //height if( ent->axis[AXIS_UP+2] <= 0 ) { le->type = LE_FREE; CG_FreeLocalEntity( le ); } } } if( le->type == LE_PUFF_SCALE ) { if( le->frames - f < 4 ) ent->scale = 1.0f - 1.0f * ( frac - abs( 4-le->frames ) )/4; } if( le->type == LE_PUFF_SHRINK ) { if( frac < 3 ) ent->scale = 1.0f - 0.2f * frac/4; else { ent->scale = 0.8 - 0.8*( frac-3 )/3; VectorScale( le->velocity, 0.85f, le->velocity ); } } if( le->type == LE_EXPLOSION_TRACER ) { if( cg.time - ent->rotation > 10.0f ) { ent->rotation = cg.time; if( ent->radius - 16*frac > 4 ) CG_Explosion_Puff( ent->origin, ent->radius-16*frac, le->frames - f ); } } switch( le->type ) { case LE_NO_FADE: break; case LE_RGB_FADE: fade = min( fade, fadeIn ); ent->shaderRGBA[0] = ( uint8_t )( fade * le->color[0] ); ent->shaderRGBA[1] = ( uint8_t )( fade * le->color[1] ); ent->shaderRGBA[2] = ( uint8_t )( fade * le->color[2] ); break; case LE_SCALE_ALPHA_FADE: fade = min( fade, fadeIn ); ent->scale = 1.0f + 1.0f / scale; ent->scale = min( ent->scale, 5.0f ); ent->shaderRGBA[3] = ( uint8_t )( fade * le->color[3] ); break; case LE_INVERSESCALE_ALPHA_FADE: fade = min( fade, fadeIn ); ent->scale = scale + 0.1f; clamp( ent->scale, 0.1f, 1.0f ); ent->shaderRGBA[3] = ( uint8_t )( fade * le->color[3] ); break; case LE_ALPHA_FADE: fade = min( fade, fadeIn ); ent->shaderRGBA[3] = ( uint8_t )( fade * le->color[3] ); break; default: break; } ent->backlerp = backlerp; if ( le->avelocity[0] || le->avelocity[1] || le->avelocity[2] ) { VectorMA( le->angles, time, le->avelocity, le->angles ); AnglesToAxis( le->angles, le->ent.axis ); } // apply rotational friction if( le->bounce ) { // FIXME? int i; const float adj = 100 * 6 * time; // magic constants here for( i = 0; i < 3; i++ ) { if( le->avelocity[i] > 0.0f ) { le->avelocity[i] -= adj; if( le->avelocity[i] < 0.0f ) { le->avelocity[i] = 0.0f; } } else if ( le->avelocity[i] < 0.0f ) { le->avelocity[i] += adj; if ( le->avelocity[i] > 0.0f ) { le->avelocity[i] = 0.0f; } } } } if( le->bounce ) { trace_t trace; vec3_t next_origin; VectorMA( ent->origin, time, le->velocity, next_origin ); CG_Trace( &trace, ent->origin, debris_mins, debris_maxs, next_origin, 0, MASK_SOLID ); // remove the particle when going out of the map if( ( trace.contents & CONTENTS_NODROP ) || ( trace.surfFlags & SURF_SKY ) ) { le->frames = 0; } else if( trace.fraction != 1.0 ) // found solid { float dot; float xyzspeed, orig_xyzspeed; float bounce; orig_xyzspeed = VectorLength( le->velocity ); // Reflect velocity dot = DotProduct( le->velocity, trace.plane.normal ); VectorMA( le->velocity, -2.0f * dot, trace.plane.normal, le->velocity ); //put new origin in the impact point, but move it out a bit along the normal VectorMA( trace.endpos, 1, trace.plane.normal, ent->origin ); // make sure we don't gain speed from bouncing off bounce = 2.0f * le->bounce * 0.01f; if( bounce < 1.5f ) bounce = 1.5f; xyzspeed = orig_xyzspeed / bounce; VectorNormalize( le->velocity ); VectorScale( le->velocity, xyzspeed, le->velocity ); //the entity has not speed enough. Stop checks if( xyzspeed * time < 1.0f ) { trace_t traceground; vec3_t ground_origin; //see if we have ground VectorCopy( ent->origin, ground_origin ); ground_origin[2] += ( debris_mins[2] - 4 ); CG_Trace( &traceground, ent->origin, debris_mins, debris_maxs, ground_origin, 0, MASK_SOLID ); if( traceground.fraction != 1.0 ) { le->bounce = 0; VectorClear( le->velocity ); VectorClear( le->accel ); VectorClear( le->avelocity ); if( le->type == LE_EXPLOSION_TRACER ) { // blx le->type = LE_FREE; CG_FreeLocalEntity( le ); } } } } else { VectorCopy( ent->origin, ent->origin2 ); VectorCopy( next_origin, ent->origin ); } } else { VectorCopy( ent->origin, ent->origin2 ); VectorMA( ent->origin, time, le->velocity, ent->origin ); } VectorCopy( ent->origin, ent->lightingOrigin ); VectorMA( le->velocity, time, le->accel, le->velocity ); CG_AddEntityToScene( ent ); } }