/* ================= CG_DrawActiveFrame Generates and draws a game scene and status information at the given time. ================= */ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback ) { int inwater; cg.cld = 0; // NERVE - SMF - reset clientDamage #ifdef DEBUGTIME_ENABLED int dbgTime = trap_Milliseconds(),elapsed; int dbgCnt = 0; #endif cg.time = serverTime; cg.demoPlayback = demoPlayback; // update cvars CG_UpdateCvars(); /* // RF, if we should force a weapon, then do so if( !cg.weaponSelect ) { if (cg_loadWeaponSelect.integer > 0) { cg.weaponSelect = cg_loadWeaponSelect.integer; cg.weaponSelectTime = cg.time; trap_Cvar_Set( "cg_loadWeaponSelect", "0" ); // turn it off } } */ #ifdef DEBUGTIME_ENABLED CG_Printf( "\n" ); #endif DEBUGTIME // if we are only updating the screen as a loading // pacifier, don't even try to read snapshots if ( cg.infoScreenText[0] != 0 ) { CG_DrawInformation(); return; } // any looped sounds will be respecified as entities // are added to the render list trap_S_ClearLoopingSounds( qfalse ); DEBUGTIME // clear all the render lists trap_R_ClearScene(); DEBUGTIME // set up cg.snap and possibly cg.nextSnap CG_ProcessSnapshots(); DEBUGTIME // if we haven't received any snapshots yet, all // we can draw is the information screen if ( !cg.snap || ( cg.snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) { CG_DrawInformation(); return; } if ( cg.weaponSelect == WP_FG42SCOPE || cg.weaponSelect == WP_SNOOPERSCOPE || cg.weaponSelect == WP_SNIPERRIFLE ) { float spd; spd = VectorLength( cg.snap->ps.velocity ); if ( spd > 180.0f ) { switch ( cg.weaponSelect ) { case WP_FG42SCOPE: CG_FinishWeaponChange( cg.weaponSelect, WP_FG42 ); break; case WP_SNOOPERSCOPE: CG_FinishWeaponChange( cg.weaponSelect, WP_GARAND ); break; case WP_SNIPERRIFLE: CG_FinishWeaponChange( cg.weaponSelect, WP_MAUSER ); break; } } } DEBUGTIME if ( !cg.lightstylesInited ) { CG_SetupDlightstyles(); } DEBUGTIME // if we have been told not to render, don't if ( cg_norender.integer ) { return; } // this counter will be bumped for every valid scene we generate cg.clientFrame++; // update cg.predictedPlayerState CG_PredictPlayerState(); DEBUGTIME // decide on third person view cg.renderingThirdPerson = cg_thirdPerson.integer /*|| (cg.snap->ps.stats[STAT_HEALTH] <= 0)*/; // build cg.refdef inwater = CG_CalcViewValues(); CG_CalcShakeCamera(); CG_ApplyShakeCamera(); DEBUGTIME // RF, draw the skyboxportal CG_DrawSkyBoxPortal(); DEBUGTIME if ( inwater ) { CG_UnderwaterSounds(); } DEBUGTIME // first person blend blobs, done after AnglesToAxis if ( !cg.renderingThirdPerson ) { CG_DamageBlendBlob(); } DEBUGTIME // build the render lists if ( !cg.hyperspace ) { CG_AddPacketEntities(); // adter calcViewValues, so predicted player state is correct CG_AddMarks(); DEBUGTIME // Rafael particles CG_AddParticles(); // done. DEBUGTIME CG_AddLocalEntities(); DEBUGTIME }
/* ================= CG_DrawActiveFrame Generates and draws a game scene and status information at the given time. ================= */ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback ) { int inwater; int mpSetup; // NERVE - SMF #ifdef DEBUGTIME_ENABLED int dbgTime=trap_Milliseconds(),elapsed; int dbgCnt=0; #endif cg.time = serverTime; cg.demoPlayback = demoPlayback; // update cvars CG_UpdateCvars(); #ifdef DEBUGTIME_ENABLED CG_Printf("\n"); #endif DEBUGTIME // if we are only updating the screen as a loading // pacifier, don't even try to read snapshots if ( cg.infoScreenText[0] != 0 ) { CG_DrawInformation(); return; } // any looped sounds will be respecified as entities // are added to the render list trap_S_ClearLoopingSounds(qfalse); DEBUGTIME // clear all the render lists trap_R_ClearScene(); DEBUGTIME // set up cg.snap and possibly cg.nextSnap CG_ProcessSnapshots(); DEBUGTIME // if we haven't received any snapshots yet, all // we can draw is the information screen if ( !cg.snap || ( cg.snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) { CG_DrawInformation(); return; } // check for server set weapons we might not know about // (FIXME: this is a hack for the time being since a scripted "selectweapon" does // not hit the first snap, the server weapon set in cg_playerstate.c line 219 doesn't // do the trick) if( !cg.weaponSelect && cg.snap->ps.weapon) { cg.weaponSelect = cg.snap->ps.weapon; cg.weaponSelectTime = cg.time; } //----(SA) nerve uses this for snooper/sniper if (cg.weaponSelect == WP_FG42SCOPE) { float spd; spd = VectorLength(cg.snap->ps.velocity); if (spd > 180.0f) CG_FinishWeaponChange(WP_FG42SCOPE, WP_FG42); } DEBUGTIME if(!cg.lightstylesInited) CG_SetupDlightstyles(); DEBUGTIME // if we have been told not to render, don't if (cg_norender.integer) { return; } // this counter will be bumped for every valid scene we generate cg.clientFrame++; // update cg.predictedPlayerState CG_PredictPlayerState(); DEBUGTIME // decide on third person view cg.renderingThirdPerson = cg_thirdPerson.integer || (cg.snap->ps.stats[STAT_HEALTH] <= 0); // build cg.refdef inwater = CG_CalcViewValues(); DEBUGTIME // RF, draw the skyboxportal CG_DrawSkyBoxPortal(); DEBUGTIME if(inwater) CG_UnderwaterSounds(); DEBUGTIME // first person blend blobs, done after AnglesToAxis if ( !cg.renderingThirdPerson ) { CG_DamageBlendBlob(); } DEBUGTIME // build the render lists if ( !cg.hyperspace ) { CG_AddPacketEntities(); // adter calcViewValues, so predicted player state is correct CG_AddMarks(); DEBUGTIME // Rafael particles CG_AddParticles (); // done. DEBUGTIME CG_AddLocalEntities(); DEBUGTIME }
/* ================ CG_Respawn A respawn happened this snapshot ================ */ void CG_Respawn(qboolean revived) { static int oldTeam = -1; static int oldCls = -1; cg.serverRespawning = qfalse; // just in case // no error decay on player movement cg.thisFrameTeleport = qtrue; // need to reset client-side weapon animations cg.predictedPlayerState.weapAnim = ((cg.predictedPlayerState.weapAnim & ANIM_TOGGLEBIT) ^ ANIM_TOGGLEBIT) | PM_IdleAnimForWeapon(cg.snap->ps.weapon); // reset weapon animations cg.predictedPlayerState.weaponstate = WEAPON_READY; // hmm, set this? what to? // display weapons available cg.weaponSelectTime = cg.time; cg.cursorHintIcon = 0; cg.cursorHintTime = 0; // select the weapon the server says we are using cg.weaponSelect = cg.snap->ps.weapon; // clear even more things on respawn cg.zoomedBinoc = qfalse; cg.zoomedScope = qfalse; cg.zoomTime = 0; cg.zoomval = 0; trap_SendConsoleCommand("-zoom\n"); cg.binocZoomTime = 0; // ensure scoped weapons are reset after revive if (revived) { if (cg.snap->ps.weapon == WP_FG42SCOPE) { CG_FinishWeaponChange(WP_FG42SCOPE, WP_FG42); } if (cg.snap->ps.weapon == WP_GARAND_SCOPE) { CG_FinishWeaponChange(WP_GARAND_SCOPE, WP_GARAND); } if (cg.snap->ps.weapon == WP_K43_SCOPE) { CG_FinishWeaponChange(WP_K43_SCOPE, WP_K43); } } // clear pmext memset(&cg.pmext, 0, sizeof(cg.pmext)); cg.pmext.bAutoReload = (cg_autoReload.integer > 0); cg.pmext.sprintTime = SPRINTTIME; if (!revived) { cgs.limboLoadoutSelected = qfalse; } // Saves the state of sidearm (riflenade weapon is considered as one too) // Puts the silencer on if class is COVERTOPS // Puts riflenade on if current weapon is riflenade weapon if (cg.predictedPlayerState.stats[STAT_PLAYER_CLASS] == PC_COVERTOPS) { cg.pmext.silencedSideArm = 1; } else if (cg.predictedPlayerState.weapon == WP_GPG40 || cg.predictedPlayerState.weapon == WP_M7) { cg.pmext.silencedSideArm = 2; } cg.proneMovingTime = 0; // reset fog to world fog (if present) trap_R_SetFog(FOG_CMD_SWITCHFOG, FOG_MAP, 20, 0, 0, 0, 0); // try to exec a cfg file if it is found if (!revived) { if ((cgs.clientinfo[cg.clientNum].team == TEAM_AXIS || cgs.clientinfo[cg.clientNum].team == TEAM_ALLIES) && (cgs.clientinfo[cg.clientNum].cls != oldCls)) { CG_execFile(va("autoexec_%s", BG_ClassnameForNumberFilename(cgs.clientinfo[cg.clientNum].cls))); oldCls = cgs.clientinfo[cg.clientNum].cls; } if (cgs.clientinfo[cg.clientNum].team != oldTeam) { CG_execFile(va("autoexec_%s", BG_TeamnameForNumber(cgs.clientinfo[cg.clientNum].team))); oldTeam = cgs.clientinfo[cg.clientNum].team; } } }
/* =============== CG_TransitionPlayerState =============== */ void CG_TransitionPlayerState(playerState_t *ps, playerState_t *ops) { #if FEATURE_MULTIVIEW // MV client handling if (cg.mvTotalClients > 0) { if (ps->clientNum != ops->clientNum) { cg.thisFrameTeleport = qtrue; // clear voicechat cg.predictedPlayerEntity.voiceChatSpriteTime = 0; // CHECKME: should we do this here? cg_entities[ps->clientNum].voiceChatSpriteTime = 0; *ops = *ps; } CG_CheckLocalSounds(ps, ops); return; } #endif // check for changing follow mode if (ps->clientNum != ops->clientNum) { cg.thisFrameTeleport = qtrue; // clear voicechat cg.predictedPlayerEntity.voiceChatSpriteTime = 0; cg_entities[ps->clientNum].voiceChatSpriteTime = 0; // make sure we don't get any unwanted transition effects *ops = *ps; // After Limbo, make sure and do a CG_Respawn if (ps->clientNum == cg.clientNum) { ops->persistant[PERS_SPAWN_COUNT]--; } } if (ps->eFlags & EF_FIRING) { cg.lastFiredWeaponTime = 0; cg.weaponFireTime += cg.frametime; } else { if (cg.weaponFireTime > 500 && cg.weaponFireTime) { cg.lastFiredWeaponTime = cg.time; } cg.weaponFireTime = 0; } // damage events (player is getting wounded) if (ps->damageEvent != ops->damageEvent && ps->damageCount) { CG_DamageFeedback(ps->damageYaw, ps->damagePitch, ps->damageCount); } // respawning if (ps->persistant[PERS_SPAWN_COUNT] != ops->persistant[PERS_SPAWN_COUNT]) { CG_Respawn(ps->persistant[PERS_REVIVE_COUNT] != ops->persistant[PERS_REVIVE_COUNT] ? qtrue : qfalse); } if (cg.mapRestart) { CG_Respawn(qfalse); cg.mapRestart = qfalse; } if (cg.snap->ps.pm_type != PM_INTERMISSION && ps->persistant[PERS_TEAM] != TEAM_SPECTATOR) { CG_CheckLocalSounds(ps, ops); } if (ps->eFlags & EF_PRONE_MOVING) { if (ps->weapon == WP_BINOCULARS) { if (ps->eFlags & EF_ZOOMING) { trap_SendConsoleCommand("-zoom\n"); } } if (!(ops->eFlags & EF_PRONE_MOVING)) { // this screws up auto-switching when dynamite planted or grenade thrown/out of ammo //CG_FinishWeaponChange( cg.weaponSelect, ps->nextWeapon ); cg.proneMovingTime = cg.time; } } else if (ops->eFlags & EF_PRONE_MOVING) { cg.proneMovingTime = -cg.time; } if (!(ps->eFlags & EF_PRONE) && (ops->eFlags & EF_PRONE)) { if (cg.weaponSelect == WP_MOBILE_MG42_SET || cg.weaponSelect == WP_MOBILE_BROWNING_SET) { CG_FinishWeaponChange(cg.weaponSelect, ps->nextWeapon); } } // run events CG_CheckPlayerstateEvents(ps, ops); // smooth the ducking viewheight change if (ps->viewheight != ops->viewheight) { cg.duckChange = ps->viewheight - ops->viewheight; cg.duckTime = cg.time; } }
/* =============== CG_TransitionPlayerState =============== */ void CG_TransitionPlayerState(playerState_t *ps, playerState_t *ops) { // check for changing follow mode if (ps->clientNum != ops->clientNum) { cg.thisFrameTeleport = qtrue; // clear voicechat cg.predictedPlayerEntity.voiceChatSpriteTime = 0; cg_entities[ps->clientNum].voiceChatSpriteTime = 0; // make sure we don't get any unwanted transition effects *ops = *ps; // DHM - Nerve :: After Limbo, make sure and do a CG_Respawn if (ps->clientNum == cg.clientNum) { ops->persistant[PERS_SPAWN_COUNT]--; } } if (ps->eFlags & EF_FIRING) { cg.lastFiredWeaponTime = 0; cg.weaponFireTime += cg.frametime; } else { if (cg.weaponFireTime > 500 && cg.weaponFireTime) { cg.lastFiredWeaponTime = cg.time; } cg.weaponFireTime = 0; } // damage events (player is getting wounded) if (ps->damageEvent != ops->damageEvent && ps->damageCount) { CG_DamageFeedback(ps->damageYaw, ps->damagePitch, ps->damageCount); } // respawning if (ps->persistant[PERS_SPAWN_COUNT] != ops->persistant[PERS_SPAWN_COUNT]) { CG_Respawn(); } CG_CheckLocalSounds(ps, ops); if (ps->eFlags & EF_PRONE_MOVING) { if (ps->weapon == WP_BINOCULARS && ps->eFlags & EF_ZOOMING) { trap_SendConsoleCommand("-zoom\n"); } if (!(ops->eFlags & EF_PRONE_MOVING)) { cg.proneMovingTime = cg.time; } } else if (ops->eFlags & EF_PRONE_MOVING) { cg.proneMovingTime = -cg.time; } if (!(ps->eFlags & EF_PRONE) && ops->eFlags & EF_PRONE && cg.weaponSelect == WP_MOBILE_MG42_SET) { CG_FinishWeaponChange(cg.weaponSelect, ps->nextWeapon); } // run events CG_CheckPlayerstateEvents(ps, ops); // smooth the ducking viewheight change if (ps->viewheight != ops->viewheight) { cg.duckChange = ps->viewheight - ops->viewheight; cg.duckTime = cg.time; } }