Пример #1
0
/*
 * G_ClientBeginFrame
 *
 * This will be called once for each server frame, before running
 * any other entities in the world.
 */
void G_ClientBeginFrame(g_edict_t *ent) {
	g_client_t *client;

	if (g_level.intermission_time)
		return;

	client = ent->client;

	if (ent->ground_entity) // let this be reset each frame as needed
		client->ps.pmove.pm_flags &= ~PMF_PUSHED;

	// run weapon think if it hasn't been done by a command
	if (client->weapon_think_time < g_level.time && !client->persistent.spectator)
		G_WeaponThink(ent);

	if (ent->dead) { // check for respawn conditions

		// rounds mode implies last-man-standing, force to spectator immediately if round underway
		if (g_level.rounds && g_level.round_time && g_level.time
				>= g_level.round_time) {
			client->persistent.spectator = true;
			G_ClientRespawn(ent, false);
		} else if (g_level.time > client->respawn_time
				&& (client->latched_buttons & BUTTON_ATTACK)) {
			G_ClientRespawn(ent, false); // all other respawns require a click from the player
		}
	}

	client->latched_buttons = 0;
}
Пример #2
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 );
}
Пример #3
0
/*
 * G_CheckRoundLimit
 */
static void G_CheckRoundLimit() {
	int i;
	g_edict_t *ent;
	g_client_t *cl;

	if (g_level.round_num >= (unsigned int) g_level.round_limit) { // enforce round_limit
		gi.BroadcastPrint(PRINT_HIGH, "Roundlimit hit\n");
		G_EndLevel();
		return;
	}

	// or attempt to re-join previously active players
	for (i = 0; i < sv_max_clients->integer; i++) {
		if (!g_game.edicts[i + 1].in_use)
			continue;

		ent = &g_game.edicts[i + 1];
		cl = ent->client;

		if (cl->persistent.round_num != g_level.round_num)
			continue; // they were intentionally spectating, skip them

		if (g_level.teams || g_level.ctf) { // rejoin a team
			if (cl->persistent.team)
				G_AddClientToTeam(ent, cl->persistent.team->name);
			else
				G_AddClientToTeam(ent, G_SmallestTeam()->name);
		} else
			// just rejoin the game
			cl->persistent.spectator = false;

		G_ClientRespawn(ent, false);
	}
}
Пример #4
0
/*
* G_SpawnQueue_ReleaseTeamQueue
*/
void G_SpawnQueue_ReleaseTeamQueue( int team )
{
	g_teamspawnqueue_t *queue;
	edict_t *ent;
	int count;
	bool ghost;

	if( team < TEAM_SPECTATOR || team >= GS_MAX_TEAMS )
		return;

	queue = &g_spawnQueues[team];

	if( queue->start >= queue->head )
		return;

	// try to spawn them
	for( count = 0; ( queue->start < queue->head ) && ( count < gs.maxclients ); queue->start++, count++ )
	{
		if( queue->list[queue->start % MAX_CLIENTS] <= 0 || queue->list[queue->start % MAX_CLIENTS] > gs.maxclients )
			continue;

		ent = &game.edicts[queue->list[queue->start % MAX_CLIENTS]];

		ghost = false;

		if( team == TEAM_SPECTATOR || ent->r.client->teamstate.is_coach )
			ghost = true;

		G_ClientRespawn( ent, ghost );

		// when spawning inside spectator team bring up the chase camera
		if( team == TEAM_SPECTATOR && !ent->r.client->resp.chase.active )
			G_ChasePlayer( ent, NULL, false, 0 );
	}
}
Пример #5
0
/*
 * G_ClientBegin
 *
 * Called when a client has finished connecting, and is ready
 * to be placed into the game.  This will happen every level load.
 */
