示例#1
0
/*
===========
PlayerBegin

called when a player has finished connecting, and is ready
to be placed into the level.  This will happen every level load,
and on transition between teams, but doesn't happen on respawns
============
*/
void PlayerBegin( int playerNum ) {
	gentity_t	*ent;
	gplayer_t	*player;
	int			flags;
	int			i;

	ent = g_entities + playerNum;

	player = level.players + playerNum;

	if ( ent->r.linked ) {
		trap_UnlinkEntity( ent );
	}
	G_InitGentity( ent );
	ent->touch = 0;
	ent->pain = 0;
	ent->player = player;

	player->pers.connected = CON_CONNECTED;
	player->pers.enterTime = level.time;
	player->pers.teamState.state = TEAM_BEGIN;

	// save eflags around this, because changing teams will
	// cause this to happen with a valid entity, and we
	// want to make sure the teleport bit is set right
	// so the viewpoint doesn't interpolate through the
	// world to the new position
	flags = player->ps.eFlags;
	memset( &player->ps, 0, sizeof( player->ps ) );
	player->ps.eFlags = flags;

	// locate ent at a spawn point
	PlayerSpawn( ent );

	if ( player->pers.initialSpawn && g_gametype.integer != GT_TOURNAMENT ) {
		// This is only sent to bots because for humans the "joining the battle" etc
		// make it clear that the player is now finished connecting. Bots on the other
		// hand have "entered the game" hard coded in botfiles/match.c so continue to
		// send it to them.
		for ( i = 0; i < level.maxplayers; i++ ) {
			if ( level.players[i].pers.connected == CON_DISCONNECTED ) {
				continue;
			}
			if ( !(g_entities[i].r.svFlags & SVF_BOT) ) {
				continue;
			}

			trap_SendServerCommand( i, va("print \"%s" S_COLOR_WHITE " entered the game\n\"", player->pers.netname) );
		}

		if ( !g_singlePlayer.integer ) {
			BroadcastTeamChange( player, -1 );
		}
	}
	player->pers.initialSpawn = qfalse;
	G_LogPrintf( "PlayerBegin: %i\n", playerNum );

	// count current players and rank for scoreboard
	CalculateRanks();
}
示例#2
0
/*
================
G_InitSessionData

Called on a first-time connect
================
*/
void G_InitSessionData( gclient_t *client, char *userinfo ) {
	clientSession_t	*sess;
	const char		*value;

	sess = &client->sess;

	// initial team determination
	if ( g_gametype.integer >= GT_TEAM ) {
		if ( g_teamAutoJoin.integer && !(g_entities[ client - level.clients ].r.svFlags & SVF_BOT) ) {
			sess->sessionTeam = PickTeam( -1 );
			BroadcastTeamChange( client, -1 );
		} else {
			// always spawn as spectator in team games
			sess->sessionTeam = TEAM_SPECTATOR;	
		}
	} else {
		value = Info_ValueForKey( userinfo, "team" );
		if ( value[0] == 's' ) {
			// a willing spectator, not a waiting-in-line
			sess->sessionTeam = TEAM_SPECTATOR;
		} else {
			switch ( g_gametype.integer ) {
			default:
			case GT_FFA:
			case GT_SINGLE_PLAYER:
				if ( g_maxGameClients.integer > 0 && 
					level.numNonSpectatorClients >= g_maxGameClients.integer ) {
					sess->sessionTeam = TEAM_SPECTATOR;
				} else {
					sess->sessionTeam = TEAM_FREE;
				}
				break;
			case GT_TOURNAMENT:
				// if the game is full, go into a waiting mode
				if ( level.numNonSpectatorClients >= 2 ) {
					sess->sessionTeam = TEAM_SPECTATOR;
				} else {
					sess->sessionTeam = TEAM_FREE;
				}
				break;
			}
		}
	}

	sess->spectatorState = SPECTATOR_FREE;
	AddTournamentQueue(client);

	if (crandom() > 0)
		client->sess.weapon = WP_RAILGUN;
	else
		client->sess.weapon = WP_ROCKET_LAUNCHER;

	G_WriteClientSessionData( client );
}
/*
================
G_InitSessionData

Called on a first-time connect
================
*/
void G_InitSessionData( gclient_t *client, char *userinfo ) {
	clientSession_t	*sess;
	const char		*value;

	sess = &client->sess;

	// initial team determination
	if ( g_gametype.integer >= GT_TEAM ) {
		if ( g_teamAutoJoin.integer ) {
			sess->sessionTeam = PickTeam( -1 );
			BroadcastTeamChange( client, -1 );
		} else {
			// always spawn as spectator in team games
			sess->sessionTeam = TEAM_SPECTATOR;	
		}
	} else {
		value = Info_ValueForKey( userinfo, "team" );
		if ( value[0] == 's' ) {
			// a willing spectator, not a waiting-in-line
			sess->sessionTeam = TEAM_SPECTATOR;
		} else {
			switch ( g_gametype.integer ) {
			default:
			case GT_FFA:
			case GT_SINGLE_PLAYER:
				if ( g_maxGameClients.integer > 0 && 
					level.numNonSpectatorClients >= g_maxGameClients.integer ) {
					sess->sessionTeam = TEAM_SPECTATOR;
				} else {
					sess->sessionTeam = TEAM_FREE;
				}
				break;
			case GT_TOURNAMENT:
				// if the game is full, go into a waiting mode
				if ( level.numNonSpectatorClients >= 2 ) {
					sess->sessionTeam = TEAM_SPECTATOR;
				} else {
					sess->sessionTeam = TEAM_FREE;
				}
				break;
			}
		}
	}

	sess->spectatorState = SPECTATOR_FREE;
	sess->spectatorTime = level.time;

	G_WriteClientSessionData( client );
}
示例#4
0
/*
================
G_InitSessionData

Called on a first-time connect
================
*/
void G_InitSessionData( gclient_t *client, char *userinfo ) 
{
	clientSession_t	*sess;
	const char		*value;

	sess = &client->sess;

	// initial team determination
	if ( level.gametypeData->teams ) 
	{
		if ( g_teamAutoJoin.integer ) 
		{
			sess->team = PickTeam( -1 );
			BroadcastTeamChange( client, -1 );
		} 
		else 
		{
			// always spawn as spectator in team games
			sess->team = TEAM_SPECTATOR;	
		}
	} 
	else 
	{
		value = Info_ValueForKey( userinfo, "team" );
		if ( value[0] == 's' ) 
		{
			// a willing spectator, not a waiting-in-line
			sess->team = TEAM_SPECTATOR;
		} 
		else 
		{
			if ( g_maxGameClients.integer > 0 && level.numNonSpectatorClients >= g_maxGameClients.integer ) 
			{
				sess->team = TEAM_SPECTATOR;
			} 
			else 
			{
				sess->team = TEAM_FREE;
			}
		}
	}

	sess->spectatorState = SPECTATOR_FREE;
	sess->spectatorTime = level.time;

	G_WriteClientSessionData( client );
}
示例#5
0
/*
===========
PlayerBegin

called when a player has finished connecting, and is ready
to be placed into the level.  This will happen every level load,
and on transition between teams, but doesn't happen on respawns
============
*/
void PlayerBegin( int playerNum ) {
	gentity_t	*ent;
	gplayer_t	*player;
	int			flags;

	ent = g_entities + playerNum;

	player = level.players + playerNum;

	if ( ent->r.linked ) {
		trap_UnlinkEntity( ent );
	}
	G_InitGentity( ent );
	ent->touch = 0;
	ent->pain = 0;
	ent->player = player;

	player->pers.connected = CON_CONNECTED;
	player->pers.enterTime = level.time;
	player->pers.teamState.state = TEAM_BEGIN;

	// save eflags around this, because changing teams will
	// cause this to happen with a valid entity, and we
	// want to make sure the teleport bit is set right
	// so the viewpoint doesn't interpolate through the
	// world to the new position
	flags = player->ps.eFlags;
	memset( &player->ps, 0, sizeof( player->ps ) );
	player->ps.eFlags = flags;

	// locate ent at a spawn point
	PlayerSpawn( ent );

	if ( player->pers.initialSpawn && !g_singlePlayer.integer ) {
		if ( g_gametype.integer != GT_TOURNAMENT ) {
			BroadcastTeamChange( player, -1 );
		}
	}
	player->pers.initialSpawn = qfalse;
	G_LogPrintf( "PlayerBegin: %i\n", playerNum );

	// count current players and rank for scoreboard
	CalculateRanks();
}
示例#6
0
/* LQ3A: Added bBroadcast parameter to allow the calling function to suppress the change. */
void SetTeam( gentity_t *ent, char *s, qboolean bBroadcast) {
	/* LQ3A */
	team_t				team, oldTeam;

	gclient_t			*client;
	int					clientNum;
	spectatorState_t	specState;
	int					specClient;
	int					teamLeader;

	//
	// see what change is requested
	//
	client = ent->client;

	clientNum = client - level.clients;
	specClient = 0;
	specState = SPECTATOR_NOT;
	if ( !Q_stricmp( s, "scoreboard" ) || !Q_stricmp( s, "score" )  ) {
		team = TEAM_SPECTATOR;
		specState = SPECTATOR_SCOREBOARD;
	} else if ( !Q_stricmp( s, "follow1" ) ) {
		team = TEAM_SPECTATOR;
		specState = SPECTATOR_FOLLOW;
		specClient = -1;
	} else if ( !Q_stricmp( s, "follow2" ) ) {
		team = TEAM_SPECTATOR;
		specState = SPECTATOR_FOLLOW;
		specClient = -2;
	} else if ( !Q_stricmp( s, "spectator" ) || !Q_stricmp( s, "s" ) ) {
		team = TEAM_SPECTATOR;
		specState = SPECTATOR_FREE;
	} else if ( g_gametype.integer >= GT_TEAM ) {
		// if running a team game, assign player to one of the teams
		specState = SPECTATOR_NOT;
		if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) ) {
			team = TEAM_RED;
		} else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) {
			team = TEAM_BLUE;
		} else {
			// pick the team with the least number of players
			team = PickTeam( clientNum );
		}

		if ( g_teamForceBalance.integer  ) {
			int		counts[TEAM_NUM_TEAMS];

			counts[TEAM_BLUE] = TeamCount( ent->client->ps.clientNum, TEAM_BLUE );
			counts[TEAM_RED] = TeamCount( ent->client->ps.clientNum, TEAM_RED );

			// We allow a spread of two
			if ( team == TEAM_RED && counts[TEAM_RED] - counts[TEAM_BLUE] > 1 ) {
				trap_SendServerCommand( ent->client->ps.clientNum, 
					"cp \"Red team has too many players.\n\"" );
				return; // ignore the request
			}
			if ( team == TEAM_BLUE && counts[TEAM_BLUE] - counts[TEAM_RED] > 1 ) {
				trap_SendServerCommand( ent->client->ps.clientNum, 
					"cp \"Blue team has too many players.\n\"" );
				return; // ignore the request
			}

			// It's ok, the team we are switching to has less or same number of players
		}

	} else {
		// force them to spectators if there aren't any spots free
		/* LQ3A */
		team = ((client->sess.sessionTeam == TEAM_FREE) ||
			((client->sess.sessionTeam != TEAM_FREE) && LQ3A_GetVacantPlayerSlots())) ? TEAM_FREE : TEAM_SPECTATOR;
	}

	// override decision if limiting the players
	if ( (g_gametype.integer == GT_TOURNAMENT)
		&& level.numNonSpectatorClients >= 2 ) {
		team = TEAM_SPECTATOR;
	} else if ( g_maxGameClients.integer > 0 && 
		level.numNonSpectatorClients > g_maxGameClients.integer ) {
		team = TEAM_SPECTATOR;
	}

	//
	// decide if we will allow the change
	//
	oldTeam = client->sess.sessionTeam;
	/* LQ3A */
	if ( team == oldTeam /*&& team != TEAM_SPECTATOR*/ ) {
		return;
	}

	/* LQ3A: Ensure we're allowed to spectate. */
	if ((team == TEAM_SPECTATOR) && !LQ3A_CanClientSpectate(ent))
	{
		return;
	}

	//
	// execute the team change
	//

	// if the player was dead leave the body
	if ( client->ps.stats[STAT_HEALTH] <= 0 ) {
		CopyToBodyQue(ent);
	}

	// he starts at 'base'
	client->pers.teamState.state = TEAM_BEGIN;

	/* LQ3A*/
	if (oldTeam == TEAM_SPECTATOR)
	{
		ent->r.svFlags &= ~SVF_NOCLIENT;
		client->pers.enterTime += (level.time - client->sess.spectatorTime);

		/* Restore the players score. */
		client->ps.persistant[PERS_SCORE] = client->pers.iScore;
	}
	else if (ent->client->ps.stats[STAT_HEALTH] > 0)
	{
		// Kill him (makes sure he loses flags, etc)
		ent->flags &= ~FL_GODMODE;

		/* LQ3A: Kill the player if they have too little health. */
		if ((g_spectatorFreePass.integer > 0) && (ent->client->ps.stats[STAT_HEALTH] < g_spectatorFreePass.integer))
		{
			ent->client->ps.stats[STAT_HEALTH] = ent->health = 0;
			player_die (ent, ent, ent, 100000, MOD_SUICIDE);
		}
		else
		{
			/* LQ3A: Drop items and return flags when we're allowed
				to become a spectator without commiting suicide. */

			// if client is in a nodrop area, don't drop anything (but return CTF flags!)
			if (!(trap_PointContents(ent->r.currentOrigin, -1) & CONTENTS_NODROP))
			{
				TossClientItems(ent);
			}
			else 
			{
				if (ent->client->ps.powerups[PW_NEUTRALFLAG])
				{
					Team_ReturnFlag(TEAM_FREE);
				}
				else if (ent->client->ps.powerups[PW_REDFLAG])
				{
					Team_ReturnFlag(TEAM_RED);
				}
				else if (ent->client->ps.powerups[PW_BLUEFLAG])
				{
					Team_ReturnFlag(TEAM_BLUE);
				}
			}
#ifdef MISSIONPACK
			TossClientPersistantPowerups(ent);

			if(g_gametype.integer == GT_HARVESTER)
			{
				TossClientCubes(ent);
			}
#endif
		}

	}
	// they go to the end of the line for tournements
	if ( team == TEAM_SPECTATOR ) {

		/* LQ3A */
		LQ3A_CompleteClientMoveToSpectatorTeam(ent);
	}

	client->sess.sessionTeam = team;
	client->sess.spectatorState = specState;
	client->sess.spectatorClient = specClient;

	client->sess.teamLeader = qfalse;
	if ( team == TEAM_RED || team == TEAM_BLUE ) {
		teamLeader = TeamLeader( team );
		// if there is no team leader or the team leader is a bot and this client is not a bot
		if ( teamLeader == -1 || ( !(g_entities[clientNum].r.svFlags & SVF_BOT) && (g_entities[teamLeader].r.svFlags & SVF_BOT) ) ) {
			SetLeader( team, clientNum );
		}
	}
	// make sure there is a team leader on the team the player came from
	if ( oldTeam == TEAM_RED || oldTeam == TEAM_BLUE ) {
		CheckTeamLeader( oldTeam );
	}

	/* LQ3A: Broadcast the change when instructed to do so. */
	if (bBroadcast)
	{
		BroadcastTeamChange(client, oldTeam);
	}

	// get and distribute relevent paramters
	ClientUserinfoChanged( clientNum );

	/* LQ3A */
	if (team != TEAM_SPECTATOR)
	{
		/* Spawn the client into the game. */
		ClientBegin(clientNum);
	}
	else
	{
		/* Update the cached scores. */
		CalculateRanks();
	}
}
示例#7
0
/*
================
G_InitSessionData

Called on a first-time connect
================
*/
void G_InitSessionData( gclient_t *client, char *userinfo, qboolean isBot ) {
	clientSession_t	*sess;
	const char		*value;

	sess = &client->sess;

	client->sess.siegeDesiredTeam = TEAM_FREE;

	// initial team determination
	if ( g_gametype.integer >= GT_TEAM ) {
		if ( g_teamAutoJoin.integer ) {
			sess->sessionTeam = PickTeam( -1 );
			BroadcastTeamChange( client, -1 );
		} else {
			// always spawn as spectator in team games
			if (!isBot)
			{
				sess->sessionTeam = TEAM_SPECTATOR;	
			}
			else
			{ //Bots choose their team on creation
				value = Info_ValueForKey( userinfo, "team" );
				if (value[0] == 'r' || value[0] == 'R')
				{
					sess->sessionTeam = TEAM_RED;
				}
				else if (value[0] == 'b' || value[0] == 'B')
				{
					sess->sessionTeam = TEAM_BLUE;
				}
				else
				{
					sess->sessionTeam = PickTeam( -1 );
				}
				BroadcastTeamChange( client, -1 );
			}
		}
	} else {
		value = Info_ValueForKey( userinfo, "team" );
		if ( value[0] == 's' ) {
			// a willing spectator, not a waiting-in-line
			sess->sessionTeam = TEAM_SPECTATOR;
		} else {
			switch ( g_gametype.integer ) {
			default:
			case GT_FFA:
			case GT_HOLOCRON:
			case GT_JEDIMASTER:
			case GT_SINGLE_PLAYER:
				if ( g_maxGameClients.integer > 0 && 
					level.numNonSpectatorClients >= g_maxGameClients.integer ) {
					sess->sessionTeam = TEAM_SPECTATOR;
				} else {
					sess->sessionTeam = TEAM_FREE;
				}
				break;
			case GT_DUEL:
				// if the game is full, go into a waiting mode
				if ( level.numNonSpectatorClients >= 2 ) {
					sess->sessionTeam = TEAM_SPECTATOR;
				} else {
					sess->sessionTeam = TEAM_FREE;
				}
				break;
			case GT_POWERDUEL:
				//sess->duelTeam = DUELTEAM_LONE; //default
				{
					int loners = 0;
					int doubles = 0;

					G_PowerDuelCount(&loners, &doubles, qtrue);

					if (!doubles || loners > (doubles/2))
					{
						sess->duelTeam = DUELTEAM_DOUBLE;
					}
					else
					{
						sess->duelTeam = DUELTEAM_LONE;
					}
				}
				sess->sessionTeam = TEAM_SPECTATOR;
				break;
			}
		}
	}

	sess->spectatorState = SPECTATOR_FREE;
	sess->spectatorTime = level.time;

	sess->siegeClass[0] = 0;
	sess->saberType[0] = 0;
	sess->saber2Type[0] = 0;

	G_WriteClientSessionData( client );
}
示例#8
0
/*
===========
ClientConnect

Called when a player begins connecting to the server.
Called again for every map change or tournement restart.

The session information will be valid after exit.

Return NULL if the client should be allowed, otherwise return
a string with the reason for denial.

Otherwise, the client will be sent the current gamestate
and will eventually get to ClientBegin.

firstTime will be qtrue the very first time a client connects
to the server machine, but qfalse on map changes and tournement
restarts.
============
*/
char           *ClientConnect(int clientNum, qboolean firstTime, qboolean isBot)
{
  char           *value;

//  char        *areabits;
  gclient_t      *client;
  char            userinfo[MAX_INFO_STRING];
  char            reason[MAX_STRING_CHARS] = "";
  gentity_t      *ent;

  ent = &g_entities[clientNum];

  trap_GetUserinfo(clientNum, userinfo, sizeof(userinfo));
  trap_LoadPlayerWeapons(clientNum, rr_weaponsAllowed.string);

  // IP filtering
  // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=500
  // recommanding PB based IP / GUID banning, the builtin system is pretty limited
  // check to see if they are on the banned IP list
  value = Info_ValueForKey(userinfo, "ip");
  if(G_FilterPacket(value))
  {
    return "You are banned from this server.";
  }

  // we don't check password for bots and local client
  // NOTE: local client <-> "ip" "localhost"
  //   this means this client is not running in our current process
  if(!isBot && (strcmp(value, "localhost") != 0))
  {
    // check for a password
    value = Info_ValueForKey(userinfo, "password");
    if(g_password.string[0] && Q_stricmp(g_password.string, "none") && strcmp(g_password.string, value) != 0)
    {
      return "Invalid password";
    }
  }

#ifdef G_LUA
  // Lua API callbacks (check with Lua scripts)
  if(G_LuaHook_ClientConnect(clientNum, firstTime, isBot, reason))
  {
    return "Connection Rejected by lua module.";
  }
#endif

  // they can connect
  ent->client = level.clients + clientNum;
  client = ent->client;

//  areabits = client->areabits;

  memset(client, 0, sizeof(*client));

  client->pers.connected = CON_CONNECTING;

  // read or initialize the session data
  if(firstTime || level.newSession)
  {
    G_InitSessionData(client, userinfo);
  }
  G_ReadSessionData(client);

  // Tr3B: add SVF_CAPSULE to players so we can trace against the rotated capsules
  // in the server entity tracing code SV_ClipToEntity
  // FIXME UPDATE: this seems to break the box traces against the player capsules by entities like rockets
  // it should be a bug in CM_TraceBoundingBoxThroughCapsule
  //ent->r.svFlags |= SVF_CAPSULE;

  if(isBot)
  {
    ent->r.svFlags |= SVF_BOT;
    ent->inuse = qtrue;

#if defined(BRAINWORKS)
    if(!G_BotConnect(clientNum, !firstTime))
    {
      return "BotConnectfailed";
    }
#elif defined(ACEBOT)
    if(!ACESP_BotConnect(clientNum, !firstTime))
    {
      return "BotConnectfailed";
    }
#else
    return "BotConnectfailed";
#endif
  }

  // get and distribute relevent paramters
  G_LogPrintf("ClientConnect: %i\n", clientNum);
  ClientUserinfoChanged(clientNum);

  // don't do the "xxx connected" messages if they were caried over from previous level
  if(firstTime)
  {
    trap_SendServerCommand(-1, va("print \"%s" S_COLOR_WHITE " connected\n\"", client->pers.netname));
  }

  if(g_gametype.integer >= GT_TEAM && client->sess.sessionTeam != TEAM_SPECTATOR)
  {
    BroadcastTeamChange(client, -1);
  }

  // count current clients and rank for scoreboard
  CalculateRanks();

  // for statistics
//  client->areabits = areabits;
//  if ( !client->areabits )
//      client->areabits = G_Alloc( (trap_AAS_PointReachabilityAreaIndex( NULL ) + 7) / 8 );

  return NULL;
}
示例#9
0
/** LQ3A: Changed return from void to qboolean.
	This function initilises the session data and assigns a team to the client,
	if we cannot assign a team it returns qfalse and the client should be dropped from the server.
	@see ClientConnect(). */
