/*
* G_Match_Ready
*/
void G_Match_Ready( edict_t *ent )
{
	if( ent->r.svflags & SVF_FAKECLIENT && level.ready[PLAYERNUM( ent )] == true )
		return;

	if( ent->s.team == TEAM_SPECTATOR )
	{
		G_PrintMsg( ent, "Join the game first\n" );
		return;
	}

	if( GS_MatchState() != MATCH_STATE_WARMUP )
	{
		if( !( ent->r.svflags & SVF_FAKECLIENT ) )
			G_PrintMsg( ent, "We're not in warmup.\n" );
		return;
	}

	if( level.ready[PLAYERNUM( ent )] )
	{
		G_PrintMsg( ent, "You are already ready.\n" );
		return;
	}

	level.ready[PLAYERNUM( ent )] = true;

	G_PrintMsg( NULL, "%s%s is ready!\n", ent->r.client->netname, S_COLOR_WHITE );

	G_UpdatePlayerMatchMsg( ent );

	G_Match_CheckReadys();
}
Exemple #2
0
/*
* G_EndServerFrames_UpdateChaseCam
*/
void G_EndServerFrames_UpdateChaseCam( void )
{
	int i, team;
	edict_t	*ent;

	// do it by teams, so spectators can copy the chasecam information from players
	for( team = TEAM_PLAYERS; team < GS_MAX_TEAMS; team++ )
	{
		for( i = 0; i < teamlist[team].numplayers; i++ )
		{
			ent = game.edicts + teamlist[team].playerIndices[i];
			if( trap_GetClientState( PLAYERNUM(ent) ) < CS_SPAWNED )
			{
				G_Chase_SetChaseActive( ent, false );
				continue;
			}

			G_EndFrame_UpdateChaseCam( ent );
		}
	}

	// Do spectators last
	team = TEAM_SPECTATOR;
	for( i = 0; i < teamlist[team].numplayers; i++ )
	{
		ent = game.edicts + teamlist[team].playerIndices[i];
		if( trap_GetClientState( PLAYERNUM(ent) ) < CS_SPAWNED )
		{
			G_Chase_SetChaseActive( ent, false );
			continue;
		}

		G_EndFrame_UpdateChaseCam( ent );
	}
}
Exemple #3
0
/*
* TVM_ClientConnect
*/
void TVM_ClientConnect( tvm_relay_t *relay, edict_t *ent, char *userinfo )
{
	edict_t *spec;

	assert( relay );
	assert( ent );
	assert( userinfo );

	// make sure we start with known default
	if( ent->relay->playernum < 0 )
		spec = NULL;
	else
		spec = ent->relay->edicts + ent->relay->playernum + 1;
	ent->local = true;
	ent->relay = relay;
	ent->r.inuse = true;
	ent->r.svflags = SVF_NOCLIENT;
	ent->s.team = spec ? spec->s.team : 0;
	ent->r.client = relay->local_clients + PLAYERNUM( ent );

	memset( ent->r.client, 0, sizeof( *ent->r.client ) );
	ent->r.client->ps.playerNum = PLAYERNUM( ent );
	InitClientPersistant( ent->r.client );

	TVM_ClientUserinfoChanged( relay, ent, userinfo );

	//TVM_Printf( "Connect: %s\n", ent->r.client->pers.netname );

	ent->r.client->pers.connected = true;
	ent->r.client->pers.connecting = true;
}
/*
* G_Match_NotReady
*/
void G_Match_NotReady( edict_t *ent )
{
	if( ent->s.team == TEAM_SPECTATOR )
	{
		G_PrintMsg( ent, "Join the game first\n" );
		return;
	}

	if( GS_MatchState() != MATCH_STATE_WARMUP && GS_MatchState() != MATCH_STATE_COUNTDOWN )
	{
		G_PrintMsg( ent, "A match is not being setup.\n" );
		return;
	}

	if( !level.ready[PLAYERNUM( ent )] )
	{
		G_PrintMsg( ent, "You weren't ready.\n" );
		return;
	}

	level.ready[PLAYERNUM( ent )] = false;

	G_PrintMsg( NULL, "%s%s is no longer ready.\n", ent->r.client->netname, S_COLOR_WHITE );

	G_UpdatePlayerMatchMsg( ent );

	G_Match_CheckReadys();
}
Exemple #5
0
void G_ScoreboardMessage_AddChasers( int entnum, int entnum_self )
{
	char entry[MAX_TOKEN_CHARS];
	int i;
	edict_t *e;
	size_t len;

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

	// add personal spectators
	Q_strncpyz( entry, "&y ", 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( ENTNUM( e ) == entnum_self )
			continue;

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

		if( !e->r.client->resp.chase.active || e->r.client->resp.chase.target != entnum )
			continue;

		Q_snprintfz( entry, sizeof( entry ), "%i ", PLAYERNUM( e ) );
		ADD_SCOREBOARD_ENTRY( scoreboardString, len, entry );
	}
}
Exemple #6
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 );
	}
}
Exemple #7
0
/*
* TVM_ClientUserInfoChanged
* 
* called whenever the player updates a userinfo variable.
* 
* The game can override any of the settings in place
* (forcing skins or names, etc) before copying it off.
*/
void TVM_ClientUserinfoChanged( tvm_relay_t *relay, edict_t *ent, char *userinfo )
{
	gclient_t *cl;
	char *s;

	assert( ent && ent->local && ent->r.client );

	cl = ent->r.client;

	// check for malformed or illegal info strings
	if( !Info_Validate( userinfo ) )
	{
		trap_DropClient( relay, PLAYERNUM( ent ), DROP_TYPE_GENERAL, "Error: Invalid userinfo" );
		return;
	}

	if( !Info_ValueForKey( userinfo, "name" ) )
	{
		trap_DropClient( relay, PLAYERNUM( ent ), DROP_TYPE_GENERAL, "Error: No name set" );
		return;
	}

	// set name, it's validated and possibly changed first
	Q_strncpyz( cl->pers.netname, Info_ValueForKey( userinfo, "name" ), sizeof( cl->pers.netname ) );

	// fov
	s = Info_ValueForKey( userinfo, "fov" );
	if( !s )
	{
		cl->pers.fov = 100;
	}
	else
	{
		cl->pers.fov = atoi( s );
		clamp( cl->pers.fov, 1, 140 );
	}

	s = Info_ValueForKey( userinfo, "zoomfov" );
	if( !s )
	{
		cl->pers.zoomfov = 30;
	}
	else
	{
		cl->pers.zoomfov = atoi( s );
		clamp( cl->pers.zoomfov, 1, 60 );
	}

	// save off the userinfo in case we want to check something later
	Q_strncpyz( cl->pers.userinfo, userinfo, sizeof( cl->pers.userinfo ) );
}
Exemple #8
0
/*
* TVM_Cmd_PlayersExt_f
*/
static void TVM_Cmd_PlayersExt_f( edict_t *ent, bool onlyspecs ) {
	int i;
	int count = 0;
	int start = 0;
	char line[64];
	char msg[1024];
	edict_t *e;
	tvm_relay_t *relay = ent->relay;

	if( trap_Cmd_Argc() > 1 ) {
		start = atoi( trap_Cmd_Argv( 1 ) );
	}
	clamp( start, 0, relay->maxclients - 1 );

	// print information
	msg[0] = 0;

	for( i = start + 1; PLAYERNUM( ( relay->edicts + i ) ) < relay->maxclients; i++ ) {
		e = relay->edicts + i;
		if( e->r.inuse && !e->local && e->r.client ) {
			char *userinfo;

			userinfo = relay->configStrings[CS_PLAYERINFOS + PLAYERNUM( e )];
			Q_snprintfz( line, sizeof( line ), "%3i %s\n", i, Info_ValueForKey( userinfo, "name" ) );

			if( strlen( line ) + strlen( msg ) > sizeof( msg ) - 100 ) {
				// can't print all of them in one packet
				Q_strncatz( msg, "...\n", sizeof( msg ) );
				break;
			}

			if( count == 0 ) {
				Q_strncatz( msg, "num name\n", sizeof( msg ) );
				Q_strncatz( msg, "--- ---------------\n", sizeof( msg ) );
			}

			Q_strncatz( msg, line, sizeof( msg ) );
			count++;
		}
	}

	if( count ) {
		Q_strncatz( msg, "--- ---------------\n", sizeof( msg ) );
	}
	Q_strncatz( msg, va( "%3i %s\n", count, trap_Cmd_Argv( 0 ) ), sizeof( msg ) );
	TVM_PrintMsg( relay, ent, "%s", msg );

	if( i < relay->maxclients ) {
		TVM_PrintMsg( relay, ent, "Type '%s %i' for more %s\n", trap_Cmd_Argv( 0 ), i, trap_Cmd_Argv( 0 ) );
	}
}
char *G_Gametype_GENERIC_ScoreboardMessage( void )
{
	char entry[MAX_TOKEN_CHARS];
	size_t len;
	int i;
	edict_t	*e;
	int carrierIcon;

	*scoreboardString = 0;
	len = 0;

	Q_snprintfz( entry, sizeof(entry), "&t %i 0 0 ", TEAM_PLAYERS );
	if( SCOREBOARD_MSG_MAXSIZE - len > strlen( entry ) )
	{
		Q_strncatz( scoreboardString, entry, sizeof( scoreboardString ) );
		len = strlen( scoreboardString );
	}

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

		if( e->s.effects & EF_CARRIER )
			carrierIcon = trap_ImageIndex( ( e->s.team == TEAM_BETA ) ? PATH_ALPHAFLAG_ICON : PATH_BETAFLAG_ICON );
		else if( e->s.effects & EF_QUAD )
			carrierIcon = trap_ImageIndex( PATH_QUAD_ICON );
		else if( e->s.effects & EF_SHELL )
			carrierIcon = trap_ImageIndex( PATH_SHELL_ICON );
		else if( e->s.effects & EF_REGEN )
			carrierIcon = trap_ImageIndex( PATH_REGEN_ICON );
		else
			carrierIcon = 0;

		Q_snprintfz( entry, sizeof( entry ), "&p %i %i %i %i %i ",
			PLAYERNUM( e ),
			e->r.client->level.stats.score,
			e->r.client->r.ping > 999 ? 999 : e->r.client->r.ping,
			carrierIcon,
			( level.ready[PLAYERNUM( e )] || GS_MatchState() >= MATCH_STATE_PLAYTIME ) ? trap_ImageIndex( PATH_VSAY_YES_ICON ) : 0
			);

		if( SCOREBOARD_MSG_MAXSIZE - len > strlen( entry ) )
		{
			Q_strncatz( scoreboardString, entry, sizeof( scoreboardString ) );
			len = strlen( scoreboardString );
		}
	}

	return scoreboardString;
}
Exemple #10
0
//==========================================
// AITools_Frame
// Gives think time to the debug tools found
// in this archive (those witch need it)
//==========================================
void AITools_Frame( void )
{
	edict_t *ent;
	for( ent = game.edicts + 1; PLAYERNUM( ent ) < gs.maxclients; ent++ )
	{
		if( !ent->r.inuse )
			continue;
		if( trap_GetClientState( PLAYERNUM( ent ) ) < CS_SPAWNED )
			continue;

		AITools_DropNodes( ent );
		AITools_ShowPlinks( ent );
	}
}
Exemple #11
0
/*
* ClientDisconnect
* Called when a player drops from the server.
* Will not be called between levels.
*/
void ClientDisconnect( edict_t *ent, const char *reason )
{
	int team;

	if( !ent->r.client || !ent->r.inuse )
		return;

	// always report in RACE mode
	if( GS_RaceGametype() 
		|| ( ent->r.client->team != TEAM_SPECTATOR && ( GS_MatchState() == MATCH_STATE_PLAYTIME || GS_MatchState() == MATCH_STATE_POSTMATCH ) ) )
		G_AddPlayerReport( ent, GS_MatchState() == MATCH_STATE_POSTMATCH );

	for( team = TEAM_PLAYERS; team < GS_MAX_TEAMS; team++ )
		G_Teams_UnInvitePlayer( team, ent );

	if( !level.gametype.disableObituaries || !(ent->r.svflags & SVF_FAKECLIENT ) )
	{
		if( !reason )
			G_PrintMsg( NULL, "%s" S_COLOR_WHITE " disconnected\n", ent->r.client->netname );
		else
			G_PrintMsg( NULL, "%s" S_COLOR_WHITE " disconnected (%s" S_COLOR_WHITE ")\n", ent->r.client->netname, reason );
	}

	// send effect
	if( ent->s.team > TEAM_SPECTATOR )
		G_TeleportEffect( ent, false );

	ent->r.client->team = TEAM_SPECTATOR;
	G_ClientRespawn( ent, true ); // respawn as ghost
	ent->movetype = MOVETYPE_NOCLIP; // allow freefly

	// let the gametype scripts know this client just disconnected
	G_Gametype_ScoreEvent( ent->r.client, "disconnect", NULL );

	G_FreeAI( ent );
	AI_EnemyRemoved( ent );

	ent->r.inuse = false;
	ent->r.svflags = SVF_NOCLIENT;

	memset( ent->r.client, 0, sizeof( *ent->r.client ) );
	ent->r.client->ps.playerNum = PLAYERNUM( ent );

	trap_ConfigString( CS_PLAYERINFOS+PLAYERNUM( ent ), "" );
	GClip_UnlinkEntity( ent );

	G_Match_CheckReadys();
}
Exemple #12
0
void G_PlayerAward( edict_t *ent, const char *awardMsg )
{
	edict_t *other;
	char cmd[MAX_STRING_CHARS];
	gameaward_t *ga;
	int i, size;
	score_stats_t *stats;

	if( !awardMsg || !awardMsg[0] || !ent->r.client )
		return;

	Q_snprintfz( cmd, sizeof( cmd ), "aw \"%s\"", awardMsg );
	trap_GameCmd( ent, cmd );

	if( dedicated->integer )
		G_Printf( "%s", COM_RemoveColorTokens( va( "%s receives a '%s' award.\n", ent->r.client->netname, awardMsg ) ) );

	ent->r.client->level.stats.awards++;
	teamlist[ent->s.team].stats.awards++;
	G_Gametype_ScoreEvent( ent->r.client, "award", awardMsg );

	stats = &ent->r.client->level.stats;
	if( !stats->awardAllocator )
		stats->awardAllocator = LinearAllocator( sizeof( gameaward_t ), 0, _G_LevelMalloc, _G_LevelFree );

	// ch : this doesnt work for race right?
	if( GS_MatchState() == MATCH_STATE_PLAYTIME || GS_MatchState() == MATCH_STATE_POSTMATCH )
	{
		// ch : we store this locally to send to MM
		// first check if we already have this one on the clients list
		size = LA_Size( stats->awardAllocator );
		ga = NULL;
		for( i = 0; i < size; i++ )
		{
			ga = ( gameaward_t * )LA_Pointer( stats->awardAllocator, i );
			if( !strncmp( ga->name, awardMsg, sizeof(ga->name)-1 ) )
				break;
		}

		if( i >= size )
		{
			ga = ( gameaward_t * )LA_Alloc( stats->awardAllocator );
			memset( ga, 0, sizeof(*ga) );
			ga->name = G_RegisterLevelString( awardMsg );
		}

		if( ga )
			ga->count++;
	}

	// add it to every player who's chasing this player
	for( other = game.edicts + 1; PLAYERNUM( other ) < gs.maxclients; other++ )
	{
		if( !other->r.client || !other->r.inuse || !other->r.client->resp.chase.active )
			continue;

		if( other->r.client->resp.chase.target == ENTNUM( ent ) )
			trap_GameCmd( other, cmd );
	}
}
Exemple #13
0
/*
* G_Chase_IsValidTarget
*/
static bool G_Chase_IsValidTarget( edict_t *ent, edict_t *target, bool teamonly ) {
	if( !ent || !target ) {
		return false;
	}

	if( !target->r.inuse || !target->r.client || trap_GetClientState( PLAYERNUM( target ) ) < CS_SPAWNED ) {
		return false;
	}

	if( target->s.team < TEAM_PLAYERS || target->s.team >= GS_MAX_TEAMS || target == ent ) {
		return false;
	}

	if( teamonly && !ent->r.client->teamstate.is_coach && G_ISGHOSTING( target ) ) {
		return false;
	}

	if( teamonly && target->s.team != ent->s.team ) {
		return false;
	}

	if( G_ISGHOSTING( target ) && !target->deadflag && target->s.team != TEAM_SPECTATOR ) {
		return false; // ghosts that are neither dead, nor speccing (probably originating from gt-specific rules)

	}
	return true;
}
Exemple #14
0
/*
* G_Teams_Invite_f
*/
void G_Teams_Invite_f( edict_t *ent )
{
	char *text;
	edict_t *toinvite;
	int team;

	if( ( !ent->r.inuse || !ent->r.client ) )
		return;

	text = trap_Cmd_Argv( 1 );

	if( !text || !strlen( text ) )
	{
		int i;
		edict_t *e;
		char msg[1024];

		msg[0] = 0;
		Q_strncatz( msg, "Usage: invite <player>\n", sizeof( msg ) );
		Q_strncatz( msg, "- List of current players:\n", sizeof( msg ) );

		for( i = 0, e = game.edicts+1; i < gs.maxclients; i++, e++ )
		{
			if( !e->r.inuse ) 
				continue;

			Q_strncatz( msg, va( "%3i: %s\n", PLAYERNUM( e ), e->r.client->netname ), sizeof( msg ) );
		}

		G_PrintMsg( ent, "%s", msg );
		return;
	}

	team = ent->s.team;

	if( !G_Teams_TeamIsLocked( team ) )
	{
		G_PrintMsg( ent, "Your team is not locked.\n" );
		return;
	}

	toinvite = G_PlayerForText( text );

	if( !toinvite )
	{
		G_PrintMsg( ent, "No such player.\n" );
		return;
	}

	if( G_Teams_PlayerIsInvited( team, toinvite ) )
	{
		G_PrintMsg( ent, "%s%s is already invited to your team.\n", toinvite->r.client->netname, S_COLOR_WHITE );
		return;
	}

	G_Teams_InvitePlayer( team, toinvite );

	G_PrintMsg( NULL, "%s%s invited %s%s to team %s%s.\n", ent->r.client->netname, S_COLOR_WHITE,
		toinvite->r.client->netname, S_COLOR_WHITE, GS_TeamName( team ), S_COLOR_WHITE );
}
/*
* G_Match_ScorelimitHit
*/
bool G_Match_ScorelimitHit( void )
{
	edict_t	*e;

	if( GS_MatchState() != MATCH_STATE_PLAYTIME )
		return false;

	if( g_scorelimit->integer )
	{
		if( !GS_TeamBasedGametype() )
		{
			for( e = game.edicts+1; PLAYERNUM( e ) < gs.maxclients; e++ )
			{
				if( !e->r.inuse )
					continue;

				if( e->r.client->level.stats.score >= g_scorelimit->integer )
					return true;
			}
		}
		else
		{
			int team;

			for( team = TEAM_ALPHA; team < GS_MAX_TEAMS; team++ )
			{
				if( teamlist[team].stats.score >= g_scorelimit->integer )
					return true;
			}
		}
	}

	return false;
}
/*
* G_Match_ToggleReady
*/
void G_Match_ToggleReady( edict_t *ent )
{
	if( !level.ready[PLAYERNUM( ent )] )
		G_Match_Ready( ent );
	else
		G_Match_NotReady( ent );
}
Exemple #17
0
/*
* AI_InitEntitiesData
*/
void AI_InitEntitiesData( void )
{
	int newlinks, newjumplinks;
	edict_t *ent;

	if( !nav.num_nodes )
	{
		if( g_numbots->integer ) trap_Cvar_Set( "g_numbots", "0" );
		return;
	}

	// create nodes for navigable map entities ( must happen after finding teams )
	for( ent = game.edicts + 1 + gs.maxclients; ENTNUM( ent ) < game.numentities; ent++ )
		AI_AddNavigableEntity( ent );

	// add all clients to goalEntities so they can be tracked as enemies
	for( ent = game.edicts + 1; PLAYERNUM( ent ) < gs.maxclients; ent++ )
		AI_AddGoalEntity( ent );

	// link all newly added nodes
	newlinks = AI_LinkServerNodes( nav.serverNodesStart );
	newjumplinks = AI_LinkCloseNodes_JumpPass( nav.serverNodesStart );

	if( developer->integer )
	{
		G_Printf( "       : added nodes:%i.\n", nav.num_nodes - nav.serverNodesStart );
		G_Printf( "       : total nodes:%i.\n", nav.num_nodes );
		G_Printf( "       : added links:%i.\n", newlinks );
		G_Printf( "       : added jump links:%i.\n", newjumplinks );
	}

	G_Printf( "       : AI Navigation Initialized.\n" );

	nav.loaded = qtrue;
}
Exemple #18
0
/*
* ClientCommand
*/
void ClientCommand( edict_t *ent )
{
	char *cmd;
	int i;

	if( !ent->r.client || trap_GetClientState( PLAYERNUM( ent ) ) < CS_SPAWNED )
		return; // not fully in game yet

	cmd = trap_Cmd_Argv( 0 );

	if( Q_stricmp( cmd, "cvarinfo" ) ) // skip cvarinfo cmds because they are automatic responses
		G_Client_UpdateActivity( ent->r.client ); // activity detected

	for( i = 0; i < MAX_GAMECOMMANDS; i++ )
	{
		if( !g_Commands[i].name[0] )
			break;

		if( !Q_stricmp( g_Commands[i].name, cmd ) )
		{
			if( g_Commands[i].func )
				g_Commands[i].func( ent );
			else
				GT_asCallGameCommand( ent->r.client, cmd, trap_Cmd_Args(), trap_Cmd_Argc() - 1 );
			return;
		}
	}

	G_PrintMsg( ent, "Bad user command: %s\n", cmd );
}
Exemple #19
0
/*
* G_Teams_InitLevel
*/
void G_Teams_Init( void )
{
	edict_t	*ent;

	// set the team names with default ones
	trap_ConfigString( CS_TEAM_SPECTATOR_NAME, GS_DefaultTeamName( TEAM_SPECTATOR ) );
	trap_ConfigString( CS_TEAM_PLAYERS_NAME, GS_DefaultTeamName( TEAM_PLAYERS ) );
	trap_ConfigString( CS_TEAM_ALPHA_NAME, GS_DefaultTeamName( TEAM_ALPHA ) );
	trap_ConfigString( CS_TEAM_BETA_NAME, GS_DefaultTeamName( TEAM_BETA ) );

	g_teams_maxplayers = trap_Cvar_Get( "g_teams_maxplayers", "0", CVAR_ARCHIVE );
	g_teams_allow_uneven = trap_Cvar_Get( "g_teams_allow_uneven", "1", CVAR_ARCHIVE );

	//unlock all teams and clear up team lists
	memset( teamlist, 0, sizeof( teamlist ) );

	for( ent = game.edicts + 1; PLAYERNUM( ent ) < gs.maxclients; ent++ )
	{
		if( ent->r.inuse )
		{
			memset( &ent->r.client->teamstate, 0, sizeof( ent->r.client->teamstate ) );
			memset( &ent->r.client->resp, 0, sizeof( ent->r.client->resp ) );
			ent->s.team = ent->r.client->team = TEAM_SPECTATOR;
			G_GhostClient( ent );
			ent->movetype = MOVETYPE_NOCLIP; // allow freefly
			ent->r.client->teamstate.timeStamp = level.time;
			ent->r.client->resp.timeStamp = level.time;
		}
	}

}
Exemple #20
0
/*
* G_Teams_SetTeam - sets clients team without any checking
*/
void G_Teams_SetTeam( edict_t *ent, int team )
{
	assert( ent && ent->r.inuse && ent->r.client );
	assert( team >= TEAM_SPECTATOR && team < GS_MAX_TEAMS );

	// if player was on a team, send partial report to matchmaker
	if( ent->r.client->team != TEAM_SPECTATOR && ent->r.client->team != team && GS_MatchState() == MATCH_STATE_PLAYTIME )
	{
		G_Printf("Sending teamchange to MM, team %d to team %d\n", ent->r.client->team, team );
		G_AddPlayerReport( ent, false );
		// trap_MR_SendPartialReport();
	}

	// clear scores at changing team
	memset( &ent->r.client->level.stats, 0, sizeof( ent->r.client->level.stats ) );

	memset( &ent->r.client->teamstate, 0, sizeof( ent->r.client->teamstate ) );
	ent->r.client->team = team;
	ent->r.client->teamstate.timeStamp = level.time;
	G_Teams_UnInvitePlayer( team, ent );

	G_ClientRespawn( ent, true ); // make ghost using G_ClientRespawn so team is updated at ghosting
	G_SpawnQueue_AddClient( ent );

	level.ready[PLAYERNUM( ent )] = false;

	G_Match_CheckReadys();
	G_UpdatePlayerMatchMsg( ent );
}
Exemple #21
0
/*
* TVM_ClientBegin
* 
* called when a client has finished connecting, and is ready
* to be placed into the game. This will happen every level load.
*/
void TVM_ClientBegin( tvm_relay_t *relay, edict_t *ent )
{
	edict_t *spot, *other;
	int i, specs;
	char hostname[MAX_CONFIGSTRING_CHARS];

	assert( ent && ent->local && ent->r.client );

	//TVM_Printf( "Begin: %s\n", ent->r.client->pers.netname );

	ent->r.client->pers.connecting = false;

	spot = TVM_SelectSpawnPoint( ent );
	if( spot )
	{
		VectorCopy( spot->s.origin, ent->s.origin );
		VectorCopy( spot->s.origin, ent->s.old_origin );
		VectorCopy( spot->s.angles, ent->s.angles );
		VectorCopy( spot->s.origin, ent->r.client->ps.pmove.origin );
		VectorCopy( spot->s.angles, ent->r.client->ps.viewangles );
	}
	else
	{
		VectorClear( ent->s.origin );
		VectorClear( ent->s.old_origin );
		VectorClear( ent->s.angles );
		VectorClear( ent->r.client->ps.pmove.origin );
		VectorClear( ent->r.client->ps.viewangles );
	}

	ent->s.teleported = true;
	// set the delta angle
	for( i = 0; i < 3; i++ )
		ent->r.client->ps.pmove.delta_angles[i] = ANGLE2SHORT( ent->s.angles[i] ) - ent->r.client->pers.cmd_angles[i];

	specs = 0;
	for( i = 0; i < relay->local_maxclients; i++ )
	{
		other = relay->local_edicts + i;
		if( other == ent )
			continue;
		if( !other->r.inuse || !other->r.client )
			continue;
		if( trap_GetClientState( relay, PLAYERNUM( other ) ) != CS_SPAWNED )
			continue;
		specs++;
	}

	Q_strncpyz( hostname, relay->configStrings[CS_HOSTNAME], sizeof( hostname ) );
	TVM_PrintMsg( relay, ent, S_COLOR_ORANGE "Welcome to %s! There %s currently %i spectator%s on this channel.\n",
		COM_RemoveColorTokens( hostname ), (specs == 1 ? "is" : "are"), specs, (specs == 1 ? "" : "s") );

	TVM_PrintMsg( relay, ent, S_COLOR_ORANGE "For more information about chase camera modes type 'chase help' at console.\n" );

	if( ent->r.client->chase.active )
		TVM_ChaseClientEndSnapFrame( ent );
	else
		TVM_ClientEndSnapFrame( ent );
}
void G_Gametype_GENERIC_SetUpEndMatch( void )
{
	edict_t *ent;

	level.gametype.readyAnnouncementEnabled = false;
	level.gametype.scoreAnnouncementEnabled = false;
	level.gametype.pickableItemsMask = 0; // disallow item pickup
	level.gametype.countdownEnabled = false;

	for( ent = game.edicts + 1; PLAYERNUM( ent ) < gs.maxclients; ent++ )
	{
		if( ent->r.inuse && trap_GetClientState( PLAYERNUM( ent ) ) >= CS_SPAWNED )
			G_ClientRespawn( ent, true );
	}

	G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_POSTMATCH_GAMEOVER_1_to_2, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, true, NULL );
}
Exemple #23
0
/*
* G_ClientEndSnapFrame
* 
* Called for each player at the end of the server frame
* and right after spawning
*/
void G_ClientEndSnapFrame( edict_t *ent )
{
	gclient_t *client;
	int i;

	if( trap_GetClientState( PLAYERNUM( ent ) ) < CS_SPAWNED )
		return;

	client = ent->r.client;

	// set fov
	if( !client->ps.pmove.stats[PM_STAT_ZOOMTIME] )
		client->ps.fov = ent->r.client->fov;
	else
	{
		float frac = (float)client->ps.pmove.stats[PM_STAT_ZOOMTIME] / (float)ZOOMTIME;
		client->ps.fov = client->fov - ( (float)( client->fov - client->zoomfov ) * frac );
	}

	// If the end of unit layout is displayed, don't give
	// the player any normal movement attributes
	if( GS_MatchState() >= MATCH_STATE_POSTMATCH )
	{
		G_SetClientStats( ent );
	}
	else
	{
		if( G_IsDead( ent ) && !level.gametype.customDeadBodyCam )
		{
			G_Client_DeadView( ent );
		}

		G_PlayerWorldEffects( ent ); // burn from lava, etc
		G_ClientDamageFeedback( ent ); // show damage taken along the snap
		G_SetClientStats( ent );
		G_SetClientEffects( ent );
		G_SetClientSound( ent );
		G_SetClientFrame( ent );

		client->ps.plrkeys = client->resp.snap.plrkeys;
	}

	G_ReleaseClientPSEvent( client );

	// set the delta angle
	for( i = 0; i < 3; i++ )
		client->ps.pmove.delta_angles[i] = ANGLE2SHORT( client->ps.viewangles[i] ) - client->ucmd.angles[i];

	// this is pretty hackish. We exploit the fact that servers *do not* transmit
	// origin2/old_origin for ET_PLAYER/ET_CORPSE entities, and we use it for sending the player velocity
	if( !G_ISGHOSTING( ent ) )
	{
		ent->r.svflags |= SVF_TRANSMITORIGIN2;
		VectorCopy( ent->velocity, ent->s.origin2 );
	}
	else
		ent->r.svflags &= ~SVF_TRANSMITORIGIN2;
}
/*
* G_CheckNumBots
*/
static void G_CheckNumBots( void )
{
	edict_t	*ent;
	int desiredNumBots;

	if( level.spawnedTimeStamp + 5000 > game.realtime )
		return;

	// check sanity of g_numbots
	if( g_numbots->integer < 0 )
		trap_Cvar_Set( "g_numbots", "0" );

	if( g_numbots->integer > gs.maxclients )
		trap_Cvar_Set( "g_numbots", va( "%i", gs.maxclients ) );

	if( level.gametype.numBots > gs.maxclients )
		level.gametype.numBots = gs.maxclients;

	desiredNumBots = level.gametype.numBots ? level.gametype.numBots : g_numbots->integer;

	if( desiredNumBots < game.numBots )
	{
		// kick one bot
		for( ent = game.edicts + gs.maxclients; PLAYERNUM( ent ) >= 0; ent-- )
		{
			if( !ent->r.inuse || !( ent->r.svflags & SVF_FAKECLIENT ) )
				continue;
			if( AI_GetType( ent->ai ) == AI_ISBOT )
			{
				trap_DropClient( ent, DROP_TYPE_GENERAL, NULL );
				break;
			}
		}
		return;
	}

	if( desiredNumBots > game.numBots )
	{                                     // add a bot if there is room
		for( ent = game.edicts + 1; PLAYERNUM( ent ) < gs.maxclients && game.numBots < desiredNumBots; ent++ )
		{
			if( !ent->r.inuse && trap_GetClientState( PLAYERNUM( ent ) ) == CS_FREE )
				BOT_SpawnBot( NULL );
		}
	}
}
Exemple #25
0
void G_AwardPlayerMissedLasergun( edict_t *self, int mod )
{
    int i;
    if( mod == MOD_LASERGUN_W || mod == MOD_LASERGUN_S )
    {
        for( i = 0; i < gs.maxclients; i++ )  // cancelling lasergun combo award
            game.clients[i].resp.awardInfo.combo[PLAYERNUM( self )] &= ~COMBO_FLAG( WEAP_LASERGUN );
    }
}
Exemple #26
0
/*
* G_ClearSnap
* We just run G_SnapFrame, the server just sent the snap to the clients,
* it's now time to clean up snap specific data to start the next snap from clean.
*/
void G_ClearSnap( void )
{
	edict_t	*ent;

	game.realtime = trap_Milliseconds(); // level.time etc. might not be real time

	// clear gametype's clock override
	gs.gameState.longstats[GAMELONG_CLOCKOVERRIDE] = 0;

	// clear all events in the snap
	for( ent = &game.edicts[0]; ENTNUM( ent ) < game.numentities; ent++ )
	{
		if( ISEVENTENTITY( &ent->s ) )  // events do not persist after a snapshot
		{
			G_FreeEdict( ent );
			continue;
		}

		// events only last for a single message
		ent->s.events[0] = ent->s.events[1] = 0;
		ent->s.eventParms[0] = ent->s.eventParms[1] = 0;
		ent->numEvents = 0;
		ent->eventPriority[0] = ent->eventPriority[1] = false;
		ent->s.teleported = qfalse; // remove teleported bit.

		// remove effect bits that are (most likely) added from gametypes
		ent->s.effects = ( ent->s.effects & (EF_TAKEDAMAGE|EF_CARRIER|EF_FLAG_TRAIL|EF_ROTATE_AND_BOB|EF_STRONG_WEAPON|EF_GHOST) );
	}

	// recover some info, let players respawn and finally clear the snap structures
	for( ent = &game.edicts[0]; ENTNUM( ent ) < game.numentities; ent++ )
	{
		if( !GS_MatchPaused() )
		{
			// copy origin to old origin ( this old_origin is for snaps )
			if( !( ent->r.svflags & SVF_TRANSMITORIGIN2 ) )
				VectorCopy( ent->s.origin, ent->s.old_origin );

			G_CheckClientRespawnClick( ent );
		}

		if( GS_MatchPaused() )
			ent->s.sound = entity_sound_backup[ENTNUM( ent )];

		// clear the snap temp info
		memset( &ent->snap, 0, sizeof( ent->snap ) );
		if( ent->r.client && trap_GetClientState( PLAYERNUM( ent ) ) >= CS_SPAWNED )
		{
			memset( &ent->r.client->resp.snap, 0, sizeof( ent->r.client->resp.snap ) );

			// set race stats to invisible
			RS_clearHUDStats( ent->r.client ); // racesow - clear with our function
		}
	}

	g_snapStarted = false;
}
Exemple #27
0
/*
* G_StatsMessage
* 
* Generates stats message for the entity
* The returned string must be freed by the caller using G_Free
* Note: This string must never contain " characters
*/
char *G_StatsMessage( edict_t *ent )
{
	gclient_t *client;
	gsitem_t *item;
	int i, shot_weak, hit_weak, shot_strong, hit_strong, shot_total, hit_total;
	static char entry[MAX_TOKEN_CHARS];

	assert( ent && ent->r.client );
	client = ent->r.client;

	// message header
	Q_snprintfz( entry, sizeof( entry ), "%d", PLAYERNUM( ent ) );

	for( i = WEAP_GUNBLADE; i < WEAP_TOTAL; i++ )
	{
		item = GS_FindItemByTag( i );
		assert( item );

		hit_weak = hit_strong = 0;
		shot_weak = shot_strong = 0;

		if( item->weakammo_tag != AMMO_NONE )
		{
			hit_weak = client->level.stats.accuracy_hits[item->weakammo_tag - AMMO_GUNBLADE];
			shot_weak = client->level.stats.accuracy_shots[item->weakammo_tag - AMMO_GUNBLADE];
		}

		if( item->ammo_tag != AMMO_NONE )
		{
			hit_strong = client->level.stats.accuracy_hits[item->ammo_tag - AMMO_GUNBLADE];
			shot_strong = client->level.stats.accuracy_shots[item->ammo_tag - AMMO_GUNBLADE];
		}

		hit_total = hit_weak + hit_strong;
		shot_total = shot_weak + shot_strong;

		Q_strncatz( entry, va( " %d", shot_total ), sizeof( entry ) );
		if( shot_total < 1 )
			continue;
		Q_strncatz( entry, va( " %d", hit_total ), sizeof( entry ) );

		// strong
		Q_strncatz( entry, va( " %d", shot_strong ), sizeof( entry ) );
		if( shot_strong != shot_total )
			Q_strncatz( entry, va( " %d", hit_strong ), sizeof( entry ) );
	}

	Q_strncatz( entry, va( " %d %d", client->level.stats.total_damage_given, client->level.stats.total_damage_received ), sizeof( entry ) );
	Q_strncatz( entry, va( " %d %d", client->level.stats.health_taken, client->level.stats.armor_taken ), sizeof( entry ) );

	// add enclosing quote
	Q_strncatz( entry, "\"", sizeof( entry ) );

	return entry;
}
/*
* G_Match_Autorecord_Stats
*/
void G_Match_Autorecord_Stats( void )
{
	edict_t *ent;

	for( ent = game.edicts + 1; PLAYERNUM( ent ) < gs.maxclients; ent++ )
	{
		if( !ent->r.inuse || ent->s.team == TEAM_SPECTATOR || ( ent->r.svflags & SVF_FAKECLIENT ) )
			continue;
		trap_GameCmd( ent, va( "plstats 2 \"%s\"", G_StatsMessage( ent ) ) );
	}
}
Exemple #29
0
void G_AwardResetPlayerComboStats( edict_t *ent )
{
    int i;
    int resetvalue;

    // combo from LB can be cancelled only if player's dead, if he missed or if he hasnt shot with LB for too long
    resetvalue = ( G_IsDead( ent ) ? 0 : COMBO_FLAG( WEAP_LASERGUN ) );

    for( i = 0; i < gs.maxclients; i++ )
        game.clients[i].resp.awardInfo.combo[PLAYERNUM( ent )] &= resetvalue;
}
/*
* G_TickOutPowerUps
*/
static void G_TickOutPowerUps( void )
{
	edict_t *ent;
	gsitem_t *item;
	int i;

	for( ent = game.edicts + 1; PLAYERNUM( ent ) < gs.maxclients; ent++ )
	{
		if( ent->r.inuse && trap_GetClientState( PLAYERNUM( ent ) ) >= CS_SPAWNED )
		{
			for( i = POWERUP_QUAD; i < POWERUP_TOTAL; i++ )
			{
				item = GS_FindItemByTag( i );
				if( item && item->quantity && ent->r.client->ps.inventory[item->tag] > 0 )
				{
					ent->r.client->ps.inventory[item->tag]--;
				}
			}
		}
	}

	// also tick out dropped powerups
	for( ent = game.edicts + gs.maxclients + BODY_QUEUE_SIZE; ENTNUM( ent ) < game.numentities; ent++ )
	{
		if( !ent->r.inuse || !ent->item )
			continue;

		if( !( ent->item->type & IT_POWERUP ) )
			continue;

		if( ent->spawnflags & DROPPED_ITEM )
		{
			ent->count--;
			if( ent->count <= 0 )
			{
				G_FreeEdict( ent );
				continue;
			}
		}
	}
}