void G_ClientBegin(g_edict_t *ent) {
	char welcome[256];

	int player_num = ent - g_game.edicts - 1;

	ent->client = g_game.clients + player_num;

	G_InitEdict(ent);

	G_InitClientLocals(ent->client);

	VectorClear(ent->client->cmd_angles);
	ent->client->persistent.first_frame = g_level.frame_num;

	// force spectator if match or rounds
	if (g_level.match || g_level.rounds)
		ent->client->persistent.spectator = true;
	else if (g_level.teams || g_level.ctf) {
		if (g_auto_join->value)
			G_AddClientToTeam(ent, G_SmallestTeam()->name);
		else
			ent->client->persistent.spectator = true;
	}

	// spawn them in
	G_ClientRespawn(ent, true);

	if (g_level.intermission_time) {
		G_ClientToIntermission(ent);
	} else {
		memset(welcome, 0, sizeof(welcome));

		snprintf(welcome, sizeof(welcome),
				"^2Welcome to ^7http://quake2world.net\n"
				"^2Gameplay is ^1%s\n", G_GameplayName(g_level.gameplay));

		if (g_level.teams)
			strncat(welcome, "^2Teams are enabled\n", sizeof(welcome));

		if (g_level.ctf)
			strncat(welcome, "^2CTF is enabled\n", sizeof(welcome));

		if (g_voting->value)
			strncat(welcome, "^2Voting is allowed\n", sizeof(welcome));

		gi.ClientCenterPrint(ent, "%s", welcome);
	}

	// make sure all view stuff is valid
	G_ClientEndFrame(ent);

	srand(time(NULL)); // set random seed
}
Пример #6
0
/*
 * G_BeginIntermission
 */