qboolean G_InitSessionData( gclient_t *client, char *userinfo ) {
	clientSession_t	*sess;
	/* LQ3A */
//	const char	*value;
	qboolean	bCanClientSpectate;
	int			iVacantPlayerSlots;

	/* LQ3A */
	UNREFERENCED_PARAMETER(userinfo);

	sess = &client->sess;

	/* LQ3A */
	bCanClientSpectate	= LQ3A_CanClientSpectate(LQ3A_ClientToEntity(client));
	iVacantPlayerSlots	= LQ3A_GetVacantPlayerSlots();

	// initial team determination
	if (g_gametype.integer >= GT_TEAM)
	{
		/* LQ3A: Added support for g_maxGameClients in team games.
			Force auto join when the client cannot spectate. */
		if (iVacantPlayerSlots && (g_teamAutoJoin.integer || !bCanClientSpectate))
		{
			sess->sessionTeam = PickTeam( -1 );
			BroadcastTeamChange( client, -1 );
		}
		else if (bCanClientSpectate)
		{
			sess->sessionTeam = TEAM_SPECTATOR;	
		}
		else
		{
			/* No vacant player slots and we cannot spectate. */
			return qfalse;
		}

	} else {

		/* LQ3A: Place clients into spectator mode by default where possible. */
		if (bCanClientSpectate)
		{
			sess->sessionTeam = TEAM_SPECTATOR;
		}
		/* If we cannot spectate, place the client in the game when there are vacant slots. */
		else if (iVacantPlayerSlots)
		{
			sess->sessionTeam = TEAM_FREE;
		}
		else
		{
			/* No vacant player slots and we cannot spectate. */
			return qfalse;
		}
	}

	sess->spectatorState = SPECTATOR_FREE;
	sess->spectatorTime = level.time;

	/* LQ3A */
	if (sess->sessionTeam == TEAM_SPECTATOR)
	{
		LQ3A_CompleteClientMoveToSpectatorTeam(LQ3A_ClientToEntity(client));
	}

	G_WriteClientSessionData( client );

	/* LQ3A */
	return qtrue;
}
示例#10
0
/** LQ3A: Changed return from void to qboolean.
	This function reads the session data from cvars and assigns a team to the client,
	if we cannot assign a team it returns qfalse and the client should be dropped from the server.
	@see ClientConnect(). */
