/*
============
CalculateRanks

Recalculates the score ranks of all players
This will be called on every client connect, begin, disconnect, death,
and team change.
============
*/
void CalculateRanks( void ) {
	int		i;
	int		rank;
	int		score;
	int		newScore;
	gclient_t	*cl;

	level.follow1 = -1;
	level.follow2 = -1;
	level.numConnectedClients = 0;
	level.numNonSpectatorClients = 0;
	level.numPlayingClients = 0;
	level.numVotingClients = 0;		// don't count bots

	for (i = 0; i < ARRAY_LEN(level.numteamVotingClients); i++)
		level.numteamVotingClients[i] = 0;

	for ( i = 0 ; i < level.maxclients ; i++ ) {
		if ( level.clients[i].pers.connected != CON_DISCONNECTED ) {
			level.sortedClients[level.numConnectedClients] = i;
			level.numConnectedClients++;

			if ( level.clients[i].sess.sessionTeam != TEAM_SPECTATOR ) {
				level.numNonSpectatorClients++;
			
				// decide if this should be auto-followed
				if ( level.clients[i].pers.connected == CON_CONNECTED ) {
					level.numPlayingClients++;
					if ( !(g_entities[i].r.svFlags & SVF_BOT) ) {
						level.numVotingClients++;
						if ( level.clients[i].sess.sessionTeam == TEAM_RED )
							level.numteamVotingClients[0]++;
						else if ( level.clients[i].sess.sessionTeam == TEAM_BLUE )
							level.numteamVotingClients[1]++;
					}
					if ( level.follow1 == -1 ) {
						level.follow1 = i;
					} else if ( level.follow2 == -1 ) {
						level.follow2 = i;
					}
				}
			}
		}
	}

	qsort( level.sortedClients, level.numConnectedClients, 
		sizeof(level.sortedClients[0]), SortRanks );

	// set the rank value for all clients that are connected and not spectators
	if ( g_gametype.integer >= GT_TEAM ) {
		// in team games, rank is just the order of the teams, 0=red, 1=blue, 2=tied
		for ( i = 0;  i < level.numConnectedClients; i++ ) {
			cl = &level.clients[ level.sortedClients[i] ];
			if ( level.teamScores[TEAM_RED] == level.teamScores[TEAM_BLUE] ) {
				cl->ps.persistant[PERS_RANK] = 2;
			} else if ( level.teamScores[TEAM_RED] > level.teamScores[TEAM_BLUE] ) {
				cl->ps.persistant[PERS_RANK] = 0;
			} else {
				cl->ps.persistant[PERS_RANK] = 1;
			}
		}
	} else {	
		rank = -1;
		score = 0;
		for ( i = 0;  i < level.numPlayingClients; i++ ) {
			cl = &level.clients[ level.sortedClients[i] ];
			newScore = cl->ps.persistant[PERS_SCORE];
			if ( i == 0 || newScore != score ) {
				rank = i;
				// assume we aren't tied until the next client is checked
				level.clients[ level.sortedClients[i] ].ps.persistant[PERS_RANK] = rank;
			} else {
				// we are tied with the previous client
				level.clients[ level.sortedClients[i-1] ].ps.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
				level.clients[ level.sortedClients[i] ].ps.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
			}
			score = newScore;
			if ( g_gametype.integer == GT_SINGLE_PLAYER && level.numPlayingClients == 1 ) {
				level.clients[ level.sortedClients[i] ].ps.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
			}
		}
	}

	// set the CS_SCORES1/2 configstrings, which will be visible to everyone
	if ( g_gametype.integer >= GT_TEAM ) {
		trap_SetConfigstring( CS_SCORES1, va("%i", level.teamScores[TEAM_RED] ) );
		trap_SetConfigstring( CS_SCORES2, va("%i", level.teamScores[TEAM_BLUE] ) );
	} else {
		if ( level.numConnectedClients == 0 ) {
			trap_SetConfigstring( CS_SCORES1, va("%i", SCORE_NOT_PRESENT) );
			trap_SetConfigstring( CS_SCORES2, va("%i", SCORE_NOT_PRESENT) );
		} else if ( level.numConnectedClients == 1 ) {
			trap_SetConfigstring( CS_SCORES1, va("%i", level.clients[ level.sortedClients[0] ].ps.persistant[PERS_SCORE] ) );
			trap_SetConfigstring( CS_SCORES2, va("%i", SCORE_NOT_PRESENT) );
		} else {
			trap_SetConfigstring( CS_SCORES1, va("%i", level.clients[ level.sortedClients[0] ].ps.persistant[PERS_SCORE] ) );
			trap_SetConfigstring( CS_SCORES2, va("%i", level.clients[ level.sortedClients[1] ].ps.persistant[PERS_SCORE] ) );
		}
	}

	// see if it is time to end the level
	CheckExitRules();

	// if we are at the intermission, send the new info to everyone
	if ( level.intermissiontime ) {
		SendScoreboardMessageToAllClients();
	}
}
Exemplo n.º 2
0
/*
============
CalculateRanks

Recalculates the score ranks of all players
This will be called on every client connect, begin, disconnect, death,
and team change.
============
*/
void CalculateRanks()
{
	theLevel.follow1_ = -1;
	theLevel.follow2_ = -1;
	theLevel.numConnectedClients_ = 0;
	theLevel.numNonSpectatorClients_ = 0;
	theLevel.numPlayingClients_ = 0;
	theLevel.numVotingClients_ = 0;		// don't count bots
	for( int i = 0; i < ClientBase::TEAM_NUM_TEAMS; i++ ) 
		theLevel.numteamVotingClients_[i] = 0;

	for( int i = 1 ; i <= theLevel.maxclients_ ; i++ ) 
	{
		GameClient* client = theLevel.getClient(i);
		if( client && client->pers_.connected_ != GameClient::ClientPersistant::CON_DISCONNECTED ) 
		{
			theLevel.sortedClients_[theLevel.numConnectedClients_] = i;
			theLevel.numConnectedClients_++;

			if( client->sess_.sessionTeam_ != ClientBase::TEAM_SPECTATOR ) 
			{
				theLevel.numNonSpectatorClients_++;
			
				// decide if this should be auto-followed
				if ( client->pers_.connected_ == GameClient::ClientPersistant::CON_CONNECTED ) 
				{
					theLevel.numPlayingClients_++;
					if( !(theLevel.getEntity(i)->r.svFlags & SVF_BOT) ) 
					{
						theLevel.numVotingClients_++;
						if( client->sess_.sessionTeam_ == ClientBase::TEAM_RED )
							theLevel.numteamVotingClients_[0]++;
						else if( client->sess_.sessionTeam_ == ClientBase::TEAM_BLUE )
							theLevel.numteamVotingClients_[1]++;
					}
					if( theLevel.follow1_ == -1 ) 
						theLevel.follow1_ = i;
					else if( theLevel.follow2_ == -1 ) 
						theLevel.follow2_ = i;
				}
			}
		}
	}

	qsort( theLevel.sortedClients_, theLevel.numConnectedClients_, 
		sizeof(theLevel.sortedClients_[0]), SortRanks );

	// set the rank value for all clients that are connected and not spectators
	if( g_gametype.integer >= GT_TEAM ) 
	{
		// in team games, rank is just the order of the teams, 0=red, 1=blue, 2=tied
		for ( int i = 0;  i < theLevel.numConnectedClients_; i++ ) 
		{
			GameClient *cl =  theLevel.getClient(theLevel.sortedClients_[i]);
			if( theLevel.teamScores_[ClientBase::TEAM_RED] == theLevel.teamScores_[ClientBase::TEAM_BLUE] ) 
				cl->ps_.persistant[PERS_RANK] = 2;
			else if( theLevel.teamScores_[ClientBase::TEAM_RED] > theLevel.teamScores_[ClientBase::TEAM_BLUE] ) 
				cl->ps_.persistant[PERS_RANK] = 0;
			else
				cl->ps_.persistant[PERS_RANK] = 1;
		}
	} 
	else 
	{	
		int rank = -1;
		int score = 0;
		for( int i = 0;  i < theLevel.numPlayingClients_; i++ ) 
		{
			GameClient *cl = theLevel.getClient(theLevel.sortedClients_[i]);
			int newScore = cl->ps_.persistant[PERS_SCORE];
			if( i == 0 || newScore != score ) 
			{
				rank = i;
				// assume we aren't tied until the next client is checked
				theLevel.getClient(theLevel.sortedClients_[i])->ps_.persistant[PERS_RANK] = rank;
			} 
			else 
			{
				// we are tied with the previous client
				theLevel.getClient(theLevel.sortedClients_[i-1])->ps_.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
				theLevel.getClient(theLevel.sortedClients_[i])->ps_.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
			}
			score = newScore;
			if( g_gametype.integer == GT_SINGLE_PLAYER && theLevel.numPlayingClients_ == 1 ) 
				theLevel.getClient(theLevel.sortedClients_[i])->ps_.persistant[PERS_RANK] = rank | RANK_TIED_FLAG;
		}
	}

	// set the CS_SCORES1/2 configstrings, which will be visible to everyone
	if( g_gametype.integer >= GT_TEAM ) 
	{
		SV_SetConfigstring( CS_SCORES1, va("%i", theLevel.teamScores_[ClientBase::TEAM_RED] ) );
		SV_SetConfigstring( CS_SCORES2, va("%i", theLevel.teamScores_[ClientBase::TEAM_BLUE] ) );
	} 
	else
	{
		if( theLevel.numConnectedClients_ == 0 ) 
		{
			SV_SetConfigstring( CS_SCORES1, va("%i", SCORE_NOT_PRESENT) );
			SV_SetConfigstring( CS_SCORES2, va("%i", SCORE_NOT_PRESENT) );
		}
		else if( theLevel.numConnectedClients_ == 1 ) 
		{
			SV_SetConfigstring( CS_SCORES1, va("%i", theLevel.getClient(theLevel.sortedClients_[0])->ps_.persistant[PERS_SCORE] ) );
			SV_SetConfigstring( CS_SCORES2, va("%i", SCORE_NOT_PRESENT) );
		} 
		else
		{
			SV_SetConfigstring( CS_SCORES1, va("%i", theLevel.getClient(theLevel.sortedClients_[0])->ps_.persistant[PERS_SCORE] ) );
			SV_SetConfigstring( CS_SCORES2, va("%i", theLevel.getClient(theLevel.sortedClients_[1])->ps_.persistant[PERS_SCORE] ) );
		}
	}

	// see if it is time to end the level
	CheckExitRules();

	// if we are at the intermission, send the New info to everyone
	if( theLevel.intermissiontime_ ) 
		SendScoreboardMessageToAllClients();
}
/*
================
G_RunFrame

Advances the non-player objects in the world
================
*/
void G_RunFrame( int levelTime ) {
	int			i;
	gentity_t	*ent;

	// if we are waiting for the level to restart, do nothing
	if ( level.restarted ) {
		return;
	}

	level.framenum++;
	level.previousTime = level.time;
	level.time = levelTime;

	// get any cvar changes
	G_UpdateCvars();

	//
	// go through all allocated objects
	//
	ent = &g_entities[0];
	for (i=0 ; i<level.num_entities ; i++, ent++) {
		if ( !ent->inuse ) {
			continue;
		}

		// clear events that are too old
		if ( level.time - ent->eventTime > EVENT_VALID_MSEC ) {
			if ( ent->s.event ) {
				ent->s.event = 0;	// &= EV_EVENT_BITS;
				if ( ent->client ) {
					ent->client->ps.externalEvent = 0;
					// predicted events should never be set to zero
					//ent->client->ps.events[0] = 0;
					//ent->client->ps.events[1] = 0;
				}
			}
			if ( ent->freeAfterEvent ) {
				// tempEntities or dropped items completely go away after their event
				G_FreeEntity( ent );
				continue;
			} else if ( ent->unlinkAfterEvent ) {
				// items that will respawn will hide themselves after their pickup event
				ent->unlinkAfterEvent = qfalse;
				trap_UnlinkEntity( ent );
			}
		}

		// temporary entities don't think
		if ( ent->freeAfterEvent ) {
			continue;
		}

		if ( !ent->r.linked && ent->neverFree ) {
			continue;
		}

		if ( ent->s.eType == ET_MISSILE ) {
			G_RunMissile( ent );
			continue;
		}

		if ( ent->s.eType == ET_ITEM || ent->physicsObject ) {
			G_RunItem( ent );
			continue;
		}

		if ( ent->s.eType == ET_MOVER ) {
			G_RunMover( ent );
			continue;
		}

		if ( i < MAX_CLIENTS ) {
			G_RunClient( ent );
			continue;
		}

		G_RunThink( ent );
	}

	// perform final fixups on the players
	ent = &g_entities[0];
	for (i=0 ; i < level.maxclients ; i++, ent++ ) {
		if ( ent->inuse ) {
			ClientEndFrame( ent );
		}
	}

	// see if it is time to do a tournement restart
	CheckTournament();

	// see if it is time to end the level
	CheckExitRules();

	// update to team status?
	CheckTeamStatus();

	// cancel vote if timed out
	CheckVote();

	// check team votes
	CheckTeamVote( TEAM_RED );
	CheckTeamVote( TEAM_BLUE );

	// for tracking changes
	CheckCvars();

	if (g_listEntity.integer) {
		for (i = 0; i < MAX_GENTITIES; i++) {
			G_Printf("%4i: %s\n", i, g_entities[i].classname);
		}
		trap_Cvar_Set("g_listEntity", "0");
	}
}
Exemplo n.º 4
0
/*
================
G_RunFrame

Advances the non-player objects in the world
================
*/
void G_RunFrame( int levelTime ) 
{
	int i;
	// if we are waiting for the level to restart, do nothing
	if( theLevel.restarted_ )
		return;

	theLevel.framenum_++;
	theLevel.previousTime_ = theLevel.time_;
	theLevel.time_ = levelTime;
	int msec = theLevel.time_ - theLevel.previousTime_;

	// get any cvar changes
	G_UpdateCvars();

	//
	// go through all allocated objects
	//
	int start = Sys_Milliseconds();
	GameEntity* ent = 0;//&g_entities[0];
	for( i=0 ; i<theLevel.num_entities_ ; i++ )
	{
		ent = theLevel.getEntity(i);
		if( !ent || !ent->inuse_ ) 
			continue;

		// clear events that are too old
		if( theLevel.time_ - ent->eventTime_ > EVENT_VALID_MSEC ) 
		{
			if( ent->s.event ) 
			{
				ent->s.event = 0;	// &= EV_EVENT_BITS;
				if( ent->client_ ) 
				{
					ent->client_->ps_.externalEvent = 0;
					// predicted events should never be set to zero
					//ent->client->ps.events[0] = 0;
					//ent->client->ps.events[1] = 0;
				}
			}
			if( ent->freeAfterEvent_ ) 
			{
				// tempEntities or dropped items completely go away after their event
				ent->freeUp();// former G_FreeEntity
				continue;
			} 
			else if( ent->unlinkAfterEvent_ ) 
			{
				// items that will respawn will hide themselves after their pickup event
				ent->unlinkAfterEvent_ = false;
				SV_UnlinkEntity( ent );
			}
		}
		// temporary entities don't think
		if( ent->freeAfterEvent_ ) 
			continue;

		if( ent->s.eType == ET_MISSILE ||
			 ent->s.eType == ET_BULLET ) 
		{
			G_RunMissile( ent );
			continue;
		}
		if( ent->s.eType == ET_ITEM || ent->physicsObject_ ) 
		{
			G_RunItem( ent );
			continue;
		}
		if( ent->s.eType == ET_MOVER )
		{
			G_RunMover( ent );
			continue;
		}
		if( ent->client_ )
		{
			G_RunClient( ent );
			continue;
		}
		G_RunThink( ent );
	}
	int end = Sys_Milliseconds();

	start = Sys_Milliseconds();
	// perform final fixups on the players
	//ent = &g_entities[0];
	for( i=1 ; i <= theLevel.maxclients_ ; i++ ) 
	{
		ent = theLevel.getEntity(i);
		if( ent && ent->inuse_ ) 
			ClientEndFrame( ent );
	}
	end = Sys_Milliseconds();

	// see if it is time to do a tournement restart
	CheckTournament();

	// see if it is time to end the level
	CheckExitRules();

	// update to team status?
	CheckTeamStatus();

	// cancel vote if timed out
	CheckVote();

	// check team votes
	CheckTeamVote( ClientBase::TEAM_RED );
	CheckTeamVote( ClientBase::TEAM_BLUE );

	// for tracking changes
	CheckCvars();

	if( g_listEntity.integer ) 
	{
		for( i = 0; i < MAX_GENTITIES; i++ )
		{
			ent = theLevel.getEntity(i);
			Com_Printf("%4i: %s\n", i, ent->classname_);
		}
		Cvar_Set("g_listEntity", "0");
	}
}