Esempio n. 1
0
AiBaseTeamBrain *AiBaseTeamBrain::InstantiateTeamBrain( int team, const char *gametype ) {
	// Delegate construction to AiSquadBasedTeamBrain
	if( GS_TeamBasedGametype() && !GS_InvidualGameType() ) {
		return AiSquadBasedTeamBrain::InstantiateTeamBrain( team, gametype );
	}

	void *mem = G_Malloc( sizeof( AiBaseTeamBrain ) );
	return new(mem)AiBaseTeamBrain( team );
}
Esempio n. 2
0
void G_Teams_Coach( edict_t *ent )
{
	if( GS_TeamBasedGametype() && !GS_InvidualGameType() && ent->s.team != TEAM_SPECTATOR )
	{
		if( !teamlist[ent->s.team].has_coach )
		{
			if( GS_MatchState() > MATCH_STATE_WARMUP && !GS_MatchPaused() )
			{
				G_PrintMsg( ent, "Can't set coach mode with the match in progress\n" );
			}
			else
			{
				// move to coach mode
				ent->r.client->teamstate.is_coach = true;
				G_GhostClient( ent );
				ent->health = ent->max_health;
				ent->deadflag = DEAD_NO;

				G_ChasePlayer( ent, NULL, true, 0 );

				//clear up his scores
				G_Match_Ready( ent ); // set ready and check readys
				memset( &ent->r.client->level.stats, 0, sizeof( ent->r.client->level.stats ) );

				teamlist[ent->s.team].has_coach = true;
				G_PrintMsg( NULL, "%s%s is now team %s coach \n", ent->r.client->netname,
					S_COLOR_WHITE, GS_TeamName( ent->s.team ) );
			}
		}
		else if( ent->r.client->teamstate.is_coach )
		{                            // if you are this team coach, resign
			ent->r.client->teamstate.is_coach = false;
			G_PrintMsg( NULL, "%s%s is no longer team %s coach \n", ent->r.client->netname,
				S_COLOR_WHITE, GS_TeamName( ent->s.team ) );

			G_Teams_SetTeam( ent, ent->s.team );
		}
		else
			G_PrintMsg( ent, "Your team already has a coach.\n" );
	}
	else
		G_PrintMsg( ent, "Coaching only valid while on a team in Team based Gametypes.\n" );
}
Esempio n. 3
0
void G_Gametype_GENERIC_PlayerKilled( edict_t *targ, edict_t *attacker, edict_t *inflictor )
{
	if( !attacker || GS_MatchState() != MATCH_STATE_PLAYTIME || ( targ->r.svflags & SVF_CORPSE ) )
		return;

	if( !attacker->r.client || attacker == targ || attacker == world )
		teamlist[targ->s.team].stats.score--;
	else
	{
		if( GS_InvidualGameType() )
			teamlist[attacker->s.team].stats.score = attacker->r.client->level.stats.score;
		if( GS_IsTeamDamage( &targ->s, &attacker->s ) )
			teamlist[attacker->s.team].stats.score--;
		else
			teamlist[attacker->s.team].stats.score++;
	}

	// drop items
	if( targ->r.client && !( G_PointContents( targ->s.origin ) & CONTENTS_NODROP ) )
	{
		// drop the weapon
		if ( targ->r.client->ps.stats[STAT_WEAPON] > WEAP_GUNBLADE )
		{
			gsitem_t *weaponItem = GS_FindItemByTag( targ->r.client->ps.stats[STAT_WEAPON] );
			if( weaponItem )
			{
				edict_t *drop = Drop_Item( targ, weaponItem );
				if( drop )
				{
					drop->count = targ->r.client->ps.inventory[ weaponItem->weakammo_tag ];
					targ->r.client->ps.inventory[ weaponItem->weakammo_tag ] = 0;
				}
			}
		}

		// drop ammo pack (won't drop anything if player doesn't have any strong ammo)
		Drop_Item( targ, GS_FindItemByTag( AMMO_PACK ) );
	}
}
Esempio n. 4
0
/*
* CG_FlashGameWindow
*
* Flashes game window in case of important events (match state changes, etc) for user to notice
*/
static void CG_FlashGameWindow( void )
{
	static int oldState = -1;
	int newState;
	bool flash = false;
	static int oldAlphaScore, oldBetaScore;
	static bool scoresSet = false;

	// notify player of important match states
	newState = GS_MatchState();
	if( oldState != newState )
	{
		switch( newState )
		{
		case MATCH_STATE_COUNTDOWN:
		case MATCH_STATE_PLAYTIME:
		case MATCH_STATE_POSTMATCH:
			flash = true;
			break;
		default:
			break;
		}

		oldState = newState;
	}

	// notify player of teams scoring in team-based gametypes
	if( !scoresSet || 
		( oldAlphaScore != cg.predictedPlayerState.stats[STAT_TEAM_ALPHA_SCORE] || oldBetaScore != cg.predictedPlayerState.stats[STAT_TEAM_BETA_SCORE] ) )  {
		oldAlphaScore = cg.predictedPlayerState.stats[STAT_TEAM_ALPHA_SCORE];
		oldBetaScore = cg.predictedPlayerState.stats[STAT_TEAM_BETA_SCORE];

		flash = scoresSet && GS_TeamBasedGametype() && !GS_InvidualGameType();
		scoresSet = true;
	}

	if( flash )
		trap_VID_FlashWindow( cg_flashWindowCount->integer );
}
Esempio n. 5
0
/*
* G_Match_ScoreAnnouncement
*/
static void G_Match_ScoreAnnouncement( void )
{
	int i;
	edict_t *e, *chased;
	int num_leaders, team;

	if( !level.gametype.scoreAnnouncementEnabled )
		return;

	num_leaders = 0;
	memset( leaders, 0, sizeof( leaders ) );

	if( GS_TeamBasedGametype() )
	{
		int score_max = -999999999;

		for( team = TEAM_ALPHA; team < GS_MAX_TEAMS; team++ )
		{
			if( !teamlist[team].numplayers )
				continue;

			if( teamlist[team].stats.score > score_max )
			{
				score_max = teamlist[team].stats.score;
				leaders[0] = team;
				num_leaders = 1;
			}
			else if( teamlist[team].stats.score == score_max )
			{
				leaders[num_leaders++] = team;
			}
		}
		leaders[num_leaders] = 0;
	}
	else
	{
		int score_max = -999999999;

		for( i = 0; i < MAX_CLIENTS && i < teamlist[TEAM_PLAYERS].numplayers; i++ )
		{
			if( game.clients[teamlist[TEAM_PLAYERS].playerIndices[i]-1].level.stats.score > score_max )
			{
				score_max = game.clients[teamlist[TEAM_PLAYERS].playerIndices[i]-1].level.stats.score;
				leaders[0] = teamlist[TEAM_PLAYERS].playerIndices[i];
				num_leaders = 1;
			}
			else if( game.clients[teamlist[TEAM_PLAYERS].playerIndices[i]-1].level.stats.score == score_max )
			{
				leaders[num_leaders++] = teamlist[TEAM_PLAYERS].playerIndices[i];
			}
		}
		leaders[num_leaders] = 0;
	}

	if( !score_announcement_init )
	{
		// copy over to last_leaders
		memcpy( last_leaders, leaders, sizeof( leaders ) );
		score_announcement_init = true;
		return;
	}

	for( e = game.edicts + 1; PLAYERNUM( e ) < gs.maxclients; e++ )
	{
		if( !e->r.client || trap_GetClientState( PLAYERNUM( e ) ) < CS_SPAWNED )
			continue;

		if( e->r.client->resp.chase.active )
			chased = &game.edicts[e->r.client->resp.chase.target];
		else
			chased = e;

		// floating spectator
		if( chased->s.team == TEAM_SPECTATOR )
		{
			if( !GS_TeamBasedGametype() )
				continue;

			if( last_leaders[1] == 0 && leaders[1] != 0 )
			{
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_TIED_LEAD_1_to_2, ( rand()&1 )+1 ) ),
					GS_MAX_TEAMS, true, NULL );
			}
			else if( leaders[1] == 0 && ( last_leaders[0] != leaders[0] || last_leaders[1] != 0 ) )
			{
				//G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_1_to_4_TAKEN_LEAD_1_to_2,
				//	leaders[0]-1, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, true, NULL );
			}
			continue;
		}

		// in the game or chasing someone who is
		if( G_WasLeading( chased ) && !G_IsLeading( chased ) )
		{
			if( GS_TeamBasedGametype() && !GS_InvidualGameType() )
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_LOST_LEAD_1_to_2, ( rand()&1 )+1 ) ),
				GS_MAX_TEAMS, true, NULL );
			else
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_LOST_LEAD_1_to_2, ( rand()&1 )+1 ) ),
				GS_MAX_TEAMS, true, NULL );
		}
		else if( ( !G_WasLeading( chased ) || ( last_leaders[1] != 0 ) ) && G_IsLeading( chased ) && ( leaders[1] == 0 ) )
		{
			if( GS_TeamBasedGametype() && !GS_InvidualGameType() )
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_TAKEN_LEAD_1_to_2, ( rand()&1 )+1 ) ),
				GS_MAX_TEAMS, true, NULL );
			else
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TAKEN_LEAD_1_to_2, ( rand()&1 )+1 ) ),
				GS_MAX_TEAMS, true, NULL );
		}
		else if( ( !G_WasLeading( chased ) || ( last_leaders[1] == 0 ) ) && G_IsLeading( chased ) && ( leaders[1] != 0 ) )
		{
			if( GS_TeamBasedGametype() && !GS_InvidualGameType() )
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TEAM_TIED_LEAD_1_to_2, ( rand()&1 )+1 ) ),
				GS_MAX_TEAMS, true, NULL );
			else
				G_AnnouncerSound( e, trap_SoundIndex( va( S_ANNOUNCER_SCORE_TIED_LEAD_1_to_2, ( rand()&1 )+1 ) ),
				GS_MAX_TEAMS, true, NULL );
		}
	}

	// copy over to last_leaders
	memcpy( last_leaders, leaders, sizeof( leaders ) );
}
Esempio n. 6
0
/*
* G_Match_Autorecord_Start
*/
void G_Match_Autorecord_Start( void )
{
	int team, i, playerCount;

	G_Match_SetAutorecordState( "start" );

	// do not start autorecording if all playing clients are bots
	for( playerCount = 0, team = TEAM_PLAYERS; team < GS_MAX_TEAMS; team++ )
	{
		// add our team info to the string
		for( i = 0; i < teamlist[team].numplayers; i++ )
		{
			if( game.edicts[ teamlist[team].playerIndices[i] ].r.svflags & SVF_FAKECLIENT )
				continue;

			playerCount++;
			break; // we only need one for this check
		}
	}

	if( playerCount && g_autorecord->integer )
	{
		char datetime[17], players[MAX_STRING_CHARS];
		time_t long_time;
		struct tm *newtime;

		// date & time
		time( &long_time );
		newtime = localtime( &long_time );

		Q_snprintfz( datetime, sizeof( datetime ), "%04d-%02d-%02d_%02d-%02d", newtime->tm_year + 1900,
			newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min );

		// list of players
		Q_strncpyz( players, trap_GetConfigString( CS_MATCHNAME ), sizeof( players ) );
		if( players[0] == '\0' )
		{
			if( GS_InvidualGameType() )
			{
				const char *netname;
				int team;
				edict_t *ent;

				for( team = TEAM_ALPHA; team < GS_MAX_TEAMS; team++ )
				{
					if( !teamlist[team].numplayers )
						continue;
					ent = game.edicts + teamlist[team].playerIndices[0];
					netname = ent->r.client->netname;
					Q_strncatz( players, netname, sizeof( players ) );
					if( team != GS_MAX_TEAMS - 1 )
						Q_strncatz( players, " vs ", sizeof( players ) );
				}
			}
		}

		if( players[0] != '\0' )
		{
			char *t = strstr( players, " vs " );
			if( t )
				memcpy( t, "_vs_", strlen( "_vs_" ) );
			Q_strncpyz( players, COM_RemoveJunkChars( COM_RemoveColorTokens( players ) ), sizeof( players ) );
		}

		// combine
		Q_snprintfz( level.autorecord_name, sizeof( level.autorecord_name ), "%s_%s_%s%s%s_auto%04i", 
			datetime, gs.gametypeName, level.mapname, players[0] == '\0' ? "" : "_", players, (int)brandom( 1, 9999 ) );

		trap_Cmd_ExecuteText( EXEC_APPEND, va( "serverrecord %s\n", level.autorecord_name ) );
	}
}
Esempio n. 7
0
/*
* G_vsay_f
*/
static void G_vsay_f( edict_t *ent, bool team )
{
	edict_t	*event = NULL;
	g_vsays_t *vsay;
	const char *text = NULL;
	char *msg = trap_Cmd_Argv( 1 );

	if( ent->r.client && ent->r.client->muted & 2 )
		return;

	if( ( !GS_TeamBasedGametype() || GS_InvidualGameType() ) && ent->s.team != TEAM_SPECTATOR )
		team = false;

	if( !( ent->r.svflags & SVF_FAKECLIENT ) )
	{                                      // ignore flood checks on bots
		if( ent->r.client->level.last_vsay > game.realtime - 500 )
			return; // ignore silently vsays in that come in rapid succession
		ent->r.client->level.last_vsay = game.realtime;

		if( CheckFlood( ent, false ) )
			return;
	}

	for( vsay = g_vsays; vsay->name; vsay++ )
	{
		if( !Q_stricmp( msg, vsay->name ) )
		{
			event = G_SpawnEvent( EV_VSAY, vsay->id, NULL );
			text = vsay->message;
			break;
		}
	}

	if( event && text )
	{
		char saystring[256];

		event->r.svflags |= SVF_BROADCAST; // force sending even when not in PVS
		event->s.ownerNum = ent->s.number;
		if( team )
		{
			event->s.team = ent->s.team;
			event->r.svflags |= SVF_ONLYTEAM; // send only to clients with the same ->s.team value
		}

		if( trap_Cmd_Argc() > 2 )
		{
			int i;

			saystring[0] = 0;
			for( i = 2; i < trap_Cmd_Argc(); i++ )
			{
				Q_strncatz( saystring, trap_Cmd_Argv( i ), sizeof( saystring ) );
				Q_strncatz( saystring, " ", sizeof( saystring ) );
			}
			text = saystring;
		}

		if( team )
			G_Say_Team( ent, va( "(v) %s", text ), false );
		else
			G_ChatMsg( NULL, ent, false, "(v) %s", text );
		return;
	}

	// unknown token, print help
	{
		char string[MAX_STRING_CHARS];

		// print information
		string[0] = 0;
		if( msg && msg[0] != '\0' )
			Q_strncatz( string, va( "%sUnknown vsay token%s \"%s\"\n", S_COLOR_YELLOW, S_COLOR_WHITE, msg ), sizeof( string ) );
		Q_strncatz( string, va( "%svsays:%s\n", S_COLOR_YELLOW, S_COLOR_WHITE ), sizeof( string ) );
		for( vsay = g_vsays; vsay->name; vsay++ )
		{
			if( strlen( vsay->name ) + strlen( string ) < sizeof( string ) - 6 )
			{
				Q_strncatz( string, va( "%s ", vsay->name ), sizeof( string ) );
			}
		}
		Q_strncatz( string, "\n", sizeof( string ) );
		G_PrintMsg( ent, string );
	}
}
Esempio n. 8
0
void G_Say_Team( edict_t *who, char *msg, bool checkflood )
{
	char outmsg[256];
	char buf[256];
	char *p;
	char current_color[3];

	if( who->s.team != TEAM_SPECTATOR && ( !GS_TeamBasedGametype() || GS_InvidualGameType() ) )
	{
		Cmd_Say_f( who, false, true );
		return;
	}

	if( checkflood )
	{
		if( CheckFlood( who, true ) )
			return;
	}

	if( *msg == '\"' )
	{
		msg[strlen( msg ) - 1] = 0;
		msg++;
	}

	if( who->s.team == TEAM_SPECTATOR )
	{
		// if speccing, also check for non-team flood
		if( checkflood )
		{
			if( CheckFlood( who, false ) )
				return;
		}

		G_ChatMsg( NULL, who, true, "%s", msg );
		return;
	}

#ifdef AUTHED_SAY
	if( sv_mm_enable->integer && who->r.client && who->r.client->mm_session <= 0 )
	{
		// unauthed players are only allowed to chat to public at non play-time
		// they are allowed to team-chat at any time
		if( GS_MatchState() == MATCH_STATE_PLAYTIME )
		{
			G_PrintMsg( who, "%s", S_COLOR_YELLOW "You must authenticate to be able to chat with other players during the match.\n");
			return;
		}
	}
#endif

	Q_strncpyz( current_color, S_COLOR_WHITE, sizeof( current_color ) );

	memset( outmsg, 0, sizeof( outmsg ) );

	UpdatePoint( who );

	for( p = outmsg; *msg && (size_t)( p - outmsg ) < sizeof( outmsg ) - 3; msg++ )
	{
		if( *msg == '%' )
		{
			buf[0] = 0;
			switch( *++msg )
			{
			case 'l':
				Say_Team_Location( who, buf, sizeof( buf ), current_color );
				break;
			case 'a':
				Say_Team_Armor( who, buf, sizeof( buf ), current_color );
				break;
			case 'h':
				Say_Team_Health( who, buf, sizeof( buf ), current_color );
				break;
			case 'b':
				Say_Team_Best_Weapons( who, buf, sizeof( buf ), current_color );
				break;
			case 'w':
				Say_Team_Current_Weapon( who, buf, sizeof( buf ), current_color );
				break;
			case 'x':
				Say_Team_Point( who, buf, sizeof( buf ), current_color );
				break;
			case 'y':
				Say_Team_Point_Location( who, buf, sizeof( buf ), current_color );
				break;
			case 'X':
				Say_Team_Pickup( who, buf, sizeof( buf ), current_color );
				break;
			case 'Y':
				Say_Team_Pickup_Location( who, buf, sizeof( buf ), current_color );
				break;
			case 'd':
				Say_Team_Drop( who, buf, sizeof( buf ), current_color );
				break;
			case 'D':
				Say_Team_Drop_Location( who, buf, sizeof( buf ), current_color );
				break;
			case '%':
				*p++ = *msg;
				break;
			default:
				// Maybe add a warning here?
				*p++ = '%';
				*p++ = *msg;
				break;
			}
			if( strlen( buf ) + ( p - outmsg ) < sizeof( outmsg ) - 3 )
			{
				Q_strncatz( outmsg, buf, sizeof( outmsg ) );
				p += strlen( buf );
			}
		}
		else if( *msg == '^' )
		{
			*p++ = *msg++;
			*p++ = *msg;
			Q_strncpyz( current_color, p-2, sizeof( current_color ) );
		}
		else
		{
			*p++ = *msg;
		}
	}
	*p = 0;

	G_ChatMsg( NULL, who, true, "%s", outmsg );
}
Esempio n. 9
0
//==========================================
// BOT_DMclass_VSAYmessages
//==========================================
static void BOT_DMclass_VSAYmessages( edict_t *self )
{
	if( GS_MatchState() != MATCH_STATE_PLAYTIME )
		return;
	if( level.gametype.dummyBots || bot_dummy->integer )
		return;

	if( self->snap.damageteam_given > 25 )
	{
		if( rand() & 1 )
		{
			if( rand() & 1 )
			{
				G_BOTvsay_f( self, "oops", true );
			}
			else
			{
				G_BOTvsay_f( self, "sorry", true );
			}
		}
		return;
	}

	if( self->ai->vsay_timeout > level.time )
		return;

	if( GS_MatchDuration() && game.serverTime + 4000 > GS_MatchEndTime() )
	{
		self->ai->vsay_timeout = game.serverTime + ( 1000 + (GS_MatchEndTime() - game.serverTime) );
		if( rand() & 1 )
			G_BOTvsay_f( self, "goodgame", false );
		return;
	}

	self->ai->vsay_timeout = level.time + ( ( 8+random()*12 ) * 1000 );

	// the more bots, the less vsays to play
	if( random() > 0.1 + 1.0f / game.numBots )
		return;

	if( GS_TeamBasedGametype() && !GS_InvidualGameType() )
	{
		if( self->health < 20 && random() > 0.3 )
		{
			G_BOTvsay_f( self, "needhealth", true );
			return;
		}

		if( ( self->s.weapon == 0 || self->s.weapon == 1 ) && random() > 0.7 )
		{
			G_BOTvsay_f( self, "needweapon", true );
			return;
		}

		if( self->r.client->resp.armor < 10 && random() > 0.8 )
		{
			G_BOTvsay_f( self, "needarmor", true );
			return;
		}
	}

	// NOT team based here

	if( random() > 0.2 )
		return;

	switch( (int)brandom( 1, 8 ) )
	{
	default:
		break;
	case 1:
		G_BOTvsay_f( self, "roger", false );
		break;
	case 2:
		G_BOTvsay_f( self, "noproblem", false );
		break;
	case 3:
		G_BOTvsay_f( self, "yeehaa", false );
		break;
	case 4:
		G_BOTvsay_f( self, "yes", false );
		break;
	case 5:
		G_BOTvsay_f( self, "no", false );
		break;
	case 6:
		G_BOTvsay_f( self, "booo", false );
		break;
	case 7:
		G_BOTvsay_f( self, "attack", false );
		break;
	case 8:
		G_BOTvsay_f( self, "ok", false );
		break;
	}
}
Esempio n. 10
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;
	}
}
Esempio n. 11
0
void G_Say_Team( edict_t *who, char *msg, bool checkflood )
{
	char outmsg[256];
	char buf[256];
	char *p;
	char current_color[3];

	if( who->s.team != TEAM_SPECTATOR && ( !GS_TeamBasedGametype() || GS_InvidualGameType() ) )
	{
		Cmd_Say_f( who, false, true );
		return;
	}

	if( checkflood )
	{
		if( CheckFlood( who, true ) )
			return;
	}

	if( *msg == '\"' )
	{
		msg[strlen( msg ) - 1] = 0;
		msg++;
	}

	if( who->s.team == TEAM_SPECTATOR )
	{
		// if speccing, also check for non-team flood
		if( checkflood )
		{
			if( CheckFlood( who, false ) )
				return;
		}

		G_ChatMsg( NULL, who, true, "%s", msg );
		return;
	}

	Q_strncpyz( current_color, S_COLOR_WHITE, sizeof( current_color ) );

	memset( outmsg, 0, sizeof( outmsg ) );

	UpdatePoint( who );

	for( p = outmsg; *msg && (size_t)( p - outmsg ) < sizeof( outmsg ) - 3; msg++ )
	{
		if( *msg == '%' )
		{
			buf[0] = 0;
			switch( *++msg )
			{
			case 'l':
				Say_Team_Location( who, buf, sizeof( buf ), current_color );
				break;
			case 'a':
				Say_Team_Armor( who, buf, sizeof( buf ), current_color );
				break;
			case 'h':
				Say_Team_Health( who, buf, sizeof( buf ), current_color );
				break;
			case 'b':
				Say_Team_Best_Weapons( who, buf, sizeof( buf ), current_color );
				break;
			case 'w':
				Say_Team_Current_Weapon( who, buf, sizeof( buf ), current_color );
				break;
			case 'x':
				Say_Team_Point( who, buf, sizeof( buf ), current_color );
				break;
			case 'y':
				Say_Team_Point_Location( who, buf, sizeof( buf ), current_color );
				break;
			case 'X':
				Say_Team_Pickup( who, buf, sizeof( buf ), current_color );
				break;
			case 'Y':
				Say_Team_Pickup_Location( who, buf, sizeof( buf ), current_color );
				break;
			case 'd':
				Say_Team_Drop( who, buf, sizeof( buf ), current_color );
				break;
			case 'D':
				Say_Team_Drop_Location( who, buf, sizeof( buf ), current_color );
				break;
			case '%':
				*p++ = *msg;
				break;
			default:
				// Maybe add a warning here?
				*p++ = '%';
				*p++ = *msg;
				break;
			}
			if( strlen( buf ) + ( p - outmsg ) < sizeof( outmsg ) - 3 )
			{
				Q_strncatz( outmsg, buf, sizeof( outmsg ) );
				p += strlen( buf );
			}
		}
		else if( *msg == '^' )
		{
			*p++ = *msg++;
			*p++ = *msg;
			Q_strncpyz( current_color, p-2, sizeof( current_color ) );
		}
		else
		{
			*p++ = *msg;
		}
	}
	*p = 0;

	G_ChatMsg( NULL, who, true, "%s", outmsg );
}