qboolean G_ReadSessionData(gclient_t *client) {
	char	s[MAX_STRING_CHARS];
	const char	*var;

	// bk001205 - format
	int teamLeader;
	int spectatorState;
	int sessionTeam;
	/* LQ3A */
	qboolean bCanClientSpectate;

	var = va( "session%i", client - level.clients );
	trap_Cvar_VariableStringBuffer( var, s, sizeof(s) );

	sscanf( s, "%i %i %i %i %i %i %i",
		&sessionTeam,                 // bk010221 - format
		&client->sess.spectatorTime,
		&spectatorState,              // bk010221 - format
		&client->sess.spectatorClient,
		&client->sess.wins,
		&client->sess.losses,
		&teamLeader                   // bk010221 - format
		);

	/* LQ3A */
	bCanClientSpectate = LQ3A_CanClientSpectate(LQ3A_ClientToEntity(client));

	/* Place clients into the same teams they were in previously. */
	if (g_gametype.integer >= GT_TEAM)
	{
		client->sess.sessionTeam = (team_t)sessionTeam;

		/* Force spectators into the game if we can no longer spectate. */
		if ((client->sess.sessionTeam == TEAM_SPECTATOR) && !bCanClientSpectate)
		{
			client->sess.sessionTeam = PickTeam(-1);
			BroadcastTeamChange(client, -1);
		}
	}
	/* Always default as spectator. */
	else if (bCanClientSpectate)
	{
		client->sess.sessionTeam = TEAM_SPECTATOR;
	}
	/* If we cannot spectate, can we join the game? */
	else if (LQ3A_GetVacantPlayerSlots())
	{
		client->sess.sessionTeam = TEAM_FREE;
	}
	else
	{
		/* No vacant player slots and we cannot spectate. */
		return qfalse;
	}

	if (client->sess.sessionTeam == TEAM_SPECTATOR)
	{
		/* Force free floating spectator mode each level load. */
		client->sess.spectatorState		= SPECTATOR_FREE;
		client->sess.spectatorClient	= 0;
	}

	client->sess.teamLeader = (qboolean)teamLeader;

	/* LQ3A */
	return qtrue;
}
示例#11
0
/*
=================
SetTeam
=================
*/
void SetTeam( gentity_t *ent, char *s ) {
	int					team, oldTeam;
	gclient_t			*client;
	int					clientNum;
	spectatorState_t	specState;
	int					specClient;
	int					teamLeader;

	//
	// see what change is requested
	//
	client = ent->client;

	clientNum = client - level.clients;
	specClient = 0;
	specState = SPECTATOR_NOT;
	if ( !Q_stricmp( s, "scoreboard" ) || !Q_stricmp( s, "score" )  ) {
		team = TEAM_SPECTATOR;
		specState = SPECTATOR_SCOREBOARD;
	} else if ( !Q_stricmp( s, "follow1" ) ) {
		team = TEAM_SPECTATOR;
		specState = SPECTATOR_FOLLOW;
		specClient = -1;
	} else if ( !Q_stricmp( s, "follow2" ) ) {
		team = TEAM_SPECTATOR;
		specState = SPECTATOR_FOLLOW;
		specClient = -2;
	} else if ( !Q_stricmp( s, "spectator" ) || !Q_stricmp( s, "s" ) ) {
		team = TEAM_SPECTATOR;
		specState = SPECTATOR_FREE;
	} else if ( g_gametype.integer >= GT_TEAM ) {
		// if running a team game, assign player to one of the teams
		specState = SPECTATOR_NOT;
		if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) ) {
			team = TEAM_RED;
		} else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) ) {
			team = TEAM_BLUE;
		} else {
			// pick the team with the least number of players
			team = PickTeam( clientNum );
		}

		if ( g_teamForceBalance.integer  ) {
			int		counts[TEAM_NUM_TEAMS];

			counts[TEAM_BLUE] = TeamCount( clientNum, TEAM_BLUE );
			counts[TEAM_RED] = TeamCount( clientNum, TEAM_RED );

			// We allow a spread of two
			if ( team == TEAM_RED && counts[TEAM_RED] - counts[TEAM_BLUE] > 1 ) {
				trap_SendServerCommand( clientNum, 
					"cp \"Red team has too many players.\n\"" );
				return; // ignore the request
			}
			if ( team == TEAM_BLUE && counts[TEAM_BLUE] - counts[TEAM_RED] > 1 ) {
				trap_SendServerCommand( clientNum, 
					"cp \"Blue team has too many players.\n\"" );
				return; // ignore the request
			}

			// It's ok, the team we are switching to has less or same number of players
		}

	} else {
		// force them to spectators if there aren't any spots free
		team = TEAM_FREE;
	}

	// override decision if limiting the players
	if ( (g_gametype.integer == GT_TOURNAMENT)
		&& level.numNonSpectatorClients >= 2 ) {
		team = TEAM_SPECTATOR;
	} else if ( g_maxGameClients.integer > 0 && 
		level.numNonSpectatorClients >= g_maxGameClients.integer ) {
		team = TEAM_SPECTATOR;
	}

	//
	// decide if we will allow the change
	//
	oldTeam = client->sess.sessionTeam;
	if ( team == oldTeam && team != TEAM_SPECTATOR ) {
		return;
	}

	//
	// execute the team change
	//

	// if the player was dead leave the body
	if ( client->ps.stats[STAT_HEALTH] <= 0 ) {
		CopyToBodyQue(ent);
	}

	// he starts at 'base'
	client->pers.teamState.state = TEAM_BEGIN;
	if ( oldTeam != TEAM_SPECTATOR ) {
		// Kill him (makes sure he loses flags, etc)
		ent->flags &= ~FL_GODMODE;
		ent->client->ps.stats[STAT_HEALTH] = ent->health = 0;
		player_die (ent, ent, ent, 100000, MOD_SUICIDE);

	}

	// they go to the end of the line for tournements
	if(team == TEAM_SPECTATOR && oldTeam != team)
		AddTournamentQueue(client);

	client->sess.sessionTeam = team;
	client->sess.spectatorState = specState;
	client->sess.spectatorClient = specClient;

	client->sess.teamLeader = qfalse;
	if ( team == TEAM_RED || team == TEAM_BLUE ) {
		teamLeader = TeamLeader( team );
		// if there is no team leader or the team leader is a bot and this client is not a bot
		if ( teamLeader == -1 || ( !(g_entities[clientNum].r.svFlags & SVF_BOT) && (g_entities[teamLeader].r.svFlags & SVF_BOT) ) ) {
			SetLeader( team, clientNum );
		}
	}
	// make sure there is a team leader on the team the player came from
	if ( oldTeam == TEAM_RED || oldTeam == TEAM_BLUE ) {
		CheckTeamLeader( oldTeam );
	}

	BroadcastTeamChange( client, oldTeam );

	// get and distribute relevent paramters
	ClientUserinfoChanged( clientNum );

	ClientBegin( clientNum );
}
示例#12
0
/*
===========
ClientConnect

Called when a player begins connecting to the server.
Called again for every map change or tournement restart.

The session information will be valid after exit.

Return NULL if the client should be allowed, otherwise return
a string with the reason for denial.

Otherwise, the client will be sent the current gamestate
and will eventually get to ClientBegin.

firstTime will be qtrue the very first time a client connects
to the server machine, but qfalse on map changes and tournement
restarts.
============
*/
char *ClientConnect( int clientNum, qboolean firstTime, qboolean isBot ) {
	char		*value;
//	char		*areabits;
	gclient_t	*client;
	char		userinfo[MAX_INFO_STRING];
	gentity_t	*ent;

	ent = &g_entities[ clientNum ];

	trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) );

 	// IP filtering
 	// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=500
 	// recommanding PB based IP / GUID banning, the builtin system is pretty limited
 	// check to see if they are on the banned IP list
	value = Info_ValueForKey (userinfo, "ip");
	if ( G_FilterPacket( value ) ) {
		return "You are banned from this server.";
	}

  // we don't check password for bots and local client
  // NOTE: local client <-> "ip" "localhost"
  //   this means this client is not running in our current process
	if ( !( ent->r.svFlags & SVF_BOT ) && (strcmp(value, "localhost") != 0)) {
		// check for a password
		value = Info_ValueForKey (userinfo, "password");
		if ( g_password.string[0] && Q_stricmp( g_password.string, "none" ) &&
			strcmp( g_password.string, value) != 0) {
			return "Invalid password";
		}
	}

	// they can connect
	ent->client = level.clients + clientNum;
	client = ent->client;