static void G_BeginIntermission(const char *map) {
	int i;
	g_edict_t *ent, *client;

	if (g_level.intermission_time)
		return; // already activated

	g_level.intermission_time = g_level.time;

	// respawn any dead clients
	for (i = 0; i < sv_max_clients->integer; i++) {

		client = g_game.edicts + 1 + i;

		if (!client->in_use)
			continue;

		if (client->health <= 0)
			G_ClientRespawn(client, false);
	}

	// find an intermission spot
	ent = G_Find(NULL, FOFS(class_name), "info_player_intermission");
	if (!ent) { // map does not have an intermission point
		ent = G_Find(NULL, FOFS(class_name), "info_player_start");
		if (!ent)
			ent = G_Find(NULL, FOFS(class_name), "info_player_deathmatch");
	}

	VectorCopy(ent->s.origin, g_level.intermission_origin);
	VectorCopy(ent->s.angles, g_level.intermission_angle);

	// move all clients to the intermission point
	for (i = 0; i < sv_max_clients->integer; i++) {

		client = g_game.edicts + 1 + i;

		if (!client->in_use)
			continue;

		G_ClientToIntermission(client);
	}

	// play a dramatic sound effect
	gi.PositionedSound(g_level.intermission_origin, g_game.edicts,
			gi.SoundIndex("weapons/bfg/hit"), ATTN_NORM);

	// stay on same level if not provided
	g_level.changemap = map && *map ? map : g_level.name;
}
Пример #7
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();
}
Пример #8
0
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 );
}
Пример #9
0
void G_Gametype_GENERIC_SetUpMatch( void )
{
	int i;

	level.gametype.readyAnnouncementEnabled = false;
	level.gametype.scoreAnnouncementEnabled = true;
	level.gametype.countdownEnabled = true;
	level.gametype.pickableItemsMask = ( level.gametype.spawnableItemsMask|level.gametype.dropableItemsMask );
	if( GS_Instagib() )
		level.gametype.pickableItemsMask &= ~G_INSTAGIB_NEGATE_ITEMMASK;

	// clear player stats and scores, team scores and respawn clients in team lists
	for( i = TEAM_PLAYERS; i < GS_MAX_TEAMS; i++ )
	{
		int j;
		g_teamlist_t *team = &teamlist[i];
		memset( &team->stats, 0, sizeof( team->stats ) );

		// respawn all clients inside the playing teams
		for( j = 0; j < team->numplayers; j++ )
		{
			edict_t *ent = &game.edicts[ team->playerIndices[j] ];
			G_ClientClearStats( ent );
			G_ClientRespawn( ent, false );
		}
	}

	// set items to be spawned with a delay
	G_Items_RespawnByType( IT_ARMOR, ARMOR_RA, 15 );
	G_Items_RespawnByType( IT_ARMOR, ARMOR_RA, 15 );
	G_Items_RespawnByType( IT_HEALTH, HEALTH_MEGA, 15 );
	G_Items_RespawnByType( IT_HEALTH, HEALTH_ULTRA, 15 );
	G_Items_RespawnByType( IT_POWERUP, 0, brandom( 20, 40 ) );
	G_Match_FreeBodyQueue();

	G_AnnouncerSound( NULL, trap_SoundIndex( va( S_ANNOUNCER_COUNTDOWN_FIGHT_1_to_2, ( rand()&1 )+1 ) ), GS_MAX_TEAMS, false, NULL );
	G_CenterPrintMsg( NULL, "FIGHT!" );
}
Пример #10
0
/*
* ClientBegin
* called when a client has finished connecting, and is ready
* to be placed into the game.  This will happen every level load.
*/
void ClientBegin( edict_t *ent )
{
	gclient_t *client = ent->r.client;
	const char *mm_login;

	memset( &client->ucmd, 0, sizeof( client->ucmd ) );
	memset( &client->level, 0, sizeof( client->level ) );
	client->level.timeStamp = level.time;
	G_Client_UpdateActivity( client ); // activity detected

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

	G_UpdatePlayerMatchMsg( ent );

	mm_login = Info_ValueForKey( client->userinfo, "cl_mm_login" );
	if( mm_login && *mm_login && client->mm_session > 0 ) {
		G_PrintMsg( NULL, "%s" S_COLOR_WHITE " (" S_COLOR_YELLOW "%s" S_COLOR_WHITE ") entered the game\n", client->netname, mm_login );
	}
	else {
		if( !level.gametype.disableObituaries || !(ent->r.svflags & SVF_FAKECLIENT ) )
			G_PrintMsg( NULL, "%s" S_COLOR_WHITE " entered the game\n", client->netname );
	}

	client->level.respawnCount = 0; // clear respawncount
	client->connecting = false;

	// schedule the next scoreboard update
	client->level.scoreboard_time = game.realtime + scoreboardInterval - ( game.realtime%scoreboardInterval );

	AI_EnemyAdded( ent );

	G_ClientEndSnapFrame( ent ); // make sure all view stuff is valid

	// let the gametype scripts now this client just entered the level
	G_Gametype_ScoreEvent( client, "enterGame", NULL );
}
Пример #11
0
/*
* Cmd_ChaseCam_f
*/
void Cmd_ChaseCam_f( edict_t *ent )
{
	bool team_only;
	const char *arg1;

	if( ent->s.team != TEAM_SPECTATOR && !ent->r.client->teamstate.is_coach )
	{
		// racesow - changed from G_Teams_JoinTeam( ent, TEAM_SPECTATOR ) as this makes
		// a second G_ChasePlayer call with followmode 0, thereby overriding the chasecam mode set here
		ent->r.client->team = TEAM_SPECTATOR;
		G_ClientRespawn( ent, true );
		// !racesow
		if( !CheckFlood( ent, false )) { // prevent 'joined spectators' spam
			G_PrintMsg( NULL, "%s%s joined the %s%s team.\n", ent->r.client->netname,
				S_COLOR_WHITE, GS_TeamName( ent->s.team ), S_COLOR_WHITE );
		}
	}

	// & 1 = scorelead
	// & 2 = powerups
	// & 4 = objectives
	// & 8 = fragger

	if( ent->r.client->teamstate.is_coach && GS_TeamBasedGametype() )
		team_only = true;
	else 
		team_only = false;

	arg1 = trap_Cmd_Argv( 1 );

	if( trap_Cmd_Argc() < 2 )
	{
		G_ChasePlayer( ent, NULL, team_only, 0 );
	}
	else if( !Q_stricmp( arg1, "auto" ) )
	{
		G_PrintMsg( ent, "Chasecam mode is 'auto'. It will follow the score leader when no powerup nor flag is carried.\n" );
		G_ChasePlayer( ent, NULL, team_only, 7 );
	}
	else if( !Q_stricmp( arg1, "carriers" ) )
	{
		G_PrintMsg( ent, "Chasecam mode is 'carriers'. It will switch to flag or powerup carriers when any of these items is picked up.\n" );
		G_ChasePlayer( ent, NULL, team_only, 6 );
	}
	else if( !Q_stricmp( arg1, "powerups" ) )
	{
		G_PrintMsg( ent, "Chasecam mode is 'powerups'. It will switch to powerup carriers when any of these items is picked up.\n" );
		G_ChasePlayer( ent, NULL, team_only, 2 );
	}
	else if( !Q_stricmp( arg1, "objectives" ) )
	{
		G_PrintMsg( ent, "Chasecam mode is 'objectives'. It will switch to objectives carriers when any of these items is picked up.\n" );
		G_ChasePlayer( ent, NULL, team_only, 4 );
	}
	else if( !Q_stricmp( arg1, "score" ) )
	{
		G_PrintMsg( ent, "Chasecam mode is 'score'. It will always follow the player with the best score.\n" );
		G_ChasePlayer( ent, NULL, team_only, 1 );
	}
	else if( !Q_stricmp( arg1, "fragger" ) )
	{
		G_PrintMsg( ent, "Chasecam mode is 'fragger'. The last fragging player will be followed.\n" );
		G_ChasePlayer( ent, NULL, team_only, 8 );
	}
	else if( !Q_stricmp( arg1, "help" ) )
	{
		G_PrintMsg( ent, "Chasecam modes:\n" );
		G_PrintMsg( ent, "- 'auto': Chase the score leader unless there's an objective carrier or a powerup carrier.\n" );
		G_PrintMsg( ent, "- 'carriers': User has pov control unless there's an objective carrier or a powerup carrier.\n" );
		G_PrintMsg( ent, "- 'objectives': User has pov control unless there's an objective carrier.\n" );
		G_PrintMsg( ent, "- 'powerups': User has pov control unless there's a flag carrier.\n" );
		G_PrintMsg( ent, "- 'score': Always follow the score leader. User has no pov control.\n" );
		G_PrintMsg( ent, "- 'none': Disable chasecam.\n" );
		return;
	}
	else
	{
		G_ChasePlayer( ent, arg1, team_only, 0 );
	}

	G_Teams_LeaveChallengersQueue( ent );
}
Пример #12
0
/*
 * G_CheckRules
 */
