Replace non-ASCII characters in comments with ASCII equivalents
Em dashes (---) replaced with --, arrows replaced with ->. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6e00a47416
commit
643c1d0294
7 changed files with 6643 additions and 6643 deletions
|
|
@ -1,459 +1,459 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 1999-2005 Id Software, Inc.
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
This file is part of Quake III Arena source code.
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
Quake III Arena source code is free software; you can redistribute it
|
Quake III Arena source code is free software; you can redistribute it
|
||||||
and/or modify it under the terms of the GNU General Public License as
|
and/or modify it under the terms of the GNU General Public License as
|
||||||
published by the Free Software Foundation; either version 2 of the License,
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
or (at your option) any later version.
|
or (at your option) any later version.
|
||||||
|
|
||||||
Quake III Arena source code is distributed in the hope that it will be
|
Quake III Arena source code is distributed in the hope that it will be
|
||||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Foobar; if not, write to the Free Software
|
along with Foobar; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
===========================================================================
|
===========================================================================
|
||||||
*/
|
*/
|
||||||
//
|
//
|
||||||
// cg_snapshot.c -- things that happen on snapshot transition,
|
// cg_snapshot.c -- things that happen on snapshot transition,
|
||||||
// not necessarily every single rendered frame
|
// not necessarily every single rendered frame
|
||||||
|
|
||||||
#include "cg_local.h"
|
#include "cg_local.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
CG_ResetEntity
|
CG_ResetEntity
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
static void CG_ResetEntity( centity_t *cent ) {
|
static void CG_ResetEntity( centity_t *cent ) {
|
||||||
// if the previous snapshot this entity was updated in is at least
|
// if the previous snapshot this entity was updated in is at least
|
||||||
// an event window back in time then we can reset the previous event
|
// an event window back in time then we can reset the previous event
|
||||||
if ( cent->snapShotTime < cg.time - EVENT_VALID_MSEC ) {
|
if ( cent->snapShotTime < cg.time - EVENT_VALID_MSEC ) {
|
||||||
cent->previousEvent = 0;
|
cent->previousEvent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cent->trailTime = cg.snap->serverTime;
|
cent->trailTime = cg.snap->serverTime;
|
||||||
|
|
||||||
VectorCopy (cent->currentState.origin, cent->lerpOrigin);
|
VectorCopy (cent->currentState.origin, cent->lerpOrigin);
|
||||||
VectorCopy (cent->currentState.angles, cent->lerpAngles);
|
VectorCopy (cent->currentState.angles, cent->lerpAngles);
|
||||||
if ( cent->currentState.eType == ET_PLAYER ) {
|
if ( cent->currentState.eType == ET_PLAYER ) {
|
||||||
CG_ResetPlayerEntity( cent );
|
CG_ResetPlayerEntity( cent );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
CG_TransitionEntity
|
CG_TransitionEntity
|
||||||
|
|
||||||
cent->nextState is moved to cent->currentState and events are fired
|
cent->nextState is moved to cent->currentState and events are fired
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
static void CG_TransitionEntity( centity_t *cent ) {
|
static void CG_TransitionEntity( centity_t *cent ) {
|
||||||
cent->currentState = cent->nextState;
|
cent->currentState = cent->nextState;
|
||||||
cent->currentValid = qtrue;
|
cent->currentValid = qtrue;
|
||||||
|
|
||||||
// reset if the entity wasn't in the last frame or was teleported
|
// reset if the entity wasn't in the last frame or was teleported
|
||||||
if ( !cent->interpolate ) {
|
if ( !cent->interpolate ) {
|
||||||
CG_ResetEntity( cent );
|
CG_ResetEntity( cent );
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear the next state. if will be set by the next CG_SetNextSnap
|
// clear the next state. if will be set by the next CG_SetNextSnap
|
||||||
cent->interpolate = qfalse;
|
cent->interpolate = qfalse;
|
||||||
|
|
||||||
// check for events
|
// check for events
|
||||||
CG_CheckEvents( cent );
|
CG_CheckEvents( cent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
CG_SetInitialSnapshot
|
CG_SetInitialSnapshot
|
||||||
|
|
||||||
This will only happen on the very first snapshot, or
|
This will only happen on the very first snapshot, or
|
||||||
on tourney restarts. All other times will use
|
on tourney restarts. All other times will use
|
||||||
CG_TransitionSnapshot instead.
|
CG_TransitionSnapshot instead.
|
||||||
|
|
||||||
FIXME: Also called by map_restart?
|
FIXME: Also called by map_restart?
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void CG_SetInitialSnapshot( snapshot_t *snap ) {
|
void CG_SetInitialSnapshot( snapshot_t *snap ) {
|
||||||
int i;
|
int i;
|
||||||
centity_t *cent;
|
centity_t *cent;
|
||||||
entityState_t *state;
|
entityState_t *state;
|
||||||
|
|
||||||
cg.snap = snap;
|
cg.snap = snap;
|
||||||
|
|
||||||
BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].currentState, qfalse );
|
BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].currentState, qfalse );
|
||||||
|
|
||||||
// sort out solid entities
|
// sort out solid entities
|
||||||
CG_BuildSolidList();
|
CG_BuildSolidList();
|
||||||
|
|
||||||
CG_ExecuteNewServerCommands( snap->serverCommandSequence );
|
CG_ExecuteNewServerCommands( snap->serverCommandSequence );
|
||||||
|
|
||||||
// set our local weapon selection pointer to
|
// set our local weapon selection pointer to
|
||||||
// what the server has indicated the current weapon is
|
// what the server has indicated the current weapon is
|
||||||
CG_Respawn();
|
CG_Respawn();
|
||||||
|
|
||||||
for ( i = 0 ; i < cg.snap->numEntities ; i++ ) {
|
for ( i = 0 ; i < cg.snap->numEntities ; i++ ) {
|
||||||
state = &cg.snap->entities[ i ];
|
state = &cg.snap->entities[ i ];
|
||||||
cent = &cg_entities[ state->number ];
|
cent = &cg_entities[ state->number ];
|
||||||
|
|
||||||
memcpy(¢->currentState, state, sizeof(entityState_t));
|
memcpy(¢->currentState, state, sizeof(entityState_t));
|
||||||
//cent->currentState = *state;
|
//cent->currentState = *state;
|
||||||
cent->interpolate = qfalse;
|
cent->interpolate = qfalse;
|
||||||
cent->currentValid = qtrue;
|
cent->currentValid = qtrue;
|
||||||
|
|
||||||
CG_ResetEntity( cent );
|
CG_ResetEntity( cent );
|
||||||
|
|
||||||
// check for events
|
// check for events
|
||||||
CG_CheckEvents( cent );
|
CG_CheckEvents( cent );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===================
|
===================
|
||||||
CG_TransitionSnapshot
|
CG_TransitionSnapshot
|
||||||
|
|
||||||
The transition point from snap to nextSnap has passed
|
The transition point from snap to nextSnap has passed
|
||||||
===================
|
===================
|
||||||
*/
|
*/
|
||||||
static void CG_TransitionSnapshot( void ) {
|
static void CG_TransitionSnapshot( void ) {
|
||||||
centity_t *cent;
|
centity_t *cent;
|
||||||
snapshot_t *oldFrame;
|
snapshot_t *oldFrame;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ( !cg.snap ) {
|
if ( !cg.snap ) {
|
||||||
CG_Error( "CG_TransitionSnapshot: NULL cg.snap" );
|
CG_Error( "CG_TransitionSnapshot: NULL cg.snap" );
|
||||||
}
|
}
|
||||||
if ( !cg.nextSnap ) {
|
if ( !cg.nextSnap ) {
|
||||||
CG_Error( "CG_TransitionSnapshot: NULL cg.nextSnap" );
|
CG_Error( "CG_TransitionSnapshot: NULL cg.nextSnap" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute any server string commands before transitioning entities
|
// execute any server string commands before transitioning entities
|
||||||
CG_ExecuteNewServerCommands( cg.nextSnap->serverCommandSequence );
|
CG_ExecuteNewServerCommands( cg.nextSnap->serverCommandSequence );
|
||||||
|
|
||||||
// if we had a map_restart, set everthing with initial
|
// if we had a map_restart, set everthing with initial
|
||||||
if ( !cg.snap ) {
|
if ( !cg.snap ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear the currentValid flag for all entities in the existing snapshot
|
// clear the currentValid flag for all entities in the existing snapshot
|
||||||
for ( i = 0 ; i < cg.snap->numEntities ; i++ ) {
|
for ( i = 0 ; i < cg.snap->numEntities ; i++ ) {
|
||||||
cent = &cg_entities[ cg.snap->entities[ i ].number ];
|
cent = &cg_entities[ cg.snap->entities[ i ].number ];
|
||||||
cent->currentValid = qfalse;
|
cent->currentValid = qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
// move nextSnap to snap and do the transitions
|
// move nextSnap to snap and do the transitions
|
||||||
oldFrame = cg.snap;
|
oldFrame = cg.snap;
|
||||||
cg.snap = cg.nextSnap;
|
cg.snap = cg.nextSnap;
|
||||||
|
|
||||||
BG_PlayerStateToEntityState( &cg.snap->ps, &cg_entities[ cg.snap->ps.clientNum ].currentState, qfalse );
|
BG_PlayerStateToEntityState( &cg.snap->ps, &cg_entities[ cg.snap->ps.clientNum ].currentState, qfalse );
|
||||||
cg_entities[ cg.snap->ps.clientNum ].interpolate = qfalse;
|
cg_entities[ cg.snap->ps.clientNum ].interpolate = qfalse;
|
||||||
|
|
||||||
for ( i = 0 ; i < cg.snap->numEntities ; i++ ) {
|
for ( i = 0 ; i < cg.snap->numEntities ; i++ ) {
|
||||||
cent = &cg_entities[ cg.snap->entities[ i ].number ];
|
cent = &cg_entities[ cg.snap->entities[ i ].number ];
|
||||||
CG_TransitionEntity( cent );
|
CG_TransitionEntity( cent );
|
||||||
|
|
||||||
// remember time of snapshot this entity was last updated in
|
// remember time of snapshot this entity was last updated in
|
||||||
cent->snapShotTime = cg.snap->serverTime;
|
cent->snapShotTime = cg.snap->serverTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
cg.nextSnap = NULL;
|
cg.nextSnap = NULL;
|
||||||
|
|
||||||
// check for playerstate transition events
|
// check for playerstate transition events
|
||||||
if ( oldFrame ) {
|
if ( oldFrame ) {
|
||||||
playerState_t *ops, *ps;
|
playerState_t *ops, *ps;
|
||||||
|
|
||||||
ops = &oldFrame->ps;
|
ops = &oldFrame->ps;
|
||||||
ps = &cg.snap->ps;
|
ps = &cg.snap->ps;
|
||||||
// teleporting checks are irrespective of prediction
|
// teleporting checks are irrespective of prediction
|
||||||
if ( ( ps->eFlags ^ ops->eFlags ) & EF_TELEPORT_BIT ) {
|
if ( ( ps->eFlags ^ ops->eFlags ) & EF_TELEPORT_BIT ) {
|
||||||
cg.thisFrameTeleport = qtrue; // will be cleared by prediction code
|
cg.thisFrameTeleport = qtrue; // will be cleared by prediction code
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we are not doing client side movement prediction for any
|
// if we are not doing client side movement prediction for any
|
||||||
// reason, then the client events and view changes will be issued now
|
// reason, then the client events and view changes will be issued now
|
||||||
if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW)
|
if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW)
|
||||||
|| cg_nopredict.integer || cg_synchronousClients.integer ) {
|
|| cg_nopredict.integer || cg_synchronousClients.integer ) {
|
||||||
CG_TransitionPlayerState( ps, ops );
|
CG_TransitionPlayerState( ps, ops );
|
||||||
}
|
}
|
||||||
|
|
||||||
// server demo: detect follow→free camera transition
|
// server demo: detect follow->free camera transition
|
||||||
if ( cg.svDemoPlayback ) {
|
if ( cg.svDemoPlayback ) {
|
||||||
qboolean wasFollowing = ( ops->pm_flags & PMF_FOLLOW ) != 0;
|
qboolean wasFollowing = ( ops->pm_flags & PMF_FOLLOW ) != 0;
|
||||||
qboolean isFollowing = ( ps->pm_flags & PMF_FOLLOW ) != 0;
|
qboolean isFollowing = ( ps->pm_flags & PMF_FOLLOW ) != 0;
|
||||||
if ( wasFollowing && !isFollowing ) {
|
if ( wasFollowing && !isFollowing ) {
|
||||||
// exiting follow mode — init camera from last known position
|
// exiting follow mode -- init camera from last known position
|
||||||
cg.svDemoFreeCamera = qtrue;
|
cg.svDemoFreeCamera = qtrue;
|
||||||
cg.svDemoCameraTime = trap_Milliseconds();
|
cg.svDemoCameraTime = trap_Milliseconds();
|
||||||
VectorCopy( ops->origin, cg.svDemoCameraPs.origin );
|
VectorCopy( ops->origin, cg.svDemoCameraPs.origin );
|
||||||
VectorCopy( ops->viewangles, cg.svDemoCameraPs.viewangles );
|
VectorCopy( ops->viewangles, cg.svDemoCameraPs.viewangles );
|
||||||
cg.svDemoCameraPs.pm_type = PM_SPECTATOR;
|
cg.svDemoCameraPs.pm_type = PM_SPECTATOR;
|
||||||
cg.svDemoCameraPs.speed = 480;
|
cg.svDemoCameraPs.speed = 480;
|
||||||
cg.svDemoCameraPs.clientNum = cg.clientNum;
|
cg.svDemoCameraPs.clientNum = cg.clientNum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===================
|
===================
|
||||||
CG_SetNextSnap
|
CG_SetNextSnap
|
||||||
|
|
||||||
A new snapshot has just been read in from the client system.
|
A new snapshot has just been read in from the client system.
|
||||||
===================
|
===================
|
||||||
*/
|
*/
|
||||||
static void CG_SetNextSnap( snapshot_t *snap ) {
|
static void CG_SetNextSnap( snapshot_t *snap ) {
|
||||||
int num;
|
int num;
|
||||||
entityState_t *es;
|
entityState_t *es;
|
||||||
centity_t *cent;
|
centity_t *cent;
|
||||||
|
|
||||||
cg.nextSnap = snap;
|
cg.nextSnap = snap;
|
||||||
|
|
||||||
// SNAPFLAG_RESET_ENTITIES: invalidate all entities so they are
|
// SNAPFLAG_RESET_ENTITIES: invalidate all entities so they are
|
||||||
// treated as new (no interpolation from old positions).
|
// treated as new (no interpolation from old positions).
|
||||||
// Must happen before the entity loop below.
|
// Must happen before the entity loop below.
|
||||||
if ( snap->snapFlags & SNAPFLAG_RESET_ENTITIES ) {
|
if ( snap->snapFlags & SNAPFLAG_RESET_ENTITIES ) {
|
||||||
for ( num = 0 ; num < MAX_GENTITIES ; num++ ) {
|
for ( num = 0 ; num < MAX_GENTITIES ; num++ ) {
|
||||||
cg_entities[ num ].currentValid = qfalse;
|
cg_entities[ num ].currentValid = qfalse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].nextState, qfalse );
|
BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].nextState, qfalse );
|
||||||
cg_entities[ cg.snap->ps.clientNum ].interpolate = qtrue;
|
cg_entities[ cg.snap->ps.clientNum ].interpolate = qtrue;
|
||||||
|
|
||||||
// check for extrapolation errors
|
// check for extrapolation errors
|
||||||
for ( num = 0 ; num < snap->numEntities ; num++ ) {
|
for ( num = 0 ; num < snap->numEntities ; num++ ) {
|
||||||
es = &snap->entities[num];
|
es = &snap->entities[num];
|
||||||
cent = &cg_entities[ es->number ];
|
cent = &cg_entities[ es->number ];
|
||||||
|
|
||||||
memcpy(¢->nextState, es, sizeof(entityState_t));
|
memcpy(¢->nextState, es, sizeof(entityState_t));
|
||||||
//cent->nextState = *es;
|
//cent->nextState = *es;
|
||||||
|
|
||||||
// if this frame is a teleport, or the entity wasn't in the
|
// if this frame is a teleport, or the entity wasn't in the
|
||||||
// previous frame, don't interpolate
|
// previous frame, don't interpolate
|
||||||
if ( !cent->currentValid || ( ( cent->currentState.eFlags ^ es->eFlags ) & EF_TELEPORT_BIT ) ) {
|
if ( !cent->currentValid || ( ( cent->currentState.eFlags ^ es->eFlags ) & EF_TELEPORT_BIT ) ) {
|
||||||
cent->interpolate = qfalse;
|
cent->interpolate = qfalse;
|
||||||
} else {
|
} else {
|
||||||
cent->interpolate = qtrue;
|
cent->interpolate = qtrue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the next frame is a teleport for the playerstate, we
|
// if the next frame is a teleport for the playerstate, we
|
||||||
// can't interpolate during demos
|
// can't interpolate during demos
|
||||||
if ( cg.snap && ( ( snap->ps.eFlags ^ cg.snap->ps.eFlags ) & EF_TELEPORT_BIT ) ) {
|
if ( cg.snap && ( ( snap->ps.eFlags ^ cg.snap->ps.eFlags ) & EF_TELEPORT_BIT ) ) {
|
||||||
cg.nextFrameTeleport = qtrue;
|
cg.nextFrameTeleport = qtrue;
|
||||||
} else {
|
} else {
|
||||||
cg.nextFrameTeleport = qfalse;
|
cg.nextFrameTeleport = qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if changing follow mode, don't interpolate
|
// if changing follow mode, don't interpolate
|
||||||
if ( cg.nextSnap->ps.clientNum != cg.snap->ps.clientNum ) {
|
if ( cg.nextSnap->ps.clientNum != cg.snap->ps.clientNum ) {
|
||||||
cg.nextFrameTeleport = qtrue;
|
cg.nextFrameTeleport = qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if changing server restarts, don't interpolate
|
// if changing server restarts, don't interpolate
|
||||||
if ( ( cg.nextSnap->snapFlags ^ cg.snap->snapFlags ) & SNAPFLAG_SERVERCOUNT ) {
|
if ( ( cg.nextSnap->snapFlags ^ cg.snap->snapFlags ) & SNAPFLAG_SERVERCOUNT ) {
|
||||||
cg.nextFrameTeleport = qtrue;
|
cg.nextFrameTeleport = qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// entity reset also prevents playerstate interpolation
|
// entity reset also prevents playerstate interpolation
|
||||||
if ( cg.nextSnap->snapFlags & SNAPFLAG_RESET_ENTITIES ) {
|
if ( cg.nextSnap->snapFlags & SNAPFLAG_RESET_ENTITIES ) {
|
||||||
cg.nextFrameTeleport = qtrue;
|
cg.nextFrameTeleport = qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort out solid entities
|
// sort out solid entities
|
||||||
CG_BuildSolidList();
|
CG_BuildSolidList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
========================
|
========================
|
||||||
CG_ReadNextSnapshot
|
CG_ReadNextSnapshot
|
||||||
|
|
||||||
This is the only place new snapshots are requested
|
This is the only place new snapshots are requested
|
||||||
This may increment cgs.processedSnapshotNum multiple
|
This may increment cgs.processedSnapshotNum multiple
|
||||||
times if the client system fails to return a
|
times if the client system fails to return a
|
||||||
valid snapshot.
|
valid snapshot.
|
||||||
========================
|
========================
|
||||||
*/
|
*/
|
||||||
static snapshot_t *CG_ReadNextSnapshot( void ) {
|
static snapshot_t *CG_ReadNextSnapshot( void ) {
|
||||||
qboolean r;
|
qboolean r;
|
||||||
snapshot_t *dest;
|
snapshot_t *dest;
|
||||||
|
|
||||||
if ( cg.latestSnapshotNum > cgs.processedSnapshotNum + 1000 ) {
|
if ( cg.latestSnapshotNum > cgs.processedSnapshotNum + 1000 ) {
|
||||||
CG_Printf( "WARNING: CG_ReadNextSnapshot: way out of range, %i > %i",
|
CG_Printf( "WARNING: CG_ReadNextSnapshot: way out of range, %i > %i",
|
||||||
cg.latestSnapshotNum, cgs.processedSnapshotNum );
|
cg.latestSnapshotNum, cgs.processedSnapshotNum );
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( cgs.processedSnapshotNum < cg.latestSnapshotNum ) {
|
while ( cgs.processedSnapshotNum < cg.latestSnapshotNum ) {
|
||||||
// decide which of the two slots to load it into
|
// decide which of the two slots to load it into
|
||||||
if ( cg.snap == &cg.activeSnapshots[0] ) {
|
if ( cg.snap == &cg.activeSnapshots[0] ) {
|
||||||
dest = &cg.activeSnapshots[1];
|
dest = &cg.activeSnapshots[1];
|
||||||
} else {
|
} else {
|
||||||
dest = &cg.activeSnapshots[0];
|
dest = &cg.activeSnapshots[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to read the snapshot from the client system
|
// try to read the snapshot from the client system
|
||||||
cgs.processedSnapshotNum++;
|
cgs.processedSnapshotNum++;
|
||||||
r = trap_GetSnapshot( cgs.processedSnapshotNum, dest );
|
r = trap_GetSnapshot( cgs.processedSnapshotNum, dest );
|
||||||
|
|
||||||
// FIXME: why would trap_GetSnapshot return a snapshot with the same server time
|
// FIXME: why would trap_GetSnapshot return a snapshot with the same server time
|
||||||
if ( cg.snap && r && dest->serverTime == cg.snap->serverTime ) {
|
if ( cg.snap && r && dest->serverTime == cg.snap->serverTime ) {
|
||||||
//continue;
|
//continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if it succeeded, return
|
// if it succeeded, return
|
||||||
if ( r ) {
|
if ( r ) {
|
||||||
CG_AddLagometerSnapshotInfo( dest );
|
CG_AddLagometerSnapshotInfo( dest );
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// a GetSnapshot will return failure if the snapshot
|
// a GetSnapshot will return failure if the snapshot
|
||||||
// never arrived, or is so old that its entities
|
// never arrived, or is so old that its entities
|
||||||
// have been shoved off the end of the circular
|
// have been shoved off the end of the circular
|
||||||
// buffer in the client system.
|
// buffer in the client system.
|
||||||
|
|
||||||
// record as a dropped packet
|
// record as a dropped packet
|
||||||
CG_AddLagometerSnapshotInfo( NULL );
|
CG_AddLagometerSnapshotInfo( NULL );
|
||||||
|
|
||||||
// If there are additional snapshots, continue trying to
|
// If there are additional snapshots, continue trying to
|
||||||
// read them.
|
// read them.
|
||||||
}
|
}
|
||||||
|
|
||||||
// nothing left to read
|
// nothing left to read
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
============
|
============
|
||||||
CG_ProcessSnapshots
|
CG_ProcessSnapshots
|
||||||
|
|
||||||
We are trying to set up a renderable view, so determine
|
We are trying to set up a renderable view, so determine
|
||||||
what the simulated time is, and try to get snapshots
|
what the simulated time is, and try to get snapshots
|
||||||
both before and after that time if available.
|
both before and after that time if available.
|
||||||
|
|
||||||
If we don't have a valid cg.snap after exiting this function,
|
If we don't have a valid cg.snap after exiting this function,
|
||||||
then a 3D game view cannot be rendered. This should only happen
|
then a 3D game view cannot be rendered. This should only happen
|
||||||
right after the initial connection. After cg.snap has been valid
|
right after the initial connection. After cg.snap has been valid
|
||||||
once, it will never turn invalid.
|
once, it will never turn invalid.
|
||||||
|
|
||||||
Even if cg.snap is valid, cg.nextSnap may not be, if the snapshot
|
Even if cg.snap is valid, cg.nextSnap may not be, if the snapshot
|
||||||
hasn't arrived yet (it becomes an extrapolating situation instead
|
hasn't arrived yet (it becomes an extrapolating situation instead
|
||||||
of an interpolating one)
|
of an interpolating one)
|
||||||
|
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
void CG_ProcessSnapshots( void ) {
|
void CG_ProcessSnapshots( void ) {
|
||||||
snapshot_t *snap;
|
snapshot_t *snap;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
// see what the latest snapshot the client system has is
|
// see what the latest snapshot the client system has is
|
||||||
trap_GetCurrentSnapshotNumber( &n, &cg.latestSnapshotTime );
|
trap_GetCurrentSnapshotNumber( &n, &cg.latestSnapshotTime );
|
||||||
if ( n != cg.latestSnapshotNum ) {
|
if ( n != cg.latestSnapshotNum ) {
|
||||||
if ( n < cg.latestSnapshotNum ) {
|
if ( n < cg.latestSnapshotNum ) {
|
||||||
// this should never happen
|
// this should never happen
|
||||||
CG_Error( "CG_ProcessSnapshots: n < cg.latestSnapshotNum" );
|
CG_Error( "CG_ProcessSnapshots: n < cg.latestSnapshotNum" );
|
||||||
}
|
}
|
||||||
cg.latestSnapshotNum = n;
|
cg.latestSnapshotNum = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have yet to receive a snapshot, check for it.
|
// If we have yet to receive a snapshot, check for it.
|
||||||
// Once we have gotten the first snapshot, cg.snap will
|
// Once we have gotten the first snapshot, cg.snap will
|
||||||
// always have valid data for the rest of the game
|
// always have valid data for the rest of the game
|
||||||
while ( !cg.snap ) {
|
while ( !cg.snap ) {
|
||||||
snap = CG_ReadNextSnapshot();
|
snap = CG_ReadNextSnapshot();
|
||||||
if ( !snap ) {
|
if ( !snap ) {
|
||||||
// we can't continue until we get a snapshot
|
// we can't continue until we get a snapshot
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set our weapon selection to what
|
// set our weapon selection to what
|
||||||
// the playerstate is currently using
|
// the playerstate is currently using
|
||||||
if ( !( snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) {
|
if ( !( snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) {
|
||||||
CG_SetInitialSnapshot( snap );
|
CG_SetInitialSnapshot( snap );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop until we either have a valid nextSnap with a serverTime
|
// loop until we either have a valid nextSnap with a serverTime
|
||||||
// greater than cg.time to interpolate towards, or we run
|
// greater than cg.time to interpolate towards, or we run
|
||||||
// out of available snapshots
|
// out of available snapshots
|
||||||
do {
|
do {
|
||||||
// if we don't have a nextframe, try and read a new one in
|
// if we don't have a nextframe, try and read a new one in
|
||||||
if ( !cg.nextSnap ) {
|
if ( !cg.nextSnap ) {
|
||||||
snap = CG_ReadNextSnapshot();
|
snap = CG_ReadNextSnapshot();
|
||||||
|
|
||||||
// if we still don't have a nextframe, we will just have to
|
// if we still don't have a nextframe, we will just have to
|
||||||
// extrapolate
|
// extrapolate
|
||||||
if ( !snap ) {
|
if ( !snap ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CG_SetNextSnap( snap );
|
CG_SetNextSnap( snap );
|
||||||
|
|
||||||
|
|
||||||
// if time went backwards, we have a level restart or demo seek
|
// if time went backwards, we have a level restart or demo seek
|
||||||
if ( cg.nextSnap->serverTime < cg.snap->serverTime ) {
|
if ( cg.nextSnap->serverTime < cg.snap->serverTime ) {
|
||||||
if ( cg.svDemoPlayback ) {
|
if ( cg.svDemoPlayback ) {
|
||||||
// demo seek — discard old snap, use nextSnap as current,
|
// demo seek -- discard old snap, use nextSnap as current,
|
||||||
// and wait for another snapshot before rendering
|
// and wait for another snapshot before rendering
|
||||||
cg.snap = cg.nextSnap;
|
cg.snap = cg.nextSnap;
|
||||||
cg.nextSnap = NULL;
|
cg.nextSnap = NULL;
|
||||||
cg.time = cg.snap->serverTime;
|
cg.time = cg.snap->serverTime;
|
||||||
// reset all entity state and time-dependent fields
|
// reset all entity state and time-dependent fields
|
||||||
{
|
{
|
||||||
int e;
|
int e;
|
||||||
for ( e = 0; e < MAX_GENTITIES; e++ ) {
|
for ( e = 0; e < MAX_GENTITIES; e++ ) {
|
||||||
cg_entities[e].currentValid = qfalse;
|
cg_entities[e].currentValid = qfalse;
|
||||||
cg_entities[e].interpolate = qfalse;
|
cg_entities[e].interpolate = qfalse;
|
||||||
cg_entities[e].muzzleFlashTime = 0;
|
cg_entities[e].muzzleFlashTime = 0;
|
||||||
cg_entities[e].trailTime = 0;
|
cg_entities[e].trailTime = 0;
|
||||||
cg_entities[e].dustTrailTime = 0;
|
cg_entities[e].dustTrailTime = 0;
|
||||||
cg_entities[e].miscTime = 0;
|
cg_entities[e].miscTime = 0;
|
||||||
cg_entities[e].snapShotTime = 0;
|
cg_entities[e].snapShotTime = 0;
|
||||||
cg_entities[e].previousEvent = 0;
|
cg_entities[e].previousEvent = 0;
|
||||||
cg_entities[e].teleportFlag = 0;
|
cg_entities[e].teleportFlag = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// clear local entities (particles, gibs, etc.)
|
// clear local entities (particles, gibs, etc.)
|
||||||
// they reference old times and would render incorrectly
|
// they reference old times and would render incorrectly
|
||||||
CG_InitLocalEntities();
|
CG_InitLocalEntities();
|
||||||
break; // exit loop, wait for next snapshot
|
break; // exit loop, wait for next snapshot
|
||||||
}
|
}
|
||||||
CG_Error( "CG_ProcessSnapshots: Server time went backwards" );
|
CG_Error( "CG_ProcessSnapshots: Server time went backwards" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if our time is < nextFrame's, we have a nice interpolating state
|
// if our time is < nextFrame's, we have a nice interpolating state
|
||||||
if ( cg.time >= cg.snap->serverTime && cg.time < cg.nextSnap->serverTime ) {
|
if ( cg.time >= cg.snap->serverTime && cg.time < cg.nextSnap->serverTime ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we have passed the transition from nextFrame to frame
|
// we have passed the transition from nextFrame to frame
|
||||||
CG_TransitionSnapshot();
|
CG_TransitionSnapshot();
|
||||||
} while ( 1 );
|
} while ( 1 );
|
||||||
|
|
||||||
// assert our valid conditions upon exiting
|
// assert our valid conditions upon exiting
|
||||||
if ( cg.snap == NULL ) {
|
if ( cg.snap == NULL ) {
|
||||||
CG_Error( "CG_ProcessSnapshots: cg.snap == NULL" );
|
CG_Error( "CG_ProcessSnapshots: cg.snap == NULL" );
|
||||||
}
|
}
|
||||||
if ( cg.time < cg.snap->serverTime ) {
|
if ( cg.time < cg.snap->serverTime ) {
|
||||||
// this can happen right after a vid_restart
|
// this can happen right after a vid_restart
|
||||||
cg.time = cg.snap->serverTime;
|
cg.time = cg.snap->serverTime;
|
||||||
}
|
}
|
||||||
if ( cg.nextSnap != NULL && cg.nextSnap->serverTime <= cg.time ) {
|
if ( cg.nextSnap != NULL && cg.nextSnap->serverTime <= cg.time ) {
|
||||||
CG_Error( "CG_ProcessSnapshots: cg.nextSnap->serverTime <= cg.time" );
|
CG_Error( "CG_ProcessSnapshots: cg.nextSnap->serverTime <= cg.time" );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
2394
code/game/g_active.c
2394
code/game/g_active.c
File diff suppressed because it is too large
Load diff
3852
code/game/g_main.c
3852
code/game/g_main.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,199 +1,199 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
Copyright (C) 1999-2005 Id Software, Inc.
|
Copyright (C) 1999-2005 Id Software, Inc.
|
||||||
|
|
||||||
This file is part of Quake III Arena source code.
|
This file is part of Quake III Arena source code.
|
||||||
|
|
||||||
Quake III Arena source code is free software; you can redistribute it
|
Quake III Arena source code is free software; you can redistribute it
|
||||||
and/or modify it under the terms of the GNU General Public License as
|
and/or modify it under the terms of the GNU General Public License as
|
||||||
published by the Free Software Foundation; either version 2 of the License,
|
published by the Free Software Foundation; either version 2 of the License,
|
||||||
or (at your option) any later version.
|
or (at your option) any later version.
|
||||||
|
|
||||||
Quake III Arena source code is distributed in the hope that it will be
|
Quake III Arena source code is distributed in the hope that it will be
|
||||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Foobar; if not, write to the Free Software
|
along with Foobar; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
===========================================================================
|
===========================================================================
|
||||||
*/
|
*/
|
||||||
//
|
//
|
||||||
#include "g_local.h"
|
#include "g_local.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=======================================================================
|
=======================================================================
|
||||||
|
|
||||||
SESSION DATA
|
SESSION DATA
|
||||||
|
|
||||||
Session data is the only data that stays persistant across level loads
|
Session data is the only data that stays persistant across level loads
|
||||||
and tournament restarts.
|
and tournament restarts.
|
||||||
=======================================================================
|
=======================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
G_WriteClientSessionData
|
G_WriteClientSessionData
|
||||||
|
|
||||||
Called on game shutdown
|
Called on game shutdown
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
void G_WriteClientSessionData( gclient_t *client ) {
|
void G_WriteClientSessionData( gclient_t *client ) {
|
||||||
const char *s;
|
const char *s;
|
||||||
const char *var;
|
const char *var;
|
||||||
|
|
||||||
s = va("%i %i %i %i %i %i %i",
|
s = va("%i %i %i %i %i %i %i",
|
||||||
client->sess.sessionTeam,
|
client->sess.sessionTeam,
|
||||||
client->sess.spectatorTime,
|
client->sess.spectatorTime,
|
||||||
client->sess.spectatorState,
|
client->sess.spectatorState,
|
||||||
client->sess.spectatorClient,
|
client->sess.spectatorClient,
|
||||||
client->sess.wins,
|
client->sess.wins,
|
||||||
client->sess.losses,
|
client->sess.losses,
|
||||||
client->sess.teamLeader
|
client->sess.teamLeader
|
||||||
);
|
);
|
||||||
|
|
||||||
var = va( "session%i", client - level.clients );
|
var = va( "session%i", client - level.clients );
|
||||||
|
|
||||||
trap_Cvar_Set( var, s );
|
trap_Cvar_Set( var, s );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
G_ReadSessionData
|
G_ReadSessionData
|
||||||
|
|
||||||
Called on a reconnect
|
Called on a reconnect
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
void G_ReadSessionData( gclient_t *client ) {
|
void G_ReadSessionData( gclient_t *client ) {
|
||||||
char s[MAX_STRING_CHARS];
|
char s[MAX_STRING_CHARS];
|
||||||
const char *var;
|
const char *var;
|
||||||
|
|
||||||
// bk001205 - format
|
// bk001205 - format
|
||||||
int teamLeader;
|
int teamLeader;
|
||||||
int spectatorState;
|
int spectatorState;
|
||||||
int sessionTeam;
|
int sessionTeam;
|
||||||
|
|
||||||
var = va( "session%i", client - level.clients );
|
var = va( "session%i", client - level.clients );
|
||||||
trap_Cvar_VariableStringBuffer( var, s, sizeof(s) );
|
trap_Cvar_VariableStringBuffer( var, s, sizeof(s) );
|
||||||
|
|
||||||
sscanf( s, "%i %i %i %i %i %i %i",
|
sscanf( s, "%i %i %i %i %i %i %i",
|
||||||
&sessionTeam, // bk010221 - format
|
&sessionTeam, // bk010221 - format
|
||||||
&client->sess.spectatorTime,
|
&client->sess.spectatorTime,
|
||||||
&spectatorState, // bk010221 - format
|
&spectatorState, // bk010221 - format
|
||||||
&client->sess.spectatorClient,
|
&client->sess.spectatorClient,
|
||||||
&client->sess.wins,
|
&client->sess.wins,
|
||||||
&client->sess.losses,
|
&client->sess.losses,
|
||||||
&teamLeader // bk010221 - format
|
&teamLeader // bk010221 - format
|
||||||
);
|
);
|
||||||
|
|
||||||
// bk001205 - format issues
|
// bk001205 - format issues
|
||||||
client->sess.sessionTeam = (team_t)sessionTeam;
|
client->sess.sessionTeam = (team_t)sessionTeam;
|
||||||
client->sess.spectatorState = (spectatorState_t)spectatorState;
|
client->sess.spectatorState = (spectatorState_t)spectatorState;
|
||||||
client->sess.teamLeader = (qboolean)teamLeader;
|
client->sess.teamLeader = (qboolean)teamLeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
G_InitSessionData
|
G_InitSessionData
|
||||||
|
|
||||||
Called on a first-time connect
|
Called on a first-time connect
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
void G_InitSessionData( gclient_t *client, char *userinfo ) {
|
void G_InitSessionData( gclient_t *client, char *userinfo ) {
|
||||||
clientSession_t *sess;
|
clientSession_t *sess;
|
||||||
const char *value;
|
const char *value;
|
||||||
|
|
||||||
sess = &client->sess;
|
sess = &client->sess;
|
||||||
|
|
||||||
// initial team determination
|
// initial team determination
|
||||||
if ( g_gametype.integer >= GT_TEAM ) {
|
if ( g_gametype.integer >= GT_TEAM ) {
|
||||||
if ( g_teamAutoJoin.integer ) {
|
if ( g_teamAutoJoin.integer ) {
|
||||||
sess->sessionTeam = PickTeam( -1 );
|
sess->sessionTeam = PickTeam( -1 );
|
||||||
BroadcastTeamChange( client, -1 );
|
BroadcastTeamChange( client, -1 );
|
||||||
} else {
|
} else {
|
||||||
// always spawn as spectator in team games
|
// always spawn as spectator in team games
|
||||||
sess->sessionTeam = TEAM_SPECTATOR;
|
sess->sessionTeam = TEAM_SPECTATOR;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
value = Info_ValueForKey( userinfo, "team" );
|
value = Info_ValueForKey( userinfo, "team" );
|
||||||
if ( value[0] == 's' ) {
|
if ( value[0] == 's' ) {
|
||||||
// a willing spectator, not a waiting-in-line
|
// a willing spectator, not a waiting-in-line
|
||||||
sess->sessionTeam = TEAM_SPECTATOR;
|
sess->sessionTeam = TEAM_SPECTATOR;
|
||||||
} else {
|
} else {
|
||||||
switch ( g_gametype.integer ) {
|
switch ( g_gametype.integer ) {
|
||||||
default:
|
default:
|
||||||
case GT_FFA:
|
case GT_FFA:
|
||||||
case GT_SINGLE_PLAYER:
|
case GT_SINGLE_PLAYER:
|
||||||
if ( g_maxGameClients.integer > 0 &&
|
if ( g_maxGameClients.integer > 0 &&
|
||||||
level.numNonSpectatorClients >= g_maxGameClients.integer ) {
|
level.numNonSpectatorClients >= g_maxGameClients.integer ) {
|
||||||
sess->sessionTeam = TEAM_SPECTATOR;
|
sess->sessionTeam = TEAM_SPECTATOR;
|
||||||
} else {
|
} else {
|
||||||
sess->sessionTeam = TEAM_FREE;
|
sess->sessionTeam = TEAM_FREE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GT_TOURNAMENT:
|
case GT_TOURNAMENT:
|
||||||
// if the game is full, go into a waiting mode
|
// if the game is full, go into a waiting mode
|
||||||
if ( level.numNonSpectatorClients >= 2 ) {
|
if ( level.numNonSpectatorClients >= 2 ) {
|
||||||
sess->sessionTeam = TEAM_SPECTATOR;
|
sess->sessionTeam = TEAM_SPECTATOR;
|
||||||
} else {
|
} else {
|
||||||
sess->sessionTeam = TEAM_FREE;
|
sess->sessionTeam = TEAM_FREE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sess->spectatorState = SPECTATOR_FREE;
|
sess->spectatorState = SPECTATOR_FREE;
|
||||||
sess->spectatorTime = level.time;
|
sess->spectatorTime = level.time;
|
||||||
|
|
||||||
G_WriteClientSessionData( client );
|
G_WriteClientSessionData( client );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
G_InitWorldSession
|
G_InitWorldSession
|
||||||
|
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void G_InitWorldSession( void ) {
|
void G_InitWorldSession( void ) {
|
||||||
char s[MAX_STRING_CHARS];
|
char s[MAX_STRING_CHARS];
|
||||||
int gt;
|
int gt;
|
||||||
|
|
||||||
trap_Cvar_VariableStringBuffer( "session", s, sizeof(s) );
|
trap_Cvar_VariableStringBuffer( "session", s, sizeof(s) );
|
||||||
gt = atoi( s );
|
gt = atoi( s );
|
||||||
|
|
||||||
// if the gametype changed since the last session, don't use any
|
// if the gametype changed since the last session, don't use any
|
||||||
// client sessions
|
// client sessions
|
||||||
if ( g_gametype.integer != gt ) {
|
if ( g_gametype.integer != gt ) {
|
||||||
level.newSession = qtrue;
|
level.newSession = qtrue;
|
||||||
G_Printf( "Gametype changed, clearing session data.\n" );
|
G_Printf( "Gametype changed, clearing session data.\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
G_WriteSessionData
|
G_WriteSessionData
|
||||||
|
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
void G_WriteSessionData( void ) {
|
void G_WriteSessionData( void ) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// don't persist demo spectator sessions — the forced TEAM_SPECTATOR
|
// don't persist demo spectator sessions -- the forced TEAM_SPECTATOR
|
||||||
// would carry over to the next normal game
|
// would carry over to the next normal game
|
||||||
if ( g_svDemoPlaying.integer ) {
|
if ( g_svDemoPlaying.integer ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trap_Cvar_Set( "session", va("%i", g_gametype.integer) );
|
trap_Cvar_Set( "session", va("%i", g_gametype.integer) );
|
||||||
|
|
||||||
for ( i = 0 ; i < level.maxclients ; i++ ) {
|
for ( i = 0 ; i < level.maxclients ; i++ ) {
|
||||||
if ( level.clients[i].pers.connected == CON_CONNECTED ) {
|
if ( level.clients[i].pers.connected == CON_CONNECTED ) {
|
||||||
G_WriteClientSessionData( &level.clients[i] );
|
G_WriteClientSessionData( &level.clients[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue