Ejemplo n.º 1
0
/*
* G_Match_LaunchState
*/
void G_Match_LaunchState( int matchState )
{
	static bool advance_queue = false;

	if( game.asEngine != NULL )
	{
		// give the gametype a chance to refuse the state change, or to set up things for it
		if( !GT_asCallMatchStateFinished( matchState ) )
			return;
	}
	else
	{
		// There isn't any script, run generic fuction
		if( !G_Gametype_GENERIC_MatchStateFinished( matchState ) )
			return;
	}

	GS_GamestatSetFlag( GAMESTAT_FLAG_MATCHEXTENDED, false );
	GS_GamestatSetFlag( GAMESTAT_FLAG_WAITING, false );
	
	if( matchState == MATCH_STATE_POSTMATCH ) {
		level.finalMatchDuration = game.serverTime - GS_MatchStartTime();
	}

    if( ( matchState == MATCH_STATE_POSTMATCH && GS_RaceGametype() )
        || ( matchState != MATCH_STATE_POSTMATCH && gs.gameState.stats[GAMESTAT_MATCHSTATE] == MATCH_STATE_POSTMATCH ) )
	{
		// entering postmatch in race or leaving postmatch in normal gt
		G_Match_SendReport();
		trap_MM_GameState( false );
	}

	switch( matchState )
	{
	default:
	case MATCH_STATE_WARMUP:
		{
			advance_queue = false;
			level.forceStart = false;

			gs.gameState.stats[GAMESTAT_MATCHSTATE] = MATCH_STATE_WARMUP;
			gs.gameState.longstats[GAMELONG_MATCHDURATION] = (unsigned int)( fabs( g_warmup_timelimit->value * 60 ) * 1000 );
			gs.gameState.longstats[GAMELONG_MATCHSTART] = game.serverTime;

			// race has playtime in warmup too, so flag the matchmaker about this
			if( GS_RaceGametype() )
				trap_MM_GameState( true );

			break;
		}

	case MATCH_STATE_COUNTDOWN:
		{
			advance_queue = true;

			gs.gameState.stats[GAMESTAT_MATCHSTATE] = MATCH_STATE_COUNTDOWN;
			gs.gameState.longstats[GAMELONG_MATCHDURATION] = (unsigned int)( fabs( g_countdown_time->value ) * 1000 );
			gs.gameState.longstats[GAMELONG_MATCHSTART] = game.serverTime;

			break;
		}

	case MATCH_STATE_PLAYTIME:
		{
			// ch : should clear some statcollection memory from warmup?

			advance_queue = true; // shouldn't be needed here
			level.forceStart = false;

			gs.gameState.stats[GAMESTAT_MATCHSTATE] = MATCH_STATE_PLAYTIME;
			gs.gameState.longstats[GAMELONG_MATCHDURATION] = (unsigned int)( fabs( 60 * g_timelimit->value )*1000 );
			gs.gameState.longstats[GAMELONG_MATCHSTART] = game.serverTime;

			// request a new match UUID
			trap_ConfigString( CS_MATCHUUID, "" );

			// tell matchmaker that the game is on, so if
			// client disconnects before SendReport, it is flagged
			// as 'purgable' on MM side
			trap_MM_GameState( true );
		}
		break;

	case MATCH_STATE_POSTMATCH:
		{
			gs.gameState.stats[GAMESTAT_MATCHSTATE] = MATCH_STATE_POSTMATCH;
			gs.gameState.longstats[GAMELONG_MATCHDURATION] = (unsigned int)fabs( g_postmatch_timelimit->value * 1000 ); // postmatch time in seconds
			gs.gameState.longstats[GAMELONG_MATCHSTART] = game.serverTime;

			G_Timeout_Reset();
			level.teamlock = false;
			level.forceExit = false;

			G_Match_Autorecord_Stats();
		}
		break;

	case MATCH_STATE_WAITEXIT:
		{
			if( advance_queue )
			{
				G_Teams_AdvanceChallengersQueue();
				advance_queue = true;
			}

			gs.gameState.stats[GAMESTAT_MATCHSTATE] = MATCH_STATE_WAITEXIT;
			gs.gameState.longstats[GAMELONG_MATCHDURATION] = 25000;
			gs.gameState.longstats[GAMELONG_MATCHSTART] = game.serverTime;

			level.exitNow = false;
		}
		break;
	}

	// give the gametype the chance to setup for the new state

	if( game.asEngine != NULL )
		GT_asCallMatchStateStarted();
	else
		G_Gametype_GENERIC_MatchStateStarted();

	G_UpdatePlayersMatchMsgs();
}
Ejemplo n.º 2
0
void G_AwardPlayerKilled( edict_t *self, edict_t *inflictor, edict_t *attacker, int mod )
{
    trace_t trace;
    score_stats_t *stats;
    loggedFrag_t *lfrag;

    if( self->r.svflags & SVF_CORPSE )
        return;

    if( !attacker->r.client )
        return;

    if( !self->r.client )
        return;

    if( attacker == self )
        return;

    if( attacker->s.team == self->s.team && attacker->s.team > TEAM_PLAYERS )
        return;

    if( mod == MOD_ROCKET_W || mod == MOD_ROCKET_S )
    {
        // direct hit
        attacker->r.client->resp.awardInfo.directrocket_count++;
        if( attacker->r.client->resp.awardInfo.directrocket_count == DIRECTROCKET_FOR_AWARD )
        {
            attacker->r.client->resp.awardInfo.directrocket_count = 0;
            attacker->r.client->resp.awardInfo.directrocket_award++;
            G_PlayerAward( attacker, S_COLOR_BLUE "Direct Rocket Hit!" );
        }
        // Midair
        if( self->groundentity == NULL && !self->waterlevel )
        {
            // check for height to the ground
            G_Trace( &trace, self->s.origin, self->r.mins, self->r.maxs, tv( self->s.origin[0], self->s.origin[1], self->s.origin[2] - 64 ), self, MASK_SOLID );
            if( trace.fraction == 1.0f )
            {
                attacker->r.client->resp.awardInfo.rl_midair_award++;
                G_PlayerAward( attacker, S_COLOR_BLUE "Air Rocket!" );
            }
        }
    }
    if( mod == MOD_GRENADE_W || mod == MOD_GRENADE_S )
    {
        // direct hit
        attacker->r.client->resp.awardInfo.directgrenade_count++;
        if( attacker->r.client->resp.awardInfo.directgrenade_count == DIRECTGRENADE_FOR_AWARD )
        {
            attacker->r.client->resp.awardInfo.directgrenade_count = 0;
            attacker->r.client->resp.awardInfo.directgrenade_award++;
            G_PlayerAward( attacker, S_COLOR_BLUE "Direct Grenade Hit!" );
        }

        // Midair
        if( self->groundentity == NULL && !self->waterlevel )
        {
            // check for height to the ground
            G_Trace( &trace, self->s.origin, self->r.mins, self->r.maxs, tv( self->s.origin[0], self->s.origin[1], self->s.origin[2] - 64 ), self, MASK_SOLID );
            if( trace.fraction == 1.0f )
            {
                attacker->r.client->resp.awardInfo.gl_midair_award++;
                G_PlayerAward( attacker, S_COLOR_BLUE "Air Grenade!" );
            }
        }
    }

    // Multikill
    if( game.serverTime - attacker->r.client->resp.awardInfo.multifrag_timer < MULTIKILL_INTERVAL )
        attacker->r.client->resp.awardInfo.multifrag_count++;
    else
        attacker->r.client->resp.awardInfo.multifrag_count = 1;

    attacker->r.client->resp.awardInfo.multifrag_timer = game.serverTime;

    if( attacker->r.client->resp.awardInfo.multifrag_count > 1 )
    {
        char s[MAX_CONFIGSTRING_CHARS];

        s[0] = 0;

        switch( attacker->r.client->resp.awardInfo.multifrag_count )
        {
        case 0:
        case 1:
            break;
        case 2:
            Q_strncpyz( s, S_COLOR_GREEN "Double Frag!", sizeof( s ) );
            break;
        case 3:
            Q_strncpyz( s, S_COLOR_GREEN "Triple Frag!", sizeof( s ) );
            break;
        case 4:
            Q_strncpyz( s, S_COLOR_GREEN "Quadruple Frag!", sizeof( s ) );
            break;
        default:
            Q_snprintfz( s, sizeof( s ), S_COLOR_GREEN "Extermination! %i in a row!", attacker->r.client->resp.awardInfo.multifrag_count );
            break;
        }

        G_PlayerAward( attacker, s );
    }

    // Sprees
    attacker->r.client->resp.awardInfo.frag_count++;

    if( attacker->r.client->resp.awardInfo.frag_count &&
            ( attacker->r.client->resp.awardInfo.frag_count % 5 == 0 ) )
    {
        char s[MAX_CONFIGSTRING_CHARS];

        s[0] = 0;

        switch( (int)( attacker->r.client->resp.awardInfo.frag_count / 5 ) )
        {
        case 1:
            Q_strncpyz( s, S_COLOR_YELLOW "On Fire!", sizeof( s ) );
            G_PrintMsg( NULL, "%s" S_COLOR_YELLOW " is On Fire!\n", attacker->r.client->netname );
            break;
        case 2:
            Q_strncpyz( s, S_COLOR_YELLOW "Raging!", sizeof( s ) );
            G_PrintMsg( NULL, "%s" S_COLOR_YELLOW " is Raging!\n", attacker->r.client->netname );
            break;
        case 3:
            Q_strncpyz( s, S_COLOR_YELLOW "Fraglord!", sizeof( s ) );
            G_PrintMsg( NULL, "%s" S_COLOR_YELLOW " is the Fraglord!\n", attacker->r.client->netname );
            break;
        case 4:
            Q_strncpyz( s, S_COLOR_YELLOW "Extermination!", sizeof( s ) );
            G_PrintMsg( NULL, "%s" S_COLOR_YELLOW " is Exterminating!\n", attacker->r.client->netname );
            break;
        default:
            Q_strncpyz( s, S_COLOR_YELLOW "God Mode!", sizeof( s ) );
            G_PrintMsg( NULL, "%s" S_COLOR_YELLOW " is in God Mode!\n", attacker->r.client->netname );
            break;
        }

        G_PlayerAward( attacker, s );
    }

    // ch : weapon specific frags
    if ( G_ModToAmmo( mod ) != AMMO_NONE )
        attacker->r.client->level.stats.accuracy_frags[G_ModToAmmo( mod )-AMMO_GUNBLADE]++;

    if( GS_MatchState() == MATCH_STATE_PLAYTIME /* && !strcmp( "duel", gs.gametypeName ) */)
    {
        // ch : frag log
        stats = &attacker->r.client->level.stats;
        if( !stats->fragAllocator )
            stats->fragAllocator = LinearAllocator( sizeof( loggedFrag_t ), 0, _G_LevelMalloc, _G_LevelFree );

        lfrag = LA_Alloc( stats->fragAllocator );
        lfrag->mm_attacker = attacker->r.client->mm_session;
        lfrag->mm_victim = self->r.client->mm_session;
        lfrag->weapon = G_ModToAmmo( mod ) - AMMO_GUNBLADE;
        lfrag->time = ( game.serverTime - GS_MatchStartTime() ) / 1000;
    }
}
Ejemplo n.º 3
0
/*
* G_UpdateServerInfo
* update the cvars which show the match state at server browsers
*/
static void G_UpdateServerInfo( void )
{
	// g_match_time
	if( GS_MatchState() <= MATCH_STATE_WARMUP )
	{
		trap_Cvar_ForceSet( "g_match_time", "Warmup" );
	}
	else if( GS_MatchState() == MATCH_STATE_COUNTDOWN )
	{
		trap_Cvar_ForceSet( "g_match_time", "Countdown" );
	}
	else if( GS_MatchState() == MATCH_STATE_PLAYTIME )
	{
		// partly from G_GetMatchState
		char extra[MAX_INFO_VALUE];
		int clocktime, timelimit, mins, secs;

		if( GS_MatchDuration() )
			timelimit = ( ( GS_MatchDuration() ) * 0.001 ) / 60;
		else
			timelimit = 0;

		clocktime = (float)( game.serverTime - GS_MatchStartTime() ) * 0.001f;

		if( clocktime <= 0 )
		{
			mins = 0;
			secs = 0;
		}
		else
		{
			mins = clocktime / 60;
			secs = clocktime - mins * 60;
		}

		extra[0] = 0;
		if( GS_MatchExtended() )
		{
			if( timelimit )
				Q_strncatz( extra, " overtime", sizeof( extra ) );
			else
				Q_strncatz( extra, " suddendeath", sizeof( extra ) );
		}
		if( GS_MatchPaused() )
			Q_strncatz( extra, " (in timeout)", sizeof( extra ) );

		if( timelimit )
			trap_Cvar_ForceSet( "g_match_time", va( "%02i:%02i / %02i:00%s", mins, secs, timelimit, extra ) );
		else
			trap_Cvar_ForceSet( "g_match_time", va( "%02i:%02i%s", mins, secs, extra ) );
	}
	else
	{
		trap_Cvar_ForceSet( "g_match_time", "Finished" );
	}

	// g_match_score
	if( GS_MatchState() >= MATCH_STATE_PLAYTIME && GS_TeamBasedGametype() )
	{
		char score[MAX_INFO_STRING];

		score[0] = 0;
		Q_strncatz( score, va( " %s: %i", GS_TeamName( TEAM_ALPHA ), teamlist[TEAM_ALPHA].stats.score ), sizeof( score ) );
		Q_strncatz( score, va( " %s: %i", GS_TeamName( TEAM_BETA ), teamlist[TEAM_BETA].stats.score ), sizeof( score ) );

		if( strlen( score ) >= MAX_INFO_VALUE ) {
			// prevent "invalid info cvar value" flooding
			score[0] = '\0';
		}
		trap_Cvar_ForceSet( "g_match_score", score );
	}
	else
	{
		trap_Cvar_ForceSet( "g_match_score", "" );
	}

	// g_needpass
	if( password->modified )
	{
		if( password->string && strlen( password->string ) )
		{
			trap_Cvar_ForceSet( "g_needpass", "1" );
		}
		else
		{
			trap_Cvar_ForceSet( "g_needpass", "0" );
		}
		password->modified = false;
	}

	// g_gametypes_available
	if( g_votable_gametypes->modified || g_disable_vote_gametype->modified )
	{
		if( g_disable_vote_gametype->integer || !g_votable_gametypes->string || !strlen( g_votable_gametypes->string ) )
		{
			trap_Cvar_ForceSet( "g_gametypes_available", "" );
		}
		else
		{
			char *votable;
			char *name;
			size_t len;
			int count;

			len = 0;

			for( count = 0; ( name = G_ListNameForPosition( g_gametypes_list->string, count, CHAR_GAMETYPE_SEPARATOR ) ) != NULL; count++ )
			{
				if( G_Gametype_IsVotable( name ) )
					len += strlen( name ) + 1;
			}

			len++;
			votable = ( char * )G_Malloc( len );
			votable[0] = 0;

			for( count = 0; ( name = G_ListNameForPosition( g_gametypes_list->string, count, CHAR_GAMETYPE_SEPARATOR ) ) != NULL; count++ )
			{
				if( G_Gametype_IsVotable( name ) )
				{
					Q_strncatz( votable, name, len );
					Q_strncatz( votable, " ", len );
				}
			}

			//votable[ strlen( votable )-2 ] = 0; // remove the last space
			trap_Cvar_ForceSet( "g_gametypes_available", votable );
			G_Free( votable );
		}

		g_votable_gametypes->modified = false;
		g_disable_vote_gametype->modified = false;
	}

	if( GS_RaceGametype() ) {
		trap_Cvar_ForceSet( "g_race_gametype", "1" );
	}
	else {
		trap_Cvar_ForceSet( "g_race_gametype", "0" );
	}
}
Ejemplo n.º 4
0
/*
* ClientThink
*/
void ClientThink( edict_t *ent, usercmd_t *ucmd, int timeDelta )
{
	gclient_t *client;
	int i, j;
	static pmove_t pm;
	int delta, count;

	client = ent->r.client;

	client->ps.POVnum = ENTNUM( ent );
	client->ps.playerNum = PLAYERNUM( ent );

	// anti-lag
	if( ent->r.svflags & SVF_FAKECLIENT )
	{
		client->timeDelta = 0;
	}
	else
	{
		int nudge;
		int fixedNudge = ( game.snapFrameTime ) * 0.5; // fixme: find where this nudge comes from.

		// add smoothing to timeDelta between the last few ucmds and a small fine-tuning nudge.
		nudge = fixedNudge + g_antilag_timenudge->integer;
		timeDelta += nudge;
		clamp( timeDelta, -g_antilag_maxtimedelta->integer, 0 );

		// smooth using last valid deltas
		i = client->timeDeltasHead - 6;
		if( i < 0 ) i = 0;
		for( count = 0, delta = 0; i < client->timeDeltasHead; i++ )
		{
			if( client->timeDeltas[i & G_MAX_TIME_DELTAS_MASK] < 0 )
			{
				delta += client->timeDeltas[i & G_MAX_TIME_DELTAS_MASK];
				count++;
			}
		}

		if( !count )
			client->timeDelta = timeDelta;
		else
		{
			delta /= count;
			client->timeDelta = ( delta + timeDelta ) * 0.5;
		}

		client->timeDeltas[client->timeDeltasHead & G_MAX_TIME_DELTAS_MASK] = timeDelta;
		client->timeDeltasHead++;

#ifdef UCMDTIMENUDGE
		client->timeDelta += client->pers.ucmdTimeNudge;
#endif
	}

	clamp( client->timeDelta, -g_antilag_maxtimedelta->integer, 0 );

	// update activity if he touched any controls
	if( ucmd->forwardmove != 0 || ucmd->sidemove != 0 || ucmd->upmove != 0 || ( ucmd->buttons & ~BUTTON_BUSYICON ) != 0
		|| client->ucmd.angles[PITCH] != ucmd->angles[PITCH] || client->ucmd.angles[YAW] != ucmd->angles[YAW] )
		G_Client_UpdateActivity( client );

	client->ucmd = *ucmd;

	// can exit intermission after two seconds, not counting postmatch
	if( GS_MatchState() == MATCH_STATE_WAITEXIT && ( ucmd->buttons & BUTTON_ATTACK ) && game.serverTime > GS_MatchStartTime() + 2000 )
		level.exitNow = true;

	// (is this really needed?:only if not cared enough about ps in the rest of the code)
	// refresh player state position from the entity
	VectorCopy( ent->s.origin, client->ps.pmove.origin );
	VectorCopy( ent->velocity, client->ps.pmove.velocity );
	VectorCopy( ent->s.angles, client->ps.viewangles );

	client->ps.pmove.gravity = level.gravity;

	if( GS_MatchState() >= MATCH_STATE_POSTMATCH || GS_MatchPaused() 
		|| ( ent->movetype != MOVETYPE_PLAYER && ent->movetype != MOVETYPE_NOCLIP ) )
		client->ps.pmove.pm_type = PM_FREEZE;
	else if( ent->s.type == ET_GIB )
		client->ps.pmove.pm_type = PM_GIB;
	else if( ent->movetype == MOVETYPE_NOCLIP || client->isTV )
		client->ps.pmove.pm_type = PM_SPECTATOR;
	else
		client->ps.pmove.pm_type = PM_NORMAL;

	// set up for pmove
	memset( &pm, 0, sizeof( pmove_t ) );
	pm.playerState = &client->ps;

	if( !client->isTV )
		pm.cmd = *ucmd;

	if( memcmp( &client->old_pmove, &client->ps.pmove, sizeof( pmove_state_t ) ) )
		pm.snapinitial = true;

	// perform a pmove
	Pmove( &pm );

	// save results of pmove
	client->old_pmove = client->ps.pmove;

	// update the entity with the new position
	VectorCopy( client->ps.pmove.origin, ent->s.origin );
	VectorCopy( client->ps.pmove.velocity, ent->velocity );
	VectorCopy( client->ps.viewangles, ent->s.angles );
	ent->viewheight = client->ps.viewheight;
	VectorCopy( pm.mins, ent->r.mins );
	VectorCopy( pm.maxs, ent->r.maxs );

	ent->waterlevel = pm.waterlevel;
	ent->watertype = pm.watertype;
	if( pm.groundentity == -1 )
	{
		ent->groundentity = NULL;
	}
	else
	{
		G_AwardResetPlayerComboStats( ent );

		ent->groundentity = &game.edicts[pm.groundentity];
		ent->groundentity_linkcount = ent->groundentity->linkcount;
	}
	
	GClip_LinkEntity( ent );

	GS_AddLaserbeamPoint( &ent->r.client->resp.trail, &ent->r.client->ps, ucmd->serverTimeStamp );

	// Regeneration
	if( ent->r.client->ps.inventory[POWERUP_REGEN] > 0 && ent->health < 200)
	{
		ent->health += ( game.frametime * 0.001f ) * 10.0f;

		// Regen expires if health reaches 200
		if ( ent->health >= 199.0f )
			ent->r.client->ps.inventory[POWERUP_REGEN]--;
	}

	// fire touch functions
	if( ent->movetype != MOVETYPE_NOCLIP )
	{
		edict_t *other;

		// touch other objects
		for( i = 0; i < pm.numtouch; i++ )
		{
			other = &game.edicts[pm.touchents[i]];
			for( j = 0; j < i; j++ )
			{
				if( &game.edicts[pm.touchents[j]] == other )
					break;
			}
			if( j != i )
				continue; // duplicated

			// player can't touch projectiles, only projectiles can touch the player
			G_CallTouch( other, ent, NULL, 0 );
		}
	}

	ent->s.weapon = GS_ThinkPlayerWeapon( &client->ps, ucmd->buttons, ucmd->msec, client->timeDelta );

	if( G_IsDead( ent ) )
	{
		if( ent->deathTimeStamp + g_respawn_delay_min->integer <= level.time )
			client->resp.snap.buttons |= ucmd->buttons;
	}
	else if( client->ps.pmove.stats[PM_STAT_NOUSERCONTROL] <= 0 )
		client->resp.snap.buttons |= ucmd->buttons;

	// trigger the instashield
	if( GS_Instagib() && g_instashield->integer )
	{
		if( client->ps.pmove.pm_type == PM_NORMAL && pm.cmd.upmove < 0 &&
			client->resp.instashieldCharge == INSTA_SHIELD_MAX && 
			client->ps.inventory[POWERUP_SHELL] == 0 )
		{
			client->ps.inventory[POWERUP_SHELL] = client->resp.instashieldCharge;
			G_Sound( ent, CHAN_AUTO, trap_SoundIndex( GS_FindItemByTag( POWERUP_SHELL )->pickup_sound ), ATTN_NORM );
		}
	}	

	// 
	if( client->ps.pmove.pm_type == PM_NORMAL )
		client->level.stats.had_playtime = true;

	// generating plrkeys (optimized for net communication)
	ClientMakePlrkeys( client, ucmd );
}
Ejemplo n.º 5
0
/*
* CG_AddLocalSounds
*/
static void CG_AddLocalSounds( void )
{
	static bool postmatchsound_set = false, demostream = false, background = false;
	static unsigned int lastSecond = 0;

	// add local announces
	if( GS_Countdown() )
	{
		if( GS_MatchDuration() )
		{
			unsigned int duration, curtime, remainingSeconds;
			float seconds;

			curtime = GS_MatchPaused() ? cg.frame.serverTime : cg.time;
			duration = GS_MatchDuration();

			if( duration + GS_MatchStartTime() < curtime )
				duration = curtime - GS_MatchStartTime(); // avoid negative results

			seconds = (float)( GS_MatchStartTime() + duration - curtime ) * 0.001f;
			remainingSeconds = (unsigned int)seconds;

			if( remainingSeconds != lastSecond )
			{
				if( 1 + remainingSeconds < 4 )
				{
					struct sfx_s *sound = trap_S_RegisterSound( va( S_ANNOUNCER_COUNTDOWN_COUNT_1_to_3_SET_1_to_2, 1 + remainingSeconds, 1 ) );
					CG_AddAnnouncerEvent( sound, false );
				}

				lastSecond = remainingSeconds;
			}
		}
	}
	else
		lastSecond = 0;

	// add sounds from announcer
	CG_ReleaseAnnouncerEvents();

	// if in postmatch, play postmatch song
	if( GS_MatchState() >= MATCH_STATE_POSTMATCH )
	{
		if( !postmatchsound_set && !demostream )
		{
			trap_S_StartBackgroundTrack( S_PLAYLIST_POSTMATCH, NULL, 3 ); // loop random track from the playlist
			postmatchsound_set = true;
			background = false;
		}
	}
	else
	{
		if( cgs.demoPlaying && cgs.demoAudioStream && !demostream )
		{
			trap_S_StartBackgroundTrack( cgs.demoAudioStream, NULL, 0 );
			demostream = true;
		}

		if( postmatchsound_set )
		{
			trap_S_StopBackgroundTrack();
			postmatchsound_set = false;
			background = false;
		}

		if( (!postmatchsound_set && !demostream) && !background )
		{
			CG_StartBackgroundTrack();
			background = true;
		}

		// notice: these 2 sound files aren't used anymore
		//cgs.media.sfxTimerBipBip
		//cgs.media.sfxTimerPloink
	}
}