//====================== // DRAW BEAM EVENT // // special effect for displacer //====================== void HUD_DrawBeam( void ) { cl_entity_t *view = GET_VIEWMODEL(); int m_iBeam = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/plasma.spr" ); gEngfuncs.pEfxAPI->R_BeamEnts( view->index|0x1000, view->index|0x2000, m_iBeam, 1.05f, 0.8f, 0.5f, 0.5f, 0.6f, 0, 10, 2, 10, 0 ); gEngfuncs.pEfxAPI->R_BeamEnts( view->index|0x1000, view->index|0x3000, m_iBeam, 1.05f, 0.8f, 0.5f, 0.5f, 0.6f, 0, 10, 2, 10, 0 ); gEngfuncs.pEfxAPI->R_BeamEnts( view->index|0x1000, view->index|0x4000, m_iBeam, 1.05f, 0.8f, 0.5f, 0.5f, 0.6f, 0, 10, 2, 10, 0 ); }
/* ============= 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; }
//========================== // V_CalcIntermisionRefdef //========================== void V_CalcIntermisionRefdef( struct ref_params_s *pparams ) { if( !v_intermission_spot ) v_intermission_spot = V_FindIntermisionSpot( pparams ); pparams->vieworg = v_intermission_spot->origin; pparams->viewangles = v_intermission_spot->angles; cl_entity_t *view = GET_VIEWMODEL(); view->model = NULL; // allways idle in intermission float old = v_idlescale; v_idlescale = 1; V_AddIdle( pparams ); v_idlescale = old; }
//========================== // V_CalcGunAngle //========================== void V_CalcGunAngle( struct ref_params_s *pparams ) { cl_entity_t *viewent; viewent = GET_VIEWMODEL(); if( !viewent ) return; viewent->angles[YAW] = pparams->viewangles[YAW] + pparams->crosshairangle[YAW]; viewent->angles[PITCH] = -pparams->viewangles[PITCH] + pparams->crosshairangle[PITCH] * 0.25f; //wow, stupid quake bug again? viewent->angles[ROLL] -= v_idlescale * sin( pparams->time * v_iroll_cycle.value ) * v_iroll_level.value; // don't apply all of the v_ipitch to prevent normally unseen parts of viewmodel from coming into view. viewent->angles[PITCH] -= v_idlescale * sin( pparams->time*v_ipitch_cycle.value ) * (v_ipitch_level.value * 0.5f); viewent->angles[YAW] -= v_idlescale * sin( pparams->time*v_iyaw_cycle.value ) * v_iyaw_level.value; viewent->latched.prevangles = viewent->angles; viewent->curstate.angles = viewent->angles; }
//====================== // Eject Shell // // eject specified shell from viewmodel // NOTE: shell model must be precached on a server //====================== void HUD_EjectShell( const struct mstudioevent_s *event, const struct cl_entity_s *entity ) { if( entity != GET_VIEWMODEL( )) return; // can eject shells only from viewmodel Vector view_ofs, ShellOrigin, ShellVelocity, forward, right, up; Vector angles = Vector( 0, entity->angles[YAW], 0 ); Vector origin = entity->origin; float fR, fU; int shell = gEngfuncs.pEventAPI->EV_FindModelIndex( event->options ); if( !shell ) { ALERT( at_error, "model %s not precached\n", event->options ); return; } int i = 0; for( i = 0; i < 3; i++ ) { if( angles[i] < -180 ) angles[i] += 360; else if( angles[i] > 180 ) angles[i] -= 360; } angles.x = -angles.x; AngleVectors( angles, forward, right, up ); fR = RANDOM_FLOAT( 50, 70 ); fU = RANDOM_FLOAT( 100, 150 ); for( i = 0; i < 3; i++ ) { ShellVelocity[i] = RI.refdef.simvel[i] + right[i] * fR + up[i] * fU + forward[i] * 25; ShellOrigin[i] = RI.refdef.vieworg[i] + up[i] * -12 + forward[i] * 20 + right[i] * 4; } gEngfuncs.pEfxAPI->R_TempModel( ShellOrigin, ShellVelocity, angles, RANDOM_LONG( 5, 10 ), shell, TE_BOUNCE_SHELL ); }
//========================== // V_CalcFirstPersonRefdef //========================== void V_CalcFirstPersonRefdef( struct ref_params_s *pparams ) { V_DriftPitch( pparams ); float bob = V_CalcBob( pparams ); pparams->vieworg = pparams->simorg; pparams->vieworg += pparams->viewheight; pparams->vieworg.z += bob; pparams->viewangles = pparams->cl_viewangles; gEngfuncs.V_CalcShake(); gEngfuncs.V_ApplyShake( pparams->vieworg, pparams->viewangles, 1.0f ); V_CalcSendOrigin( pparams ); float waterOffset = V_CalcWaterLevel( pparams ); pparams->vieworg[2] += waterOffset; V_CalcViewRoll( pparams ); V_AddIdle( pparams ); // offsets AngleVectors( pparams->cl_viewangles, pparams->forward, pparams->right, pparams->up ); cl_entity_t *view = GET_VIEWMODEL(); Vector lastAngles = view->angles = pparams->cl_viewangles; V_CalcGunAngle( pparams ); // use predicted origin as view origin. view->origin = pparams->simorg; view->origin += pparams->viewheight; view->origin.z += waterOffset; // Let the viewmodel shake at about 10% of the amplitude gEngfuncs.V_ApplyShake( view->origin, view->angles, 0.9f ); view->origin += pparams->forward * bob * 0.4f; view->origin.z += bob; view->angles[PITCH] -= bob * 0.3f; view->angles[YAW] -= bob * 0.5f; view->angles[ROLL] -= bob * 1.0f; view->origin.z -= 1; // fudge position around to keep amount of weapon visible // roughly equal with different FOV if( pparams->viewsize == 110 ) { view->origin[2] += 1; } else if( pparams->viewsize == 100 ) { view->origin[2] += 2; } else if( pparams->viewsize == 90 ) { view->origin[2] += 1; } else if( pparams->viewsize == 80 ) { view->origin[2] += 0.5; } V_CalcViewModelLag( pparams, view->origin, view->angles, lastAngles ); pparams->viewangles += pparams->punchangle; pparams->viewangles += ev_punchangle; V_DropPunchAngle(pparams->frametime,ev_punchangle); static float lasttime, oldz = 0; if( !pparams->smoothing && pparams->onground && pparams->simorg[2] - oldz > 0.0f ) { float steptime; steptime = pparams->time - lasttime; if( steptime < 0 ) steptime = 0; oldz += steptime * 150.0f; if( oldz > pparams->simorg[2] ) oldz = pparams->simorg[2]; if( pparams->simorg[2] - oldz > pparams->movevars->stepsize ) oldz = pparams->simorg[2] - pparams->movevars->stepsize; pparams->vieworg[2] += oldz - pparams->simorg[2]; view->origin.z += oldz - pparams->simorg[2]; } else { oldz = pparams->simorg[2]; } lasttime = pparams->time; // smooth player view in multiplayer V_InterpolatePos( pparams ); }
//========================== // V_InterpolatePos //========================== void V_InterpolatePos( struct ref_params_s *pparams ) { static Vector lastorg; static viewinterp_t ViewInterp; // view is the weapon model (only visible from inside body ) cl_entity_t *view = GET_VIEWMODEL(); Vector delta = pparams->simorg - lastorg; if( delta.Length() != 0.0f ) { ViewInterp.Origins[ViewInterp.CurrentOrigin & ORIGIN_MASK] = pparams->simorg; ViewInterp.OriginTime[ViewInterp.CurrentOrigin & ORIGIN_MASK] = pparams->time; ViewInterp.CurrentOrigin++; lastorg = pparams->simorg; } if( cl_vsmoothing->value && pparams->smoothing && ( pparams->maxclients > 1 )) { int i, foundidx; float t; if( cl_vsmoothing->value < 0.0f ) CVAR_SET_FLOAT( "cl_vsmoothing", 0.0 ); t = pparams->time - cl_vsmoothing->value; for( i = 1; i < ORIGIN_MASK; i++ ) { foundidx = ViewInterp.CurrentOrigin - 1 - i; if( ViewInterp.OriginTime[foundidx & ORIGIN_MASK] <= t ) break; } if( i < ORIGIN_MASK && ViewInterp.OriginTime[foundidx & ORIGIN_MASK] != 0.0f ) { // Interpolate Vector delta, neworg; double dt, frac; dt = ViewInterp.OriginTime[(foundidx + 1) & ORIGIN_MASK] - ViewInterp.OriginTime[foundidx & ORIGIN_MASK]; if( dt > 0.0f ) { frac = ( t - ViewInterp.OriginTime[foundidx & ORIGIN_MASK] ) / dt; delta = ViewInterp.Origins[( foundidx + 1 ) & ORIGIN_MASK] - ViewInterp.Origins[foundidx & ORIGIN_MASK]; frac = min( 1.0, frac ); neworg = ViewInterp.Origins[foundidx & ORIGIN_MASK] + delta * frac; // dont interpolate large changes (less than 64 units) if( delta.Length() < 64 ) { delta = neworg - pparams->simorg; pparams->simorg += delta; pparams->vieworg += delta; view->origin += delta; } } } } }