//	areabits = client->areabits;

	memset( client, 0, sizeof(*client) );

	client->pers.connected = CON_CONNECTING;

	// read or initialize the session data
	if ( firstTime || level.newSession ) {
		G_InitSessionData( client, userinfo );
	}
	G_ReadSessionData( client );

	if( isBot ) {
		ent->r.svFlags |= SVF_BOT;
		ent->inuse = qtrue;
		if( !G_BotConnect( clientNum, !firstTime ) ) {
			return "BotConnectfailed";
		}
	}

	// get and distribute relevent paramters
	G_LogPrintf( "ClientConnect: %i\n", clientNum );
	ClientUserinfoChanged( clientNum );

	// don't do the "xxx connected" messages if they were caried over from previous level
	if ( firstTime ) {
		trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " connected\n\"", client->pers.netname) );
	}

	if ( g_gametype.integer >= GT_TEAM &&
		client->sess.sessionTeam != TEAM_SPECTATOR ) {
		BroadcastTeamChange( client, -1 );
	}

	// count current clients and rank for scoreboard
	CalculateRanks();

	// for statistics
//	client->areabits = areabits;
//	if ( !client->areabits )
//		client->areabits = G_Alloc( (trap_AAS_PointReachabilityAreaIndex( NULL ) + 7) / 8 );

	return NULL;
}
示例#13
0
//[ExpSys]
//added firsttime input so we'll know if we need to reset our skill point totals or not.
void G_InitSessionData( gclient_t *client, char *userinfo, qboolean isBot, qboolean firstTime) {
//void G_InitSessionData( gclient_t *client, char *userinfo, qboolean isBot ) {
//[/ExpSys]
    clientSession_t	*sess;
    const char		*value;

    sess = &client->sess;

    client->sess.siegeDesiredTeam = TEAM_FREE;

    // initial team determination
    //[CoOp]
    //CoOp counts as a multi-team game.
    if ( g_gametype.integer >= GT_SINGLE_PLAYER) {
        //if ( g_gametype.integer >= GT_TEAM ) {
        //[/CoOp]
        if ( g_teamAutoJoin.integer )
        {
            //[AdminSys]
            sess->sessionTeam = PickTeam( -1, isBot );
            //sess->sessionTeam = PickTeam( -1 );
            //[/AdminSys]
            BroadcastTeamChange( client, -1 );
        }
        else
        {
            // always spawn as spectator in team games
            if (!isBot)
            {
                sess->sessionTeam = TEAM_SPECTATOR;
            }
            else
            {   //Bots choose their team on creation
                value = Info_ValueForKey( userinfo, "team" );
                if (value[0] == 'r' || value[0] == 'R')
                {
                    sess->sessionTeam = TEAM_RED;
                }
                else if (value[0] == 'b' || value[0] == 'B')
                {
                    sess->sessionTeam = TEAM_BLUE;
                }
                else
                {
                    //[AdminSys]
                    sess->sessionTeam = PickTeam( -1, isBot );
                    //sess->sessionTeam = PickTeam( -1 );
                    //[/AdminSys]
                }
                BroadcastTeamChange( client, -1 );
            }
        }
    } else {
        value = Info_ValueForKey( userinfo, "team" );
        if ( value[0] == 's' ) {
            // a willing spectator, not a waiting-in-line
            sess->sessionTeam = TEAM_SPECTATOR;
        } else {
            switch ( g_gametype.integer ) {
            default:
            case GT_FFA:
            case GT_HOLOCRON:
            case GT_JEDIMASTER:
                //[CoOp]
                //CoOp counts as a multi-team game.
                //case GT_SINGLE_PLAYER:
                //[/CoOp]
                if ( g_maxGameClients.integer > 0 &&
                        level.numNonSpectatorClients >= g_maxGameClients.integer ) {
                    sess->sessionTeam = TEAM_SPECTATOR;
                } else {
                    sess->sessionTeam = TEAM_FREE;
                }
                break;
            case GT_DUEL:
                // if the game is full, go into a waiting mode
                if ( level.numNonSpectatorClients >= 2 ) {
                    sess->sessionTeam = TEAM_SPECTATOR;
                } else {
                    sess->sessionTeam = TEAM_FREE;
                }
                break;
            case GT_POWERDUEL:
                //sess->duelTeam = DUELTEAM_LONE; //default
            {
                int loners = 0;
                int doubles = 0;

                G_PowerDuelCount(&loners, &doubles, qtrue);

                if (!doubles || loners > (doubles/2))
                {
                    sess->duelTeam = DUELTEAM_DOUBLE;
                }
                else
                {
                    sess->duelTeam = DUELTEAM_LONE;
                }
            }
            sess->sessionTeam = TEAM_SPECTATOR;
            break;
            }
        }
    }

    sess->spectatorState = SPECTATOR_FREE;
    sess->spectatorTime = level.time;

    sess->siegeClass[0] = 0;
    sess->saberType[0] = 0;
    sess->saber2Type[0] = 0;

    //[ExpSys]
    //[OpenRP - Skillpoint System]
    if(firstTime)
    {   //only reset skillpoints for new players.
        sess->IP[0] = 0;
        sess->skillPoints = 1;
        sess->adminLevel = 11;
        sess->radioOn = qtrue;
    }
    //[/OpenRP - Skillpoint System]
    else
    {   //remember the data from the last time.
        char	s[MAX_STRING_CHARS];
        const char	*var;
        int tempInt;
        char tempChar[64];

        var = va( "session%i", client - level.clients );
        trap_Cvar_VariableStringBuffer( var, s, sizeof(s) );
        //[ExpSys]
        sscanf( s, "%i %i %i %i %i %i %i %i %i %i %i %i %s %s %s %i %i %i %i %i %i %i %s %i",
                //sscanf( s, "%i %i %i %i %i %i %i %i %i %i %i %i %s %s %s",
                //[ExpSys]
                &tempInt,                 // bk010221 - format
                &tempInt,
                &tempInt,              // bk010221 - format
                &tempInt,
                &tempInt,
                &tempInt,
                &tempInt,                   // bk010221 - format
                &tempInt,
                &tempInt,
                &tempInt,
                &tempInt,
                &tempInt,
                &tempChar,
                &tempChar,
                &tempChar,
                &client->sess.skillPoints,
                //[OpenRP - account and character, other systems & IP]
                &client->sess.accountID,
                &client->sess.loggedinAccount,
                &client->sess.characterChosen,
                &client->sess.characterID,
                &client->sess.warnings,
                &client->sess.modelScale,
                &client->sess.IP,
                &client->sess.ojpClientPlugIn
                //[/OpenRP - account and character, other systems & IP]
              );
    }
    //[/ExpSys]

    G_WriteClientSessionData( client );
}
示例#14
0
/*
===========
ClientConnect

Called when a player begins connecting to the server.
Called again for every map change or tournement restart.

The session information will be valid after exit.

Return NULL if the client should be allowed, otherwise return
a string with the reason for denial.

Otherwise, the client will be sent the current gamestate
and will eventually get to ClientBegin.

firstTime will be qtrue the very first time a client connects
to the server machine, but qfalse on map changes and tournement
restarts.
============
*/
char *ClientConnect( int clientNum, qboolean firstTime, qboolean isBot ) {
	char		*value;
//	char		*areabits;
	gclient_t	*client;
	char		userinfo[MAX_INFO_STRING];
	gentity_t	*ent;
	gentity_t	*te;

	ent = &g_entities[ clientNum ];

	trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) );

	// check to see if they are on the banned IP list
	value = Info_ValueForKey (userinfo, "ip");
	if ( G_FilterPacket( value ) ) {
		return "Banned.";
	}

	if ( !( ent->r.svFlags & SVF_BOT ) && !isBot && g_needpass.integer ) {
		// check for a password
		value = Info_ValueForKey (userinfo, "password");
		if ( g_password.string[0] && Q_stricmp( g_password.string, "none" ) &&
			strcmp( g_password.string, value) != 0) {
			static char sTemp[1024];
			Q_strncpyz(sTemp, G_GetStripEdString("SVINGAME","INVALID_PASSWORD"), sizeof (sTemp) );
			return sTemp;// return "Invalid password";
		}
	}

	// they can connect
	ent->client = level.clients + clientNum;
	client = ent->client;

