void CG_PrevWeapon_f( void ) { int i, original; if ( !cg.snap || CG_IsSpectating() ) return; if ( cg.snap->ps.emplacedIndex ) return; cg.weaponSelectTime = cg.time; original = cg.weaponSelect; for ( i = 0; i < WP_NUM_WEAPONS; i++ ) { //*SIGH*... Hack to put concussion rifle before rocketlauncher if ( cg.weaponSelect == WP_ROCKET_LAUNCHER ) cg.weaponSelect = WP_CONCUSSION; else if ( cg.weaponSelect == WP_CONCUSSION ) cg.weaponSelect = WP_FLECHETTE; else if ( cg.weaponSelect == WP_BRYAR_OLD ) cg.weaponSelect = WP_DET_PACK; else cg.weaponSelect--; if ( cg.weaponSelect == -1 ) cg.weaponSelect = WP_NUM_WEAPONS - 1; if ( CG_WeaponSelectable( cg.weaponSelect ) ) break; } if ( i == WP_NUM_WEAPONS ) cg.weaponSelect = original; else trap->S_MuteSound( cg.snap->ps.clientNum, CHAN_WEAPON ); }
void CG_Weapon_f( void ) { int num; if ( !cg.snap || CG_IsSpectating() || cg.snap->ps.emplacedIndex ) return; num = atoi( CG_Argv( 1 ) ); if ( num < 1 || num > LAST_USEABLE_WEAPON ) return; if ( num == 1 && cg.snap->ps.weapon == WP_SABER ) { if ( cg.snap->ps.weaponTime < 1 ) trap->SendConsoleCommand( "sv_saberswitch\n" ); return; } //rww - hack to make weapon numbers same as single player if ( num > WP_STUN_BATON ) num += 2; else { if ( cg.snap->ps.stats[STAT_WEAPONS] & (1 << WP_SABER) ) num = WP_SABER; else num = WP_MELEE; } if ( num > LAST_USEABLE_WEAPON + 1 ) return; if ( num >= WP_THERMAL && num <= WP_DET_PACK ) { int weap, i = 0; // already in cycle range so start with next cycle item if ( cg.snap->ps.weapon >= WP_THERMAL && cg.snap->ps.weapon <= WP_DET_PACK ) weap = cg.snap->ps.weapon + 1; else // not in cycle range, so start with thermal detonator weap = WP_THERMAL; // prevent an endless loop while ( i <= 4 ) { if ( weap > WP_DET_PACK ) weap = WP_THERMAL; if ( CG_WeaponSelectable( weap ) ) { num = weap; break; } weap++; i++; } } if ( !CG_WeaponSelectable( num ) ) return; cg.weaponSelectTime = cg.time; if ( !(cg.snap->ps.stats[STAT_WEAPONS] & (1 << num)) ) { if ( num == WP_SABER ) { // don't have saber, try melee on the same slot num = WP_MELEE; if ( !(cg.snap->ps.stats[STAT_WEAPONS] & (1 << num)) ) return; } else return; // don't have the weapon } if ( cg.weaponSelect != num ) trap->S_MuteSound( cg.snap->ps.clientNum, CHAN_WEAPON ); cg.weaponSelect = num; }
// Version of the above which doesn't add +2 to a weapon. The above can't trigger WP_MELEE or WP_STUN_BATON. // Derogatory comments go here. void CG_WeaponClean_f( void ) { int num; if ( !cg.snap || CG_IsSpectating() || cg.snap->ps.emplacedIndex ) return; num = atoi( CG_Argv( 1 ) ); if ( num < 1 || num > LAST_USEABLE_WEAPON ) return; if ( num == 1 && cg.snap->ps.weapon == WP_SABER ) { if ( cg.predictedPlayerState.weaponTime < 1 ) trap->SendConsoleCommand( "sv_saberswitch\n" ); return; } if ( num == WP_STUN_BATON ) { if ( cg.snap->ps.stats[STAT_WEAPONS] & (1 << WP_SABER) ) num = WP_SABER; else num = WP_MELEE; } // other weapons are off limits due to not actually being weapon weapons if ( num > LAST_USEABLE_WEAPON + 1 ) return; if ( num >= WP_THERMAL && num <= WP_DET_PACK ) { int weap, i; if ( cg.snap->ps.weapon >= WP_THERMAL && cg.snap->ps.weapon <= WP_DET_PACK ) weap = cg.snap->ps.weapon + 1; else weap = WP_THERMAL; // prevent an endless loop for ( i = 0; i <= 4; i++ ) { if ( weap > WP_DET_PACK ) weap = WP_THERMAL; if ( CG_WeaponSelectable( weap ) ) { num = weap; break; } weap++; } } if ( !CG_WeaponSelectable( num ) ) return; cg.weaponSelectTime = cg.time; if ( !(cg.snap->ps.stats[STAT_WEAPONS] & (1 << num)) ) { if ( num == WP_SABER ) { // don't have saber, try melee on the same slot num = WP_MELEE; if ( !(cg.snap->ps.stats[STAT_WEAPONS] & (1 << num)) ) return; } else return; // don't have the weapon } if ( cg.weaponSelect != num ) trap->S_MuteSound( cg.snap->ps.clientNum, CHAN_WEAPON ); cg.weaponSelect = num; }
void CG_CheckPlayerG2Weapons( playerState_t *ps, centity_t *cent ) { if ( !ps ) { assert( !"CG_CheckPlayerG2Weapons: NULL ps" ); return; } if ( CG_IsSpectating() ) return; if ( cent->currentState.eType == ET_NPC ) { assert( !"CG_CheckPlayerG2Weapons on NPC" ); return; } // should we change the gun model on this player? if ( cent->currentState.saberInFlight ) cent->ghoul2weapon = CG_G2WeaponInstance( cent, WP_SABER ); if ( cent->currentState.eFlags & EF_DEAD ) { // no updating weapons when dead cent->ghoul2weapon = NULL; return; } if ( cent->torsoBolt ) { // got our limb cut off, no updating weapons until it's restored cent->ghoul2weapon = NULL; return; } if ( cgs.clientinfo[ps->clientNum].team == TEAM_SPECTATOR || ps->persistant[PERS_TEAM] == TEAM_SPECTATOR ) { cent->ghoul2weapon = cg_entities[ps->clientNum].ghoul2weapon = NULL; cent->weapon = cg_entities[ps->clientNum].weapon = 0; return; } if ( cent->ghoul2 && cent->ghoul2weapon != CG_G2WeaponInstance( cent, ps->weapon ) && ps->clientNum == cent->currentState.number ) //don't want spectator mode forcing one client's weapon instance over another's { CG_CopyG2WeaponInstance( cent, ps->weapon, cent->ghoul2 ); cent->ghoul2weapon = CG_G2WeaponInstance( cent, ps->weapon ); if ( cent->weapon == WP_SABER && cent->weapon != ps->weapon && !ps->saberHolstered ) { // switching away from the saber // trap->S_StartSound( cent->lerpOrigin, cent->currentState.number, CHAN_AUTO, trap->S_RegisterSound( "sound/weapons/saber/saberoffquick.wav" ) ); if ( cgs.clientinfo[ps->clientNum].saber[0].soundOff && !ps->saberHolstered ) trap->S_StartSound( ¢->lerpOrigin, cent->currentState.number, CHAN_AUTO, cgs.clientinfo[ps->clientNum].saber[0].soundOff ); if ( cgs.clientinfo[ps->clientNum].saber[1].soundOff && cgs.clientinfo[ps->clientNum].saber[1].model[0] && !ps->saberHolstered ) { trap->S_StartSound( ¢->lerpOrigin, cent->currentState.number, CHAN_AUTO, cgs.clientinfo[ps->clientNum].saber[1].soundOff ); } } else if ( ps->weapon == WP_SABER && cent->weapon != ps->weapon && !cent->saberWasInFlight ) { // switching to the saber // trap->S_StartSound( cent->lerpOrigin, cent->currentState.number, CHAN_AUTO, trap->S_RegisterSound( "sound/weapons/saber/saberon.wav" ) ); if ( cgs.clientinfo[ps->clientNum].saber[0].soundOn ) trap->S_StartSound( ¢->lerpOrigin, cent->currentState.number, CHAN_AUTO, cgs.clientinfo[ps->clientNum].saber[0].soundOn ); if ( cgs.clientinfo[ps->clientNum].saber[1].soundOn ) trap->S_StartSound( ¢->lerpOrigin, cent->currentState.number, CHAN_AUTO, cgs.clientinfo[ps->clientNum].saber[1].soundOn ); BG_SI_SetDesiredLength( &cgs.clientinfo[ps->clientNum].saber[0], 0, -1 ); BG_SI_SetDesiredLength( &cgs.clientinfo[ps->clientNum].saber[1], 0, -1 ); } cent->weapon = ps->weapon; } }
// The transition point from snap to nextSnap has passed static void CG_TransitionSnapshot( void ) { centity_t *cent; snapshot_t *oldFrame; int i; if ( !cg.snap ) { trap->Error( ERR_DROP, "CG_TransitionSnapshot: NULL cg.snap" ); return; } if ( !cg.nextSnap ) { trap->Error( ERR_DROP, "CG_TransitionSnapshot: NULL cg.nextSnap" ); return; } // execute any server string commands before transitioning entities CG_ExecuteNewServerCommands( cg.nextSnap->serverCommandSequence ); // clear the currentValid flag for all entities in the existing snapshot for ( i = 0; i < cg.snap->numEntities; i++ ) { cent = &cg_entities[cg.snap->entities[i].number]; cent->currentValid = qfalse; } // move nextSnap to snap and do the transitions oldFrame = cg.snap; cg.snap = cg.nextSnap; // CG_CheckPlayerG2Weapons( &cg.snap->ps, &cg_entities[cg.snap->ps.clientNum] ); // CG_CheckPlayerG2Weapons( &cg.snap->ps, &cg.predictedPlayerEntity ); BG_PlayerStateToEntityState( &cg.snap->ps, &cg_entities[cg.snap->ps.clientNum].currentState, qfalse ); cg_entities[cg.snap->ps.clientNum].interpolate = qfalse; for ( i = 0; i < cg.snap->numEntities; i++ ) { cent = &cg_entities[cg.snap->entities[i].number]; CG_TransitionEntity( cent ); // remember time of snapshot this entity was last updated in cent->snapShotTime = cg.snap->serverTime; } cg.nextSnap = NULL; // check for playerstate transition events if ( oldFrame ) { playerState_t *ops, *ps; ops = &oldFrame->ps; ps = &cg.snap->ps; // teleporting checks are irrespective of prediction if ( (ps->eFlags ^ ops->eFlags) & EF_TELEPORT_BIT ) cg.thisFrameTeleport = qtrue; // will be cleared by prediction code // if we are not doing client side movement prediction for any // reason, then the client events and view changes will be issued now if ( cg.demoPlayback || CG_IsSpectating() || cg_noPredict.integer || g_synchronousClients.integer || CG_UsingEWeb() ) { CG_TransitionPlayerState( ps, ops ); } } }