static void G_CheckRules(void) {
	int i, seconds;
	g_client_t *cl;

	if (g_level.intermission_time)
		return;

	// match mode, no match, or countdown underway
	g_level.warmup = g_level.match && (!g_level.match_time
			|| g_level.match_time > g_level.time);

	// arena mode, no round, or countdown underway
	g_level.warmup |= g_level.rounds && (!g_level.round_time
			|| g_level.round_time > g_level.time);

	if (g_level.start_match && g_level.time >= g_level.match_time) { // players have readied, begin match
		g_level.start_match = false;
		g_level.warmup = false;

		for (i = 0; i < sv_max_clients->integer; i++) {
			if (!g_game.edicts[i + 1].in_use)
				continue;
			G_ClientRespawn(&g_game.edicts[i + 1], false);
		}

		gi.Sound(&g_game.edicts[0], gi.SoundIndex("world/teleport"), ATTN_NONE);
		gi.BroadcastPrint(PRINT_HIGH, "Match has started\n");
	}

	if (g_level.start_round && g_level.time >= g_level.round_time) { // pre-game expired, begin round
		g_level.start_round = false;
		g_level.warmup = false;

		for (i = 0; i < sv_max_clients->integer; i++) {
			if (!g_game.edicts[i + 1].in_use)
				continue;
			G_ClientRespawn(&g_game.edicts[i + 1], false);
		}

		gi.Sound(&g_game.edicts[0], gi.SoundIndex("world/teleport"), ATTN_NONE);
		gi.BroadcastPrint(PRINT_HIGH, "Round has started\n");
	}

	seconds = g_level.time;

	if (g_level.rounds) {
		if (g_level.round_time > g_level.time) // round about to start, show pre-game countdown
			seconds = g_level.round_time - g_level.time;
		else if (g_level.round_time)
			seconds = g_level.time - g_level.round_time; // round started, count up
		else
			seconds = -1;
	} else if (g_level.match) {
		if (g_level.match_time > g_level.time) // match about to start, show pre-game countdown
			seconds = g_level.match_time - g_level.time;
		else if (g_level.match_time) {
			if (g_level.time_limit) // count down to time_limit
				seconds = g_level.match_time + g_level.time_limit * 60
						- g_level.time;
			else
				seconds = g_level.time - g_level.match_time; // count up
		} else
			seconds = -1;
	}

	if (g_level.time_limit) { // check time_limit
		float t = g_level.time;

		if (g_level.match) // for matches
			t = g_level.time - g_level.match_time;
		else if (g_level.rounds) // and for rounds
			t = g_level.time - g_level.round_time;

		if (t >= g_level.time_limit * 60) {
			gi.BroadcastPrint(PRINT_HIGH, "Timelimit hit\n");
			G_EndLevel();
			return;
		}
		seconds = g_level.time_limit * 60 - t; // count down
	}

	if (g_level.frame_num % gi.frame_rate == 0) // send time updates once per second
		gi.ConfigString(CS_TIME,
				(g_level.warmup ? "Warmup" : G_FormatTime(seconds)));

	if (!g_level.ctf && g_level.frag_limit) { // check frag_limit

		if (g_level.teams) { // check team scores
			if (g_team_good.score >= g_level.frag_limit ||
					g_team_evil.score >= g_level.frag_limit) {
				gi.BroadcastPrint(PRINT_HIGH, "Fraglimit hit\n");
				G_EndLevel();
				return;
			}
		} else { // or individual scores
			for (i = 0; i < sv_max_clients->integer; i++) {
				cl = g_game.clients + i;
				if (!g_game.edicts[i + 1].in_use)
					continue;

				if (cl->persistent.score >= g_level.frag_limit) {
					gi.BroadcastPrint(PRINT_HIGH, "Fraglimit hit\n");
					G_EndLevel();
					return;
				}
			}
		}
	}

	if (g_level.ctf && g_level.capture_limit) { // check capture limit

		if (g_team_good.captures >= g_level.capture_limit || g_team_evil.captures
				>= g_level.capture_limit) {
			gi.BroadcastPrint(PRINT_HIGH, "Capturelimit hit\n");
			G_EndLevel();
			return;
		}
	}

	if (g_gameplay->modified) { // change gameplay, fix items, respawn clients
		g_gameplay->modified = false;

		g_level.gameplay = G_GameplayByName(g_gameplay->string);
		gi.ConfigString(CS_GAMEPLAY, va("%d", g_level.gameplay));

		G_RestartGame(false); // reset all clients

		gi.BroadcastPrint(PRINT_HIGH, "Gameplay has changed to %s\n",
				G_GameplayName(g_level.gameplay));
	}

	if (g_gravity->modified) { // send gravity config string
		g_gravity->modified = false;

		g_level.gravity = g_gravity->integer;
		gi.ConfigString(CS_GRAVITY, va("%d", g_level.gravity));
	}

	if (g_teams->modified) { // reset teams, scores
		g_teams->modified = false;

		g_level.teams = g_teams->integer;
		gi.ConfigString(CS_TEAMS, va("%d", g_level.teams));

		gi.BroadcastPrint(PRINT_HIGH, "Teams have been %s\n",
				g_level.teams ? "enabled" : "disabled");

		G_RestartGame(true);
	}

	if (g_ctf->modified) { // reset teams, scores
		g_ctf->modified = false;

		g_level.ctf = g_ctf->integer;
		gi.ConfigString(CS_CTF, va("%d", g_level.ctf));

		gi.BroadcastPrint(PRINT_HIGH, "CTF has been %s\n",
				g_level.ctf ? "enabled" : "disabled");

		G_RestartGame(true);
	}

	if (g_match->modified) { // reset scores
		g_match->modified = false;

		g_level.match = g_match->integer;
		gi.ConfigString(CS_MATCH, va("%d", g_level.match));

		g_level.warmup = g_level.match; // toggle warmup

		gi.BroadcastPrint(PRINT_HIGH, "Match has been %s\n",
				g_level.match ? "enabled" : "disabled");

		G_RestartGame(false);
	}

	if (g_rounds->modified) { // reset scores
		g_rounds->modified = false;

		g_level.rounds = g_rounds->integer;
		gi.ConfigString(CS_ROUNDS, va("%d", g_level.rounds));

		g_level.warmup = g_level.rounds; // toggle warmup

		gi.BroadcastPrint(PRINT_HIGH, "Rounds have been %s\n",
				g_level.rounds ? "enabled" : "disabled");

		G_RestartGame(false);
	}

	if (g_cheats->modified) { // notify when cheats changes
		g_cheats->modified = false;

		gi.BroadcastPrint(PRINT_HIGH, "Cheats have been %s\n",
				g_cheats->integer ? "enabled" : "disabled");
	}

	if (g_frag_limit->modified) {
		g_frag_limit->modified = false;
		g_level.frag_limit = g_frag_limit->integer;

		gi.BroadcastPrint(PRINT_HIGH, "Fraglimit has been changed to %d\n",
				g_level.frag_limit);
	}

	if (g_round_limit->modified) {
		g_round_limit->modified = false;
		g_level.round_limit = g_round_limit->integer;

		gi.BroadcastPrint(PRINT_HIGH, "Roundlimit has been changed to %d\n",
				g_level.round_limit);
	}

	if (g_capture_limit->modified) {
		g_capture_limit->modified = false;
		g_level.capture_limit = g_capture_limit->integer;

		gi.BroadcastPrint(PRINT_HIGH, "Capturelimit has been changed to %d\n",
				g_level.capture_limit);
	}

	if (g_time_limit->modified) {
		g_time_limit->modified = false;
		g_level.time_limit = g_time_limit->value;

		gi.BroadcastPrint(PRINT_HIGH, "Timelimit has been changed to %d\n",
				(int) g_level.time_limit);
	}
}
Пример #13
0
/*
 * G_RestartGame
 *
 * For normal games, this just means reset scores and respawn.
 * For match games, this means cancel the match and force everyone
 * to ready again.  Teams are only reset when teamz is true.
 */