//	areabits = client->areabits;

	memset( client, 0, sizeof(*client) );
	memset( &bootSession[clientNum], 0, sizeof(bootSession[clientNum]) );

	client->pers.connected = CON_CONNECTING;

	// read or initialize the session data
	if ( firstTime || level.newSession ) {
		G_InitSessionData( client, userinfo, isBot );
	}
	G_ReadSessionData( client );

	if( isBot ) {
		ent->r.svFlags |= SVF_BOT;
		ent->inuse = qtrue;
		if( !G_BotConnect( clientNum, !firstTime ) ) {
			return "BotConnectfailed";
		}
	}

	// get and distribute relevent paramters
	G_LogPrintf( "ClientConnect: %i\n", clientNum );
	ClientUserinfoChanged( clientNum );

	// don't do the "xxx connected" messages if they were caried over from previous level
	if ( firstTime ) {
		trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " %s\n\"", client->pers.netname, G_GetStripEdString("SVINGAME", "PLCONNECT")) );
	}

	if ( g_gametype.integer >= GT_TEAM &&
		client->sess.sessionTeam != TEAM_SPECTATOR ) {
		BroadcastTeamChange( client, -1 );
	}

	// count current clients and rank for scoreboard
	CalculateRanks();

	te = G_TempEntity( vec3_origin, EV_CLIENTJOIN );
	te->r.svFlags |= SVF_BROADCAST;
	te->s.eventParm = clientNum;

	// for statistics
