示例#1
0
/*
* G_GameTypes_DenyJoinTeam
*/
static int G_GameTypes_DenyJoinTeam( edict_t *ent, int team )
{
	if( team < 0 || team >= GS_MAX_TEAMS )
	{
		G_Printf( "WARNING: 'G_GameTypes_CanJoinTeam' parsing a unrecognized team value\n" );
		return ER_TEAM_INVALID;
	}

	if( team == TEAM_SPECTATOR )
		return ER_TEAM_OK;

	if( GS_MatchState() > MATCH_STATE_PLAYTIME )
		return ER_TEAM_MATCHSTATE;

	// waiting for chanllengers queue to be executed
	if( GS_HasChallengers() &&
		game.realtime < level.spawnedTimeStamp + (unsigned)( G_CHALLENGERS_MIN_JOINTEAM_MAPTIME + game.snapFrameTime ) )
		return ER_TEAM_CHALLENGERS;

	// force eveyone to go through queue so things work on map change
	if( GS_HasChallengers() && !ent->r.client->queueTimeStamp )
		return ER_TEAM_CHALLENGERS;

	//see if team is locked
	if( G_Teams_TeamIsLocked( team ) && !G_Teams_PlayerIsInvited( team, ent ) )
		return ER_TEAM_LOCKED;

	if( GS_TeamBasedGametype() )
	{
		if( team >= TEAM_ALPHA && team < GS_MAX_TEAMS )
		{
			// see if team is full
			int count = teamlist[team].numplayers;

			if( ( count + 1 > level.gametype.maxPlayersPerTeam &&
				level.gametype.maxPlayersPerTeam > 0 ) ||
				( count + 1 > g_teams_maxplayers->integer &&
				g_teams_maxplayers->integer > 0 ) )
				return ER_TEAM_FULL;

			if( !g_teams_allow_uneven->integer && !G_Teams_CanKeepEvenTeam( ent->s.team, team ) )
				return ER_TEAM_UNEVEN;

			return ER_TEAM_OK;
		}
		else
		{
			return ER_TEAM_INVALID;
		}
	}
	else if( team == TEAM_PLAYERS )
	{
		return ER_TEAM_OK;
	}

	return ER_TEAM_INVALID;
}
示例#2
0
/*
* G_Teams_JoinChallengersQueue
*/
void G_Teams_JoinChallengersQueue( edict_t *ent )
{
	int pos = 0;
	edict_t *e;

	if( !GS_HasChallengers() )
	{
		ent->r.client->queueTimeStamp = 0;
		return;
	}

	if( ent->s.team != TEAM_SPECTATOR )
		return;

	// enter the challengers queue
	if( !ent->r.client->queueTimeStamp )
	{                                       // enter the line
		ent->r.client->queueTimeStamp = game.realtime;
		for( e = game.edicts + 1; PLAYERNUM( e ) < gs.maxclients; e++ )
		{
			if( !e->r.inuse || !e->r.client || trap_GetClientState( PLAYERNUM(e) ) < CS_SPAWNED )
				continue;
			if( !e->r.client->queueTimeStamp || e->s.team != TEAM_SPECTATOR )
				continue;
			// if there are other players with the same timestamp, increase ours
			if( e->r.client->queueTimeStamp >= ent->r.client->queueTimeStamp )
				ent->r.client->queueTimeStamp = e->r.client->queueTimeStamp+1;
			if( e->r.client->queueTimeStamp < ent->r.client->queueTimeStamp )
				pos++;
		}

		G_PrintMsg( ent, "%sYou entered the challengers queue in position %i\n", S_COLOR_CYAN, pos+1 );
		G_UpdatePlayerMatchMsg( ent );
	}
}
示例#3
0
/*
* G_Teams_AdvanceChallengersQueue
*/
void G_Teams_AdvanceChallengersQueue( void )
{
	int i, team, loserscount, winnerscount, playerscount = 0;
	int maxscore = 999999;
	edict_t *won, *e;
	int START_TEAM = TEAM_PLAYERS, END_TEAM = TEAM_PLAYERS+1;

	if( !GS_HasChallengers() )
		return;

	G_Teams_UpdateMembersList();

	if( GS_TeamBasedGametype() )
	{
		START_TEAM = TEAM_ALPHA;
		END_TEAM = GS_MAX_TEAMS;
	}

	// assign new timestamps to all the players inside teams
	for( team = START_TEAM; team < END_TEAM; team++ )
	{
		playerscount += teamlist[team].numplayers;
	}

	if( !playerscount )
		return;

	loserscount = 0;
	if( playerscount > 1 )
	{
		loserscount = (int)( playerscount / 2 );
	}
	winnerscount = playerscount - loserscount;

	// put everyone who just played out of the challengers queue
	for( team = START_TEAM; team < END_TEAM; team++ )
	{
		for( i = 0; i < teamlist[team].numplayers; i++ )
		{
			e = game.edicts + teamlist[team].playerIndices[i];
			e->r.client->queueTimeStamp = 0;
		}
	}

	// put (back) the best scoring players in first positions of challengers queue
	for( i = 0; i < winnerscount; i++ )
	{
		won = G_Teams_BestScoreBelow( maxscore );
		if( won )
		{
			maxscore = won->r.client->level.stats.score;
			won->r.client->queueTimeStamp = 1 + ( winnerscount-i ); // never have 2 players with the same timestamp
		}
	}
}
示例#4
0
/*
* G_Teams_ExecuteChallengersQueue
*/
void G_Teams_ExecuteChallengersQueue( void )
{
	edict_t *ent;
	edict_t **challengers;
	bool restartmatch = false;

	// Medar fixme: this is only really makes sense, if playerlimit per team is one
	if( GS_MatchState() == MATCH_STATE_PLAYTIME )
		return;

	if( !GS_HasChallengers() )
		return;

	if( game.realtime < level.spawnedTimeStamp + G_CHALLENGERS_MIN_JOINTEAM_MAPTIME )
	{
		static int time, lasttime;
		time = (int)( ( G_CHALLENGERS_MIN_JOINTEAM_MAPTIME - ( game.realtime - level.spawnedTimeStamp ) )*0.001 );
		if( lasttime && time == lasttime )
			return;
		lasttime = time;
		if( lasttime )
			G_CenterPrintFormatMsg( NULL, "Waiting... %s", va( "%i", lasttime ), NULL );
		else
			G_CenterPrintMsg( NULL, "" );
		return;
	}

	// pick players in join order and try to put them in the
	// game until we get the first refused one.
	challengers = G_Teams_ChallengersQueue();
	if( challengers )
	{
		int i;

		for( i = 0; challengers[i]; i++ )
		{
			ent = challengers[i];
			if( !G_Teams_JoinAnyTeam( ent, true ) )
				break;

			// if we successfully execute the challengers queue during the countdown, revert to warmup
			if( GS_MatchState() == MATCH_STATE_COUNTDOWN )
			{
				restartmatch = true;
			}
		}
	}

	if( restartmatch == true )
	{
		G_Match_Autorecord_Cancel();
		G_Match_LaunchState( MATCH_STATE_WARMUP );
	}
}
示例#5
0
/*
* G_Teams_LeaveChallengersQueue
*/
void G_Teams_LeaveChallengersQueue( edict_t *ent )
{
	if( !GS_HasChallengers() )
	{
		ent->r.client->queueTimeStamp = 0;
		return;
	}

	if( ent->s.team != TEAM_SPECTATOR )
		return;

	// exit the challengers queue
	if( ent->r.client->queueTimeStamp )
	{
		ent->r.client->queueTimeStamp = 0;
		G_PrintMsg( ent, "%sYou left the challengers queue\n", S_COLOR_CYAN );
		G_UpdatePlayerMatchMsg( ent );
	}
}
示例#6
0
/*
* G_Teams_JoinAnyTeam - find us a team since we are too lazy to do ourselves
*/
bool G_Teams_JoinAnyTeam( edict_t *ent, bool silent )
{
	int best_numplayers = gs.maxclients + 1, best_score = 999999;
	int i, team = -1;
	bool wasinqueue = ( ent->r.client->queueTimeStamp != 0 );

	G_Teams_UpdateMembersList(); // make sure we have up-to-date data

	//depending on the gametype, of course
	if( !GS_TeamBasedGametype() )
	{
		if( ent->s.team == TEAM_PLAYERS )
		{
			if( !silent )
			{
				G_PrintMsg( ent, "You are already in %s team\n", GS_TeamName( TEAM_PLAYERS ) );
			}
			return false;
		}
		if( G_Teams_JoinTeam( ent, TEAM_PLAYERS ) )
		{
			if( !silent )
			{
				G_PrintMsg( NULL, "%s%s joined the %s team.\n",
					ent->r.client->netname, S_COLOR_WHITE, GS_TeamName( ent->s.team ) );
			}
		}
		return true;

	}
	else
	{       //team based

		//find the available team with smaller player count or worse score
		for( i = TEAM_ALPHA; i < GS_MAX_TEAMS; i++ )
		{
			if( G_GameTypes_DenyJoinTeam( ent, i ) )
			{
				continue;
			}

			if( team == -1 || teamlist[i].numplayers < best_numplayers
					|| ( teamlist[i].numplayers == best_numplayers && teamlist[i].stats.score < best_score ) )
			{
				best_numplayers = teamlist[i].numplayers;
				best_score = teamlist[i].stats.score;
				team = i;
			}
		}

		if( team == ent->s.team )
		{                   // he is at the right team
			if( !silent )
			{
				G_PrintMsg( ent, "%sCouldn't find a better team than team %s.\n",
					S_COLOR_WHITE, GS_TeamName( ent->s.team ) );
			}
			return false;
		}

		if( team != -1 )
		{
			if( G_Teams_JoinTeam( ent, team ) )
			{
				if( !silent )
				{
					G_PrintMsg( NULL, "%s%s joined the %s team.\n",
						ent->r.client->netname, S_COLOR_WHITE, GS_TeamName( ent->s.team ) );
				}
				return true;
			}
		}
		if( GS_MatchState() <= MATCH_STATE_PLAYTIME && !silent )
			G_Teams_JoinChallengersQueue( ent );
	}

	// don't print message if we joined the queue
	if( !silent && ( !GS_HasChallengers() || wasinqueue || !ent->r.client->queueTimeStamp ) )
		G_PrintMsg( ent, "You can't join the game now\n" );

	return false;
}
示例#7
0
/*
* G_EndFrame_UpdateChaseCam
*/
static void G_EndFrame_UpdateChaseCam( edict_t *ent )
{
	edict_t *targ;
	int followpov;

	// not in chasecam
	if( !ent->r.client->resp.chase.active )
		return;

	if( ( followpov = G_Chase_FindFollowPOV( ent ) ) != -1 )
		ent->r.client->resp.chase.target = followpov;

	// is our chase target gone?
	targ = &game.edicts[ent->r.client->resp.chase.target];

	if( !G_Chase_IsValidTarget( ent, targ, ent->r.client->resp.chase.teamonly ) )
	{
		if( game.realtime < ent->r.client->resp.chase.timeout ) // wait for timeout
			return;

		ent->r.client->resp.chase.timeout = game.realtime + 1500; // update timeout

		G_ChasePlayer( ent, NULL, ent->r.client->resp.chase.teamonly, ent->r.client->resp.chase.followmode );
		targ = &game.edicts[ent->r.client->resp.chase.target];
		if( !G_Chase_IsValidTarget( ent, targ, ent->r.client->resp.chase.teamonly ) )
			return;
	}

	ent->r.client->resp.chase.timeout = game.realtime + 1500; // update timeout

	if( targ == ent )
		return;

	// free our psev buffer when in chasecam
	G_ClearPlayerStateEvents( ent->r.client );

	// copy target playerState to me
	ent->r.client->ps = targ->r.client->ps;

	// fix some stats we don't want copied from the target
	ent->r.client->ps.stats[STAT_REALTEAM] = ent->s.team;
	ent->r.client->ps.stats[STAT_LAYOUTS] &= ~STAT_LAYOUT_SCOREBOARD;
	ent->r.client->ps.stats[STAT_LAYOUTS] &= ~STAT_LAYOUT_CHALLENGER;
	ent->r.client->ps.stats[STAT_LAYOUTS] &= ~STAT_LAYOUT_READY;
	ent->r.client->ps.stats[STAT_LAYOUTS] &= ~STAT_LAYOUT_SPECTEAMONLY;
	ent->r.client->ps.stats[STAT_LAYOUTS] &= ~STAT_LAYOUT_INSTANTRESPAWN;

	if( ent->r.client->resp.chase.teamonly )
	{
		ent->r.client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_SPECTEAMONLY;
		if( !ent->r.client->teamstate.is_coach )
			ent->r.client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_SPECDEAD; // show deadcam effect
	}

	if( ent->r.client->level.showscores || GS_MatchState() >= MATCH_STATE_POSTMATCH )
		ent->r.client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_SCOREBOARD; // show the scoreboard

	if( GS_HasChallengers() && ent->r.client->queueTimeStamp )
		ent->r.client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_CHALLENGER;

	if( GS_MatchState() <= MATCH_STATE_WARMUP && level.ready[PLAYERNUM( ent )] )
		ent->r.client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_READY;

	// chasecam uses PM_CHASECAM
	ent->r.client->ps.pmove.pm_type = PM_CHASECAM;
	ent->r.client->ps.pmove.pm_flags |= PMF_NO_PREDICTION;

	VectorCopy( targ->s.origin, ent->s.origin );
	VectorCopy( targ->s.angles, ent->s.angles );
	GClip_LinkEntity( ent );
}
示例#8
0
/*
* G_SetClientStats
*/
void G_SetClientStats( edict_t *ent )
{
	gclient_t *client = ent->r.client;
	int team, i;

	if( ent->r.client->resp.chase.active )  // in chasecam it copies the other player stats
		return;

	//
	// layouts
	//
	client->ps.stats[STAT_LAYOUTS] = 0;

	// don't force scoreboard when dead during timeout
	if( ent->r.client->level.showscores || GS_MatchState() >= MATCH_STATE_POSTMATCH )
		client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_SCOREBOARD;
	if( GS_TeamBasedGametype() && !GS_InvidualGameType() )
		client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_TEAMTAB;
	if( GS_HasChallengers() && ent->r.client->queueTimeStamp )
		client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_CHALLENGER;
	if( GS_MatchState() <= MATCH_STATE_WARMUP && level.ready[PLAYERNUM( ent )] )
		client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_READY;
	if( G_SpawnQueue_GetSystem( ent->s.team ) == SPAWNSYSTEM_INSTANT )
		client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_INSTANTRESPAWN;

	//
	// team
	//
	client->ps.stats[STAT_TEAM] = client->ps.stats[STAT_REALTEAM] = ent->s.team;

	//
	// health
	//
	if( ent->s.team == TEAM_SPECTATOR )
		client->ps.stats[STAT_HEALTH] = STAT_NOTSET; // no health for spectator
	else
		client->ps.stats[STAT_HEALTH] = HEALTH_TO_INT( ent->health );
	client->r.frags = client->ps.stats[STAT_SCORE];

	//
	// armor
	//
	if( GS_Instagib() )
	{
		if( g_instashield->integer )
			client->ps.stats[STAT_ARMOR] = ARMOR_TO_INT( 100.0f * ( client->resp.instashieldCharge / INSTA_SHIELD_MAX ) );
		else
			client->ps.stats[STAT_ARMOR] = 0;
	}
	else
		client->ps.stats[STAT_ARMOR] = ARMOR_TO_INT( client->resp.armor );

	//
	// pickup message
	//
	if( level.time > client->resp.pickup_msg_time )
	{
		client->ps.stats[STAT_PICKUP_ITEM] = 0;
	}

	//
	// frags
	//
	if( ent->s.team == TEAM_SPECTATOR )
	{
		client->ps.stats[STAT_SCORE] = STAT_NOTSET; // no frags for spectators
	}
	else
	{
		client->ps.stats[STAT_SCORE] = ent->r.client->level.stats.score;
	}

	//
	// Team scores
	//
	if( GS_TeamBasedGametype() )
	{
		// team based
		i = 0;
		for( team = TEAM_ALPHA; team < GS_MAX_TEAMS; team++ )
		{
			client->ps.stats[STAT_TEAM_ALPHA_SCORE+i] = teamlist[team].stats.score;
			i++;
		}
		// mark the rest as not set
		for(; team < GS_MAX_TEAMS; team++ )
		{
			client->ps.stats[STAT_TEAM_ALPHA_SCORE+i] = STAT_NOTSET;
			i++;
		}
	}
	else
	{
		// not team based
		i = 0;
		for( team = TEAM_ALPHA; team < GS_MAX_TEAMS; team++ )
		{
			client->ps.stats[STAT_TEAM_ALPHA_SCORE+i] = STAT_NOTSET;
			i++;
		}
	}

	// spawn system
	client->ps.stats[STAT_NEXT_RESPAWN] = ceil( G_SpawnQueue_NextRespawnTime( client->team ) * 0.001f );

	// pointed player
	client->ps.stats[STAT_POINTED_TEAMPLAYER] = 0;
	client->ps.stats[STAT_POINTED_PLAYER] = G_FindPointedPlayer( ent );
	if( client->ps.stats[STAT_POINTED_PLAYER] && GS_TeamBasedGametype() )
	{
		edict_t	*e = &game.edicts[client->ps.stats[STAT_POINTED_PLAYER]];
		if( e->s.team == ent->s.team )
		{
			int pointedhealth = HEALTH_TO_INT( e->health );
			int pointedarmor = 0;
			int available_bits = 0;
			bool mega = false;

			if( pointedhealth < 0 ) pointedhealth = 0;
			if( pointedhealth > 100 )
			{
				pointedhealth -= 100;
				mega = true;
				if( pointedhealth > 100 )
					pointedhealth = 100;
			}
			pointedhealth /= 3.2;

			if( GS_Armor_TagForCount( e->r.client->resp.armor ) )
			{
				pointedarmor = ARMOR_TO_INT( e->r.client->resp.armor );
			}
			if( pointedarmor > 150 )
			{
				pointedarmor = 150;
			}
			pointedarmor /= 5;

			client->ps.stats[STAT_POINTED_TEAMPLAYER] = ( ( pointedhealth &0x1F )|( pointedarmor&0x3F )<<6|( available_bits&0xF )<<12 );
			if( mega )
			{
				client->ps.stats[STAT_POINTED_TEAMPLAYER] |= 0x20;
			}
		}
	}

	// last killer. ignore world and team kills
	if( client->teamstate.last_killer )
	{
		edict_t *targ = ent, *attacker = client->teamstate.last_killer;
		client->ps.stats[STAT_LAST_KILLER] = (attacker->r.client && !GS_IsTeamDamage( &targ->s, &attacker->s ) ? 
			ENTNUM( attacker ) : 0);
	}
	else
	{
		client->ps.stats[STAT_LAST_KILLER] = 0;
	}
}
示例#9
0
void G_ScoreboardMessage_AddSpectators( void )
{
	char entry[MAX_TOKEN_CHARS];
	int i, clstate;
	edict_t	*e;
	edict_t **challengers;
	size_t len;

	len = strlen( scoreboardString );
	if( !len )
		return;

	if( GS_HasChallengers() && (challengers = G_Teams_ChallengersQueue()) != NULL )
	{
		// add the challengers
		Q_strncpyz( entry, "&w ", sizeof(entry) );
		ADD_SCOREBOARD_ENTRY( scoreboardString, len, entry );

		for( i = 0; challengers[i]; i++ )
		{
			e = challengers[i];

			//spectator tab entry
			if( !( e->r.client->connecting == true || trap_GetClientState( PLAYERNUM( e ) ) < CS_SPAWNED ) )
			{
				Q_snprintfz( entry, sizeof( entry ), "%i %i ",
					PLAYERNUM( e ),
					e->r.client->r.ping > 999 ? 999 : e->r.client->r.ping );
				ADD_SCOREBOARD_ENTRY( scoreboardString, len, entry );
			}
		}
	}

	// add spectator team
	Q_strncpyz( entry, "&s ", sizeof(entry) );
	ADD_SCOREBOARD_ENTRY( scoreboardString, len, entry );

	for( i = 0; i < teamlist[TEAM_SPECTATOR].numplayers; i++ )
	{
		e = game.edicts + teamlist[TEAM_SPECTATOR].playerIndices[i];

		if( e->r.client->connecting == true || trap_GetClientState( PLAYERNUM( e ) ) < CS_SPAWNED )
			continue;

		if( !e->r.client->queueTimeStamp )
		{	
			// not in challenger queue
			Q_snprintfz( entry, sizeof( entry ), "%i %i ",
				PLAYERNUM( e ),
				e->r.client->r.ping > 999 ? 999 : e->r.client->r.ping );
			ADD_SCOREBOARD_ENTRY( scoreboardString, len, entry );
		}
	}

	// add connecting spectators
	for( i = 0; i < teamlist[TEAM_SPECTATOR].numplayers; i++ )
	{
		e = game.edicts + teamlist[TEAM_SPECTATOR].playerIndices[i];

		// spectator tab entry
		clstate = trap_GetClientState( PLAYERNUM( e ) );
		if( e->r.client->connecting == true || ( clstate >= CS_CONNECTED && clstate < CS_SPAWNED ) )
		{
			Q_snprintfz( entry, sizeof( entry ), "%i %i ", PLAYERNUM( e ), -1 );
			ADD_SCOREBOARD_ENTRY( scoreboardString, len, entry );
		}
	}
}