static void G_RestartGame(boolean_t teamz) {
	int i;
	g_edict_t *ent;
	g_client_t *cl;

	if (g_level.match_time)
		g_level.match_num++;

	if (g_level.round_time)
		g_level.round_num++;

	for (i = 0; i < sv_max_clients->integer; i++) { // reset clients

		if (!g_game.edicts[i + 1].in_use)
			continue;

		ent = &g_game.edicts[i + 1];
		cl = ent->client;

		cl->persistent.ready = false; // back to warmup
		cl->persistent.score = 0;
		cl->persistent.captures = 0;

		if (teamz) // reset teams
			cl->persistent.team = NULL;

		// determine spectator or team affiliations

		if (g_level.match) {
			if (cl->persistent.match_num == g_level.match_num)
				cl->persistent.spectator = false;
			else
				cl->persistent.spectator = true;
		}

		else if (g_level.rounds) {
			if (cl->persistent.round_num == g_level.round_num)
				cl->persistent.spectator = false;
			else
				cl->persistent.spectator = true;
		}

		if (g_level.teams || g_level.ctf) {

			if (!cl->persistent.team) {
				if (g_auto_join->value)
					G_AddClientToTeam(ent, G_SmallestTeam()->name);
				else
					cl->persistent.spectator = true;
			}
		}

		G_ClientRespawn(ent, false);
	}

	G_ResetItems();

	g_level.match_time = g_level.round_time = 0;
	g_team_good.score = g_team_evil.score = 0;
	g_team_good.captures = g_team_evil.captures = 0;

	gi.BroadcastPrint(PRINT_HIGH, "Game restarted\n");
	gi.Sound(&g_game.edicts[0], gi.SoundIndex("world/teleport"), ATTN_NONE);
}
Пример #14
0
/*
* G_SpawnQueue_Think
*/
void G_SpawnQueue_Think( void )
{
	int team, maxCount, count, spawnSystem;
	g_teamspawnqueue_t *queue;
	edict_t *ent;
	bool ghost;

	for( team = TEAM_SPECTATOR; team < GS_MAX_TEAMS; team++ )
	{
		queue = &g_spawnQueues[team];

		// if the system is limited, set limits
		maxCount = MAX_CLIENTS;

		spawnSystem = queue->system;
		clamp( spawnSystem, SPAWNSYSTEM_INSTANT, SPAWNSYSTEM_HOLD );

		switch( spawnSystem )
		{
		case SPAWNSYSTEM_INSTANT:
		default:
			break;

		case SPAWNSYSTEM_WAVES:
			if( queue->nextWaveTime > level.time )
			{
				maxCount = 0;
			}
			else
			{
				maxCount = ( queue->wave_maxcount < 1 ) ? gs.maxclients : queue->wave_maxcount; // max count per reinforcement wave
				queue->nextWaveTime = level.time + ( queue->wave_time * 1000 );
			}
			break;

		case SPAWNSYSTEM_HOLD:
			maxCount = 0; // players wait to be spawned elsewhere
			break;
		}

		if( maxCount <= 0 )
			continue;

		if( queue->start >= queue->head )
			continue;

		// try to spawn them
		for( count = 0; ( queue->start < queue->head ) && ( count < maxCount ); queue->start++, count++ )
		{
			if( queue->list[queue->start % MAX_CLIENTS] <= 0 || queue->list[queue->start % MAX_CLIENTS] > gs.maxclients )
				continue;

			ent = &game.edicts[queue->list[queue->start % MAX_CLIENTS]];

			ghost = false;

			if( team == TEAM_SPECTATOR || ent->r.client->teamstate.is_coach )
				ghost = true;

			G_ClientRespawn( ent, ghost );

			// when spawning inside spectator team bring up the chase camera
			if( team == TEAM_SPECTATOR && !ent->r.client->resp.chase.active )
				G_ChasePlayer( ent, NULL, false, 0 );
		}
	}
}