//	client->areabits = areabits;
//	if ( !client->areabits )
//		client->areabits = G_Alloc( (trap_AAS_PointReachabilityAreaIndex( NULL ) + 7) / 8 );

	return NULL;
}
示例#15
0
文件: g_cmds.c 项目: Razish/QtZ
void SetTeam( gentity_t *ent, char *s ) {
	int					clientNum, specClient=0;
	team_t				team, oldTeam;
	gclient_t			*client = ent->client;
	spectatorState_t	specState = SPECTATOR_NOT;

	// see what change is requested
	clientNum = ARRAY_INDEX( level.clients, client );

	if ( !Q_stricmp( s, "scoreboard" ) || !Q_stricmp( s, "score" ) ) {
		team = TEAM_SPECTATOR;
		specState = SPECTATOR_SCOREBOARD;
	}

	else if ( !Q_stricmp( s, "follow1" ) ) {
		team = TEAM_SPECTATOR;
		specState = SPECTATOR_FOLLOW;
		specClient = -1;
	}

	else if ( !Q_stricmp( s, "follow2" ) ) {
		team = TEAM_SPECTATOR;
		specState = SPECTATOR_FOLLOW;
		specClient = -2;
	}

	else if ( !Q_stricmp( s, "spectator" ) || !Q_stricmp( s, "s" ) ) {
		team = TEAM_SPECTATOR;
		specState = SPECTATOR_FREE;
	}

	// if running a team game, assign player to one of the teams
	else if ( level.gametype >= GT_TEAMBLOOD ) {
		specState = SPECTATOR_NOT;
		if ( !Q_stricmp( s, "red" ) || !Q_stricmp( s, "r" ) )
			team = TEAM_RED;
		else if ( !Q_stricmp( s, "blue" ) || !Q_stricmp( s, "b" ) )
			team = TEAM_BLUE;
		else
			team = PickTeam( clientNum ); // pick the team with the least number of players

		if ( g_teamForceBalance->integer  ) {
			int		counts[TEAM_NUM_TEAMS];

			counts[TEAM_BLUE] = TeamCount( clientNum, TEAM_BLUE );
			counts[TEAM_RED] = TeamCount( clientNum, TEAM_RED );

			// We allow a spread of two
			if ( team == TEAM_RED && counts[TEAM_RED] - counts[TEAM_BLUE] > 1 ) {
				trap->SV_GameSendServerCommand( clientNum, "cp \"Red team has too many players.\n\"" );
				return; // ignore the request
			}
			if ( team == TEAM_BLUE && counts[TEAM_BLUE] - counts[TEAM_RED] > 1 ) {
				trap->SV_GameSendServerCommand( clientNum, "cp \"Blue team has too many players.\n\"" );
				return; // ignore the request
			}

			// It's ok, the team we are switching to has less or same number of players
		}

	}
	else
		team = TEAM_FREE; // force them to spectators if there aren't any spots free

	// override decision if limiting the players
	if ( (level.gametype == GT_DUEL) && level.numNonSpectatorClients >= 2 )
		team = TEAM_SPECTATOR;
	else if ( g_maxGameClients->integer > 0 && level.numNonSpectatorClients >= g_maxGameClients->integer )
		team = TEAM_SPECTATOR;

	// decide if we will allow the change
	oldTeam = client->sess.sessionTeam;
	if ( team == oldTeam && team != TEAM_SPECTATOR )
		return;

	// if the player was dead leave the body
	if ( client->ps.stats[STAT_HEALTH] <= 0 ) {
		CopyToBodyQue( ent );
	}

	// he starts at 'base'
	client->pers.teamState.state = TEAM_BEGIN;
	if ( oldTeam != TEAM_SPECTATOR ) {
		// Kill him (makes sure he loses flags, etc)
		ent->flags &= ~FL_GODMODE;
		ent->client->ps.stats[STAT_HEALTH] = ent->health = 0;
		player_die( ent, ent, ent, 100000, MOD_SUICIDE );

	}

	// they go to the end of the line for tournaments
	if ( team == TEAM_SPECTATOR && oldTeam != team )
		AddTournamentQueue( client );

	// exploit fix: with 3 (any odd amount?) players connected, one could /callvote map x followed by /team s to force the vote
	G_ClearVote( ent );

	client->sess.sessionTeam = team;
	client->sess.spectatorState = specState;
	client->sess.spectatorClient = specClient;

	BroadcastTeamChange( client, oldTeam );
	ClientUserinfoChanged( clientNum );
	ClientBegin( clientNum );
}
示例#16
0
/*
===========
ClientConnect

Called when a player begins connecting to the server.
Called again for every map change or tournement restart.

The session information will be valid after exit.

Return NULL if the client should be allowed, otherwise return
a string with the reason for denial.

Otherwise, the client will be sent the current gamestate
and will eventually get to ClientBegin.

firstTime will be qtrue the very first time a client connects
to the server machine, but qfalse on map changes and tournement
restarts.
============
*/
char *ClientConnect( int clientNum, qboolean firstTime, qboolean isBot, int connectionNum, int localPlayerNum ) {
	char		*value;
//	char		*areabits;
	gclient_t	*client;
	char		userinfo[MAX_INFO_STRING];
	gentity_t	*ent;
	qboolean	firstConnectionPlayer;

	ent = &g_entities[ clientNum ];

	trap_GetUserinfo( clientNum, userinfo, sizeof( userinfo ) );

	// Check if it's the first player on the client (i.e. not a splitscreen player)
	firstConnectionPlayer = ( level.connections[connectionNum].numLocalPlayers == 0 );

	if ( firstConnectionPlayer ) {
		// IP filtering
		// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=500
		// recommanding PB based IP / GUID banning, the builtin system is pretty limited
		// check to see if they are on the banned IP list
		value = Info_ValueForKey (userinfo, "ip");
		if ( G_FilterPacket( value ) ) {
			return "You are banned from this server.";
		}

		// we don't check password for bots and local client
		// NOTE: local client <-> "ip" "localhost"
		//   this means this client is not running in our current process
		if ( !isBot && (strcmp(value, "localhost") != 0) ) {
			// check for a password
			value = Info_ValueForKey (userinfo, "password");
			if ( g_password.string[0] && Q_stricmp( g_password.string, "none" ) &&
				strcmp( g_password.string, value) != 0) {
				return "Invalid password";
			}
		}
	} else {
		// Don't allow splitscreen players in single player.
		if ( g_singlePlayer.integer ) {
			return "Splitscreen not allowed in single player.";
		}
	}

	// if a player reconnects quickly after a disconnect, the client disconnect may never be called, thus flag can get lost in the ether
	if (ent->inuse) {
		G_LogPrintf("Forcing disconnect on active client: %i\n", clientNum);
		// so lets just fix up anything that should happen on a disconnect
		ClientDisconnect(clientNum);
	}
	// they can connect
	ent->client = level.clients + clientNum;
	client = ent->client;

//	areabits = client->areabits;

	memset( client, 0, sizeof(*client) );

	client->pers.connected = CON_CONNECTING;

	// update client connection info
	level.connections[connectionNum].numLocalPlayers++;
	level.connections[connectionNum].localPlayerNums[localPlayerNum] = clientNum;
	client->pers.connectionNum = connectionNum;
	client->pers.localPlayerNum = localPlayerNum;

	// read or initialize the session data
	if ( firstTime || level.newSession ) {
		G_InitSessionData( client, userinfo );
	}
	G_ReadSessionData( client );

	if( isBot ) {
		ent->r.svFlags |= SVF_BOT;
		ent->inuse = qtrue;
		if( !G_BotConnect( clientNum, !firstTime ) ) {
			return "BotConnectfailed";
		}
	}

	// get and distribute relevent paramters
	G_LogPrintf( "ClientConnect: %i\n", clientNum );
	ClientUserinfoChanged( clientNum );

	// don't do the "xxx connected" messages if they were caried over from previous level
	// or if they're an extra local player
	if ( firstTime && firstConnectionPlayer ) {
		trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " connected\n\"", client->pers.netname) );
	}

	if ( g_gametype.integer >= GT_TEAM &&
		client->sess.sessionTeam != TEAM_SPECTATOR ) {
		BroadcastTeamChange( client, -1 );
	}

	// count current clients and rank for scoreboard
	CalculateRanks();

	// for statistics
