/* ============= R_CullModel ============= */ bool R_CullModel( cl_entity_t *e, const Vector &origin, const Vector &mins, const Vector &maxs, float radius ) { if( e == GET_VIEWMODEL( )) { if( RI.params & RP_NONVIEWERREF ) return true; return false; } // don't reflect this entity in mirrors if( e->curstate.effects & EF_NOREFLECT && RI.params & RP_MIRRORVIEW ) return true; // draw only in mirrors if( e->curstate.effects & EF_REFLECTONLY && !( RI.params & RP_MIRRORVIEW )) return true; // never draw playermodel for himself flashlight while shadowpass is active if( RI.params & RP_SHADOWVIEW && RI.currentlight != NULL ) { if( UTIL_IsLocal( e->index ) && UTIL_IsLocal( RI.currentlight->key )) return true; } if( RP_LOCALCLIENT( e )) { if( RI.params & RP_FORCE_NOPLAYER ) return true; if( !RI.thirdPerson && UTIL_IsLocal( RI.refdef.viewentity )) { // player can view himself from the portal camera if(!( RI.params & ( RP_MIRRORVIEW|RP_PORTALVIEW|RP_SCREENVIEW|RP_SHADOWVIEW ))) return true; } } if( R_CullSphere( origin, radius, RI.clipFlags )) return true; if( RI.params & ( RP_SKYPORTALVIEW|RP_PORTALVIEW )) { if( R_VisCullSphere( e->origin, radius )) return true; } return false; }
qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType ) { if( !ent || !ent->model ) return false; if( entityType == ET_TEMPENTITY ) { // copy actual origin and angles back to let StudioModelRenderer // get actual value directly from curstate VectorCopy( ent->origin, ent->curstate.origin ); VectorCopy( ent->angles, ent->curstate.angles ); } if( CL_IsInMenu( ) && ( !cl.background || ent->player )) { // menu entities ignores client filter if( !R_AddEntity( ent, entityType )) return false; } else { // check for adding this entity if( !clgame.dllFuncs.pfnAddEntity( entityType, ent, ent->model->name )) return false; // don't add himself on firstperson if( RP_LOCALCLIENT( ent ) && !cl.thirdperson && cls.key_dest != key_menu && cl.refdef.viewentity == ( cl.playernum + 1 )) { if( gl_allow_mirrors->integer && world.has_mirrors ) { if( !R_AddEntity( ent, entityType )) return false; } // otherwise just pass to player effects like flashlight, particles etc } else if( entityType == ET_BEAM ) { CL_AddCustomBeam( ent ); return true; } else if( !R_AddEntity( ent, entityType )) { return false; } } // set actual entity type ent->curstate.entityType = entityType; // apply effects if( ent->curstate.effects & EF_BRIGHTFIELD ) CL_EntityParticles( ent ); // add in muzzleflash effect if( ent->curstate.effects & EF_MUZZLEFLASH ) { dlight_t *dl; if( ent == &clgame.viewent ) ent->curstate.effects &= ~EF_MUZZLEFLASH; dl = CL_AllocElight( 0 ); VectorCopy( ent->attachment[0], dl->origin ); dl->die = cl.time + 0.05f; dl->color.r = 255; dl->color.g = 180; dl->color.b = 64; dl->radius = 100; } // add light effect if( ent->curstate.effects & EF_LIGHT ) { dlight_t *dl = CL_AllocDlight( ent->curstate.number ); VectorCopy( ent->origin, dl->origin ); dl->die = cl.time; // die at next frame dl->color.r = 100; dl->color.g = 100; dl->color.b = 100; dl->radius = 200; CL_RocketFlare( ent->origin ); } // add dimlight if( ent->curstate.effects & EF_DIMLIGHT ) { if( entityType == ET_PLAYER ) { CL_UpdateFlashlight( ent ); } else { dlight_t *dl = CL_AllocDlight( ent->curstate.number ); VectorCopy( ent->origin, dl->origin ); dl->die = cl.time; // die at next frame dl->color.r = 255; dl->color.g = 255; dl->color.b = 255; dl->radius = Com_RandomLong( 200, 230 ); } } if( ent->curstate.effects & EF_BRIGHTLIGHT ) { dlight_t *dl = CL_AllocDlight( 0 ); VectorSet( dl->origin, ent->origin[0], ent->origin[1], ent->origin[2] + 16.0f ); dl->die = cl.time + 0.001f; // die at next frame dl->color.r = 255; dl->color.g = 255; dl->color.b = 255; if( entityType == ET_PLAYER ) dl->radius = 430; else dl->radius = Com_RandomLong( 400, 430 ); } if( ent->model->type == mod_studio ) { if( ent->model->flags & STUDIO_ROTATE ) ent->angles[1] = anglemod( 100.0f * cl.time ); if( ent->model->flags & STUDIO_GIB ) CL_RocketTrail( ent->prevstate.origin, ent->curstate.origin, 2 ); else if( ent->model->flags & STUDIO_ZOMGIB ) CL_RocketTrail( ent->prevstate.origin, ent->curstate.origin, 4 ); else if( ent->model->flags & STUDIO_TRACER ) CL_RocketTrail( ent->prevstate.origin, ent->curstate.origin, 3 ); else if( ent->model->flags & STUDIO_TRACER2 ) CL_RocketTrail( ent->prevstate.origin, ent->curstate.origin, 5 ); else if( ent->model->flags & STUDIO_ROCKET ) { dlight_t *dl = CL_AllocDlight( ent->curstate.number ); VectorCopy( ent->origin, dl->origin ); dl->color.r = 255; dl->color.g = 255; dl->color.b = 255; // HACKHACK: get radius from head entity if( ent->curstate.rendermode != kRenderNormal ) dl->radius = max( 0, ent->curstate.renderamt - 55 ); else dl->radius = 200; dl->die = cl.time + 0.01f; CL_RocketTrail( ent->prevstate.origin, ent->curstate.origin, 0 ); } else if( ent->model->flags & STUDIO_GRENADE ) CL_RocketTrail( ent->prevstate.origin, ent->curstate.origin, 1 ); else if( ent->model->flags & STUDIO_TRACER3 ) CL_RocketTrail( ent->prevstate.origin, ent->curstate.origin, 6 ); } return true; }
void CL_UpdateEntityFields( cl_entity_t *ent ) { // parametric rockets code if( ent->curstate.starttime != 0.0f && ent->curstate.impacttime != 0.0f ) { float lerp = ( cl.time - ent->curstate.starttime ) / ( ent->curstate.impacttime - ent->curstate.starttime ); vec3_t dir; lerp = bound( 0.0f, lerp, 1.0f ); // first we need to calc actual origin VectorLerp( ent->curstate.startpos, lerp, ent->curstate.endpos, ent->curstate.origin ); VectorSubtract( ent->curstate.endpos, ent->curstate.startpos, dir ); VectorAngles( dir, ent->curstate.angles ); // re-aim projectile } ent->model = Mod_Handle( ent->curstate.modelindex ); ent->curstate.msg_time = cl.time; CL_InterpolateModel( ent ); if( ent->player && RP_LOCALCLIENT( ent )) // stupid Half-Life bug ent->angles[PITCH] = -ent->angles[PITCH] / 3.0f; // make me lerp if( ent->model && ent->model->type == mod_brush && ent->curstate.animtime != 0.0f ) { float d, f = 0.0f; int i; // don't do it if the goalstarttime hasn't updated in a while. // NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit // was increased to 1.0 s., which is 2x the max lag we are accounting for. if(( cl.time < ent->curstate.animtime + 1.0f ) && ( ent->curstate.animtime != ent->latched.prevanimtime )) f = ( cl.time - ent->curstate.animtime ) / ( ent->curstate.animtime - ent->latched.prevanimtime ); f = f - 1.0f; ent->origin[0] += ( ent->origin[0] - ent->latched.prevorigin[0] ) * f; ent->origin[1] += ( ent->origin[1] - ent->latched.prevorigin[1] ) * f; ent->origin[2] += ( ent->origin[2] - ent->latched.prevorigin[2] ) * f; for( i = 0; i < 3; i++ ) { float ang1, ang2; ang1 = ent->angles[i]; ang2 = ent->latched.prevangles[i]; d = ang1 - ang2; if( d > 180.0f ) d -= 360.0f; else if( d < -180.0f ) d += 360.0f; ent->angles[i] += d * f; } } else if( ent->curstate.eflags & EFLAG_SLERP ) { float d, f = 0.0f; cl_entity_t *m_pGround = NULL; int i; // don't do it if the goalstarttime hasn't updated in a while. // NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit // was increased to 1.0 s., which is 2x the max lag we are accounting for. if(( cl.time < ent->curstate.animtime + 1.0f ) && ( ent->curstate.animtime != ent->latched.prevanimtime )) f = ( cl.time - ent->curstate.animtime ) / ( ent->curstate.animtime - ent->latched.prevanimtime ); f = f - 1.0f; if( ent->curstate.movetype == MOVETYPE_FLY ) { ent->origin[0] += ( ent->curstate.origin[0] - ent->latched.prevorigin[0] ) * f; ent->origin[1] += ( ent->curstate.origin[1] - ent->latched.prevorigin[1] ) * f; ent->origin[2] += ( ent->curstate.origin[2] - ent->latched.prevorigin[2] ) * f; for( i = 0; i < 3; i++ ) { float ang1, ang2; ang1 = ent->curstate.angles[i]; ang2 = ent->latched.prevangles[i]; d = ang1 - ang2; if( d > 180.0f ) d -= 360.0f; else if( d < -180.0f ) d += 360.0f; ent->angles[i] += d * f; } } else if( ent->curstate.movetype == MOVETYPE_STEP ) { vec3_t vecSrc, vecEnd; pmtrace_t trace; if( ent->model ) { CL_SetTraceHull( 0 ); // g-cont. player hull for better detect moving platforms VectorSet( vecSrc, ent->origin[0], ent->origin[1], ent->origin[2] + ent->model->maxs[2] ); VectorSet( vecEnd, vecSrc[0], vecSrc[1], vecSrc[2] - ent->model->mins[2] - 8.0f ); CL_PlayerTraceExt( vecSrc, vecEnd, PM_STUDIO_IGNORE, CL_PushMoveFilter, &trace ); m_pGround = CL_GetEntityByIndex( pfnIndexFromTrace( &trace )); } if( m_pGround && m_pGround->curstate.movetype == MOVETYPE_PUSH ) { qboolean applyVel, applyAvel; applyVel = !VectorCompare( m_pGround->curstate.origin, m_pGround->prevstate.origin ); applyAvel = !VectorCompare( m_pGround->curstate.angles, m_pGround->prevstate.angles ); if( applyVel || applyAvel ) { ent->origin[0] += ( m_pGround->curstate.origin[0] - m_pGround->prevstate.origin[0] ) * -1.0f; ent->origin[1] += ( m_pGround->curstate.origin[1] - m_pGround->prevstate.origin[1] ) * -1.0f; // ent->origin[2] += ( m_pGround->curstate.origin[2] - m_pGround->prevstate.origin[2] ) * -1.0f; ent->latched.prevorigin[2] = ent->origin[2]; } if( applyAvel ) { for( i = 0; i < 3; i++ ) { float ang1, ang2; ang1 = m_pGround->curstate.angles[i]; ang2 = m_pGround->prevstate.angles[i]; d = ang1 - ang2; if( d > 180.0f ) d -= 360.0f; else if( d < -180.0f ) d += 360.0f; ent->angles[i] += d * -1.0f; } } } // moved code from StudioSetupTransform here if( host.features & ENGINE_COMPUTE_STUDIO_LERP ) { ent->origin[0] += ( ent->curstate.origin[0] - ent->latched.prevorigin[0] ) * f; ent->origin[1] += ( ent->curstate.origin[1] - ent->latched.prevorigin[1] ) * f; ent->origin[2] += ( ent->curstate.origin[2] - ent->latched.prevorigin[2] ) * f; for( i = 0; i < 3; i++ ) { float ang1, ang2; ang1 = ent->angles[i]; ang2 = ent->latched.prevangles[i]; d = ang1 - ang2; if( d > 180.0f ) d -= 360.0f; else if( d < -180.0f ) d += 360.0f; ent->angles[i] += d * f; } } } } }