//	client->areabits = areabits;
//	if ( !client->areabits )
//		client->areabits = G_Alloc( (trap_AAS_PointReachabilityAreaIndex( NULL ) + 7) / 8 );

	return NULL;
}
示例#17
0
文件: g_session.c 项目: videoP/jaPRO
/*
================
G_InitSessionData

Called on a first-time connect
================
*/
void G_InitSessionData( gclient_t *client, char *userinfo, qboolean isBot ) {
	clientSession_t	*sess;
	const char		*value;

	sess = &client->sess;

	client->sess.siegeDesiredTeam = TEAM_FREE;

	// initial team determination
	if ( level.gametype >= GT_TEAM ) {
		if ( g_teamAutoJoin.integer && !(g_entities[client-level.clients].r.svFlags & SVF_BOT) ) {
			sess->sessionTeam = PickTeam( -1 );
			BroadcastTeamChange( client, -1 );
		} else {
			// always spawn as spectator in team games
			if (!isBot)
			{
				sess->sessionTeam = TEAM_SPECTATOR;	
			}
			else
			{ //Bots choose their team on creation
				value = Info_ValueForKey( userinfo, "team" );
				if (value[0] == 'r' || value[0] == 'R')
				{
					sess->sessionTeam = TEAM_RED;
				}
				else if (value[0] == 'b' || value[0] == 'B')
				{
					sess->sessionTeam = TEAM_BLUE;
				}
				else
				{
					sess->sessionTeam = PickTeam( -1 );
				}
				BroadcastTeamChange( client, -1 );
			}
		}
	} else {
		value = Info_ValueForKey( userinfo, "team" );
		if ( value[0] == 's' ) {
			// a willing spectator, not a waiting-in-line
			sess->sessionTeam = TEAM_SPECTATOR;
		} else {
			switch ( level.gametype ) {
			default:
			case GT_FFA:
			case GT_HOLOCRON:
			case GT_JEDIMASTER:
			case GT_SINGLE_PLAYER:
				if (!isBot && (!g_maxGameClients.integer || (g_maxGameClients.integer > 0 && //loda fixme - this should fix clients showing ingame when they really arnt , when first connect?
					level.numNonSpectatorClients >= g_maxGameClients.integer))) {
					sess->sessionTeam = TEAM_SPECTATOR;
				} else {
					sess->sessionTeam = TEAM_FREE;
				}
				break;
			case GT_DUEL:
				// if the game is full, go into a waiting mode
				if ( level.numNonSpectatorClients >= 2 ) {
					sess->sessionTeam = TEAM_SPECTATOR;
				} else {
					sess->sessionTeam = TEAM_FREE;
				}
				break;
			case GT_POWERDUEL:
				//sess->duelTeam = DUELTEAM_LONE; //default
				{
					int loners = 0;
					int doubles = 0;

					G_PowerDuelCount(&loners, &doubles, qtrue);

					if (!doubles || loners > (doubles/2))
					{
						sess->duelTeam = DUELTEAM_DOUBLE;
					}
					else
					{
						sess->duelTeam = DUELTEAM_LONE;
					}
				}
				sess->sessionTeam = TEAM_SPECTATOR;
				break;
			}
		}
	}

	sess->spectatorState = SPECTATOR_FREE;
	AddTournamentQueue(client);

	sess->siegeClass[0] = 0;

	sess->ignore = 0;//[JAPRO - Serverside - All - Ignore]

	G_WriteClientSessionData( client );
}