Esempio n. 1
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;
}
Esempio n. 2
0
/*
===========
ClientSpawn

Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
============
*/
void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles )
{
  int                 index;
  vec3_t              spawn_origin, spawn_angles;
  gclient_t           *client;
  int                 i;
  clientPersistant_t  saved;
  clientSession_t     savedSess;
  int                 persistant[ MAX_PERSISTANT ];
  gentity_t           *spawnPoint = NULL, *event;
  int                 flags;
  int                 savedPing;
  int                 teamLocal;
  int                 eventSequence;
  char                userinfo[ MAX_INFO_STRING ];
  vec3_t              up = { 0.0f, 0.0f, 1.0f }, implant_dir, implant_angles, spawnPoint_velocity;
  int                 maxAmmo, maxClips;
  weapon_t            weapon;
  qboolean            fromImplant = qfalse, hatchingFailed = qfalse;

  index = ent - g_entities;
  client = ent->client;

  teamLocal = client->pers.teamSelection;

  //if client is dead and following teammate, stop following before spawning
  if( client->sess.spectatorClient != -1 )
  {
    client->sess.spectatorClient = -1;
    client->sess.spectatorState = SPECTATOR_FREE;
  }

  // only start client if chosen a class and joined a team
  if( client->pers.classSelection == PCL_NONE && teamLocal == TEAM_NONE )
    client->sess.spectatorState = SPECTATOR_FREE;
  else if( client->pers.classSelection == PCL_NONE )
    client->sess.spectatorState = SPECTATOR_LOCKED;

  // if client is dead and following teammate, stop following before spawning
  if( ent->client->sess.spectatorState == SPECTATOR_FOLLOW )
    G_StopFollowing( ent );

  if( origin != NULL )
    VectorCopy( origin, spawn_origin );

  if( angles != NULL )
    VectorCopy( angles, spawn_angles );

  // find a spawn point
  // do it before setting health back up, so farthest
  // ranging doesn't count this client
  if( client->sess.spectatorState != SPECTATOR_NOT )
  {
    if( teamLocal == TEAM_NONE )
      spawnPoint = G_SelectSpectatorSpawnPoint( spawn_origin, spawn_angles );
    else if( teamLocal == TEAM_ALIENS )
      spawnPoint = G_SelectAlienLockSpawnPoint( spawn_origin, spawn_angles );
    else if( teamLocal == TEAM_HUMANS )
      spawnPoint = G_SelectHumanLockSpawnPoint( spawn_origin, spawn_angles );
  }
  else
  {
    if( spawn == NULL )
    {
      G_Error( "ClientSpawn: spawn is NULL\n" );
      return;
    }

    spawnPoint = spawn;

    if( ent != spawn )
    {
      if( !spawnPoint->client ) //might be a human
      {
        //start spawn animation on spawnPoint
        G_SetBuildableAnim( spawnPoint, BANIM_SPAWN1, qtrue );

        if( spawnPoint->buildableTeam == TEAM_ALIENS )
          spawnPoint->clientSpawnTime = ALIEN_SPAWN_REPEAT_TIME;
        else if( spawnPoint->buildableTeam == TEAM_HUMANS )
          spawnPoint->clientSpawnTime = HUMAN_SPAWN_REPEAT_TIME;
      }
      else
      {
        qboolean crouch;
        int i;
        float zoffs = 0.0f;
        trace_t tr;
        vec3_t neworigin, mins, maxs;
        
        fromImplant = qtrue; //spawning from a human
        
        // move the origin a bit on the Z axis so the aliens jumps out of the chest, not knees
        // also prevents grangers from getting stuck in ceilings and floors
        crouch = spawnPoint->client->ps.pm_flags & PMF_DUCKED;
        switch( client->pers.classSelection )
        {
          case PCL_ALIEN_BUILDER0:
            if( !crouch )
              zoffs = 19.0f;
            else
              zoffs = -4.0f;
            break;
          case PCL_ALIEN_BUILDER0_UPG:
            if( !crouch )
              zoffs = 16.5f;
            else
              zoffs = -4.0f;
            break;
          case PCL_ALIEN_LEVEL0:
            if( !crouch )
              zoffs = 15.0f;
            else
              zoffs = -9.1f;
            break;
        }
        spawn_origin[ 2 ] += zoffs;
        
        // check if the spot would block
        BG_ClassBoundingBox( client->pers.classSelection, mins, maxs, NULL, NULL, NULL );
        trap_Trace( &tr, spawn_origin, mins, maxs, spawn_origin, spawnPoint->s.number, MASK_PLAYERSOLID );
        
        // try to unblock the player
        if( tr.startsolid )
        {
          Com_Printf("DEBUG: player is stuck!\n");
          for( i = 0; i < 16*2; i++ )
          {
            float a, r;
            
            VectorCopy( spawn_origin, neworigin );
            
            a = (float)i / 16.0f * 2.0f * M_PI;
            #define fmod(a,n) ((a)-(n)*floor((a)/(n)))
            r = ( i < 16 ? 5.5f : 11.0f ) * 1.0f / cos( fmod( a+0.25f*M_PI, 0.5f*M_PI ) - 0.25f*M_PI );
            neworigin[ 0 ] += cos( a ) * r;
            neworigin[ 1 ] += sin( a ) * r;
            
            trap_Trace( &tr, neworigin, mins, maxs, neworigin, spawnPoint->s.number, MASK_PLAYERSOLID );
            
            if( !tr.startsolid )
            {
             Com_Printf("DEBUG: player position fixed at iteration %i\n",i);
             VectorCopy( neworigin, spawn_origin );
             break;
            }
          }
        }
        
        //reward the player that implanted this one
        if( spawnPoint->client->impregnatedBy >= 0 )
        {
          gentity_t *granger;
          
          granger = &g_entities[ spawnPoint->client->impregnatedBy ];
          G_AddCreditToClient( granger->client, ALIEN_IMPREGNATION_REWARD, qtrue );  
          AddScore( granger, ALIEN_IMPREGNATION_REWARD_SCORE );
        }
        
        // kill the human, set up angles and velocity for the new alien
        if( !BG_InventoryContainsUpgrade( UP_BATTLESUIT, spawnPoint->client->ps.stats ) //humans without battlesuits always die
            || spawnPoint->client->ps.stats[ STAT_HEALTH ] < ALIEN_HATCHING_MAX_BATTLESUIT_HEALTH ) //battlesuits survive if high hp
        {
          //save viewangles and spawn velocity for velocity calculation
          VectorCopy( spawnPoint->client->ps.viewangles, implant_angles );
          AngleVectors( implant_angles, implant_dir, NULL, NULL );
          VectorCopy( spawnPoint->client->ps.velocity, spawnPoint_velocity );

          //fire a nice chest exploding effect
          event = G_TempEntity( spawnPoint->s.pos.trBase, EV_ALIEN_HATCH );
          VectorCopy( implant_dir, event->s.angles );

          //kill the player
          G_Damage( spawnPoint, NULL, ent, NULL, NULL, spawnPoint->client->ps.stats[ STAT_HEALTH ], DAMAGE_NO_ARMOR, MOD_ALIEN_HATCH );
        }
        else //human survives
        {
          //clear impregnation so the human won't explode again
          spawnPoint->client->isImpregnated = qfalse;
          spawnPoint->client->isImplantMature = qfalse;
          
          //make a sound
          event = G_TempEntity( spawnPoint->s.pos.trBase, EV_ALIEN_HATCH_FAILURE );

          //damage the human
          G_Damage( spawnPoint, NULL, ent, NULL, NULL, ALIEN_FAILED_HATCH_DAMAGE, DAMAGE_NO_ARMOR, MOD_ALIEN_HATCH );

          //kill the newly spawned alien
          VectorCopy( spawnPoint->client->ps.viewangles, implant_angles );
          implant_dir[0] = 0.0f;
          implant_dir[1] = 0.0f;
          implant_dir[2] = 0.0f;
          hatchingFailed = qtrue;
        }
      }
    }
  }

  // toggle the teleport bit so the client knows to not lerp
  flags = ( ent->client->ps.eFlags & EF_TELEPORT_BIT ) ^ EF_TELEPORT_BIT;
  G_UnlaggedClear( ent );

  // clear everything but the persistant data

  saved = client->pers;
  savedSess = client->sess;
  savedPing = client->ps.ping;

  for( i = 0; i < MAX_PERSISTANT; i++ )
    persistant[ i ] = client->ps.persistant[ i ];

  eventSequence = client->ps.eventSequence;
  memset( client, 0, sizeof( *client ) );

  client->pers = saved;
  client->sess = savedSess;
  client->ps.ping = savedPing;
  client->lastkilled_client = -1;

  for( i = 0; i < MAX_PERSISTANT; i++ )
    client->ps.persistant[ i ] = persistant[ i ];

  client->ps.eventSequence = eventSequence;

  // increment the spawncount so the client will detect the respawn
  client->ps.persistant[ PERS_SPAWN_COUNT ]++;
  client->ps.persistant[ PERS_SPECSTATE ] = client->sess.spectatorState;

  client->airOutTime = level.time + 12000;

  trap_GetUserinfo( index, userinfo, sizeof( userinfo ) );
  client->ps.eFlags = flags;

  //Com_Printf( "ent->client->pers->pclass = %i\n", ent->client->pers.classSelection );

  ent->s.groundEntityNum = ENTITYNUM_NONE;
  ent->client = &level.clients[ index ];
  ent->takedamage = qtrue;
  ent->inuse = qtrue;
  ent->classname = "player";
  ent->r.contents = CONTENTS_BODY;
  ent->clipmask = MASK_PLAYERSOLID;
  ent->die = player_die;
  ent->waterlevel = 0;
  ent->watertype = 0;
  ent->flags = 0;

  // calculate each client's acceleration
  ent->evaluateAcceleration = qtrue;

  client->ps.stats[ STAT_MISC ] = 0;
  client->buildTimer = 0;

  client->ps.eFlags = flags;
  client->ps.clientNum = index;

  BG_ClassBoundingBox( ent->client->pers.classSelection, ent->r.mins, ent->r.maxs, NULL, NULL, NULL );

  if( client->sess.spectatorState == SPECTATOR_NOT )
    client->ps.stats[ STAT_MAX_HEALTH ] =
      BG_Class( ent->client->pers.classSelection )->health;
  else
    client->ps.stats[ STAT_MAX_HEALTH ] = 100;

  // clear entity values
  if( ent->client->pers.classSelection == PCL_HUMAN )
  {
    BG_AddUpgradeToInventory( UP_MEDKIT, client->ps.stats );
    weapon = client->pers.humanItemSelection;
  }
  else if( client->sess.spectatorState == SPECTATOR_NOT )
    weapon = BG_Class( ent->client->pers.classSelection )->startWeapon;
  else
    weapon = WP_NONE;

  maxAmmo = BG_Weapon( weapon )->maxAmmo;
  maxClips = BG_Weapon( weapon )->maxClips;
  client->ps.stats[ STAT_WEAPON ] = weapon;
  client->ps.ammo = maxAmmo;
  client->ps.clips = maxClips;

  // We just spawned, not changing weapons
  client->ps.persistant[ PERS_NEWWEAPON ] = 0;

  ent->client->ps.stats[ STAT_CLASS ] = ent->client->pers.classSelection;
  ent->client->ps.stats[ STAT_TEAM ] = ent->client->pers.teamSelection;

  ent->client->ps.stats[ STAT_BUILDABLE ] = BA_NONE;
  ent->client->ps.stats[ STAT_STATE ] = 0;
  VectorSet( ent->client->ps.grapplePoint, 0.0f, 0.0f, 1.0f );

  // health will count down towards max_health
  ent->health = client->ps.stats[ STAT_HEALTH ] = client->ps.stats[ STAT_MAX_HEALTH ]; //* 1.25;

  //if evolving scale health
  if( ent == spawn )
  {
    ent->health *= ent->client->pers.evolveHealthFraction;
    client->ps.stats[ STAT_HEALTH ] *= ent->client->pers.evolveHealthFraction;
  }

  //clear the credits array
  for( i = 0; i < MAX_CLIENTS; i++ )
    ent->credits[ i ] = 0;

  client->ps.stats[ STAT_STAMINA ] = STAMINA_MAX;
  
  //never impregnated after respawning
  client->isImpregnated = qfalse;
  client->isImplantMature = qfalse;
  
  G_SetOrigin( ent, spawn_origin );
  VectorCopy( spawn_origin, client->ps.origin );

#define UP_VEL  150.0f
#define F_VEL   50.0f

  //give aliens some spawn velocity
  if( client->sess.spectatorState == SPECTATOR_NOT &&
      client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
  {
    if( ent == spawn )
    {
      //evolution particle system
      G_AddPredictableEvent( ent, EV_ALIEN_EVOLVE, DirToByte( up ) );
    }
    else if( !fromImplant ) //regular egg
    {
      spawn_angles[ YAW ] += 180.0f;
      AngleNormalize360( spawn_angles[ YAW ] );

      if( spawnPoint->s.origin2[ 2 ] > 0.0f )
      {
        vec3_t  forward, dir;

        AngleVectors( spawn_angles, forward, NULL, NULL );
        VectorScale( forward, F_VEL, forward );
        VectorAdd( spawnPoint->s.origin2, forward, dir );
        VectorNormalize( dir );

        VectorScale( dir, UP_VEL, client->ps.velocity );
      }

      G_AddPredictableEvent( ent, EV_PLAYER_RESPAWN, 0 );
    }
    else //implanted egg
    {
      VectorCopy( implant_angles, spawn_angles );
      VectorScale( implant_dir, ALIEN_HATCHING_VELOCITY, client->ps.velocity );
      VectorAdd( client->ps.velocity, spawnPoint_velocity, client->ps.velocity );
    }
  }
  else if( client->sess.spectatorState == SPECTATOR_NOT &&
           client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
  {
    spawn_angles[ YAW ] += 180.0f;
    AngleNormalize360( spawn_angles[ YAW ] );
  }

  // the respawned flag will be cleared after the attack and jump keys come up
  client->ps.pm_flags |= PMF_RESPAWNED;

  trap_GetUsercmd( client - level.clients, &ent->client->pers.cmd );
  G_SetClientViewAngle( ent, spawn_angles );

  if( client->sess.spectatorState == SPECTATOR_NOT )
  {
    trap_LinkEntity( ent );

    // force the base weapon up
    if( client->pers.teamSelection == TEAM_HUMANS )
      G_ForceWeaponChange( ent, weapon );

    client->ps.weaponstate = WEAPON_READY;
  }

  // don't allow full run speed for a bit
  client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
  client->ps.pm_time = 100;

  client->respawnTime = level.time;
  ent->nextRegenTime = level.time;

  client->inactivityTime = level.time + g_inactivity.integer * 1000;
  client->latched_buttons = 0;

  // set default animations
  client->ps.torsoAnim = TORSO_STAND;
  client->ps.legsAnim = LEGS_IDLE;

  if( level.intermissiontime )
    MoveClientToIntermission( ent );
  else
  {
    // fire the targets of the spawn point
    if( !spawn )
      G_UseTargets( spawnPoint, ent );

    // select the highest weapon number available, after any
    // spawn given items have fired
    client->ps.weapon = 1;

    for( i = WP_NUM_WEAPONS - 1; i > 0 ; i-- )
    {
      if( BG_InventoryContainsWeapon( i, client->ps.stats ) )
      {
        client->ps.weapon = i;
        break;
      }
    }
  }

  client->lastRantBombTime = level.time;
  
  // run a client frame to drop exactly to the floor,
  // initialize animations and other things
  client->ps.commandTime = level.time - 100;
  ent->client->pers.cmd.serverTime = level.time;
  ClientThink( ent-g_entities );

  // positively link the client, even if the command times are weird
  if( client->sess.spectatorState == SPECTATOR_NOT )
  {
    BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
    VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
    trap_LinkEntity( ent );
  }

  // must do this here so the number of active clients is calculated
  CalculateRanks( );

  // run the presend to set anything else
  ClientEndFrame( ent );

  // clear entity state values
  BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
  
  // kill him instantly after respawning if hatching failed
  if( fromImplant && hatchingFailed )
  {
    VectorCopy( spawnPoint->client->ps.velocity, client->ps.velocity );
    client->ps.stats[ STAT_HEALTH ] = ent->health = 0;
    player_die( ent, NULL, spawnPoint, 0, MOD_ALIEN_HATCH_FAILED );
  }
  
}
Esempio n. 3
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 ( !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";
		}
	}

	// 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;
}
Esempio n. 4
0
/*
================
Bot_ScriptInitBot
================
*/
qboolean Bot_ScriptInitBot(int entnum)
{
	gentity_t                *ent, *trav;
	bot_state_t              *bs;
	char                     userinfo[MAX_INFO_STRING];
	bot_script_global_data_t *bsgd;
	char                     *token, *p, *pBackup;
	int                      i, val = 0;
	int                      weapons[2];
	gitem_t                  *item = NULL;
	char                     *name;
	//
	bs = &botstates[entnum];
	if (!bs->inuse)
	{
		return qfalse;
	}
	if (bs->script.data)
	{
		return qtrue;
	}
	// set starting defaults
	bs->script.status.eventIndex = -1;
	bs->script.data              = NULL;
	//
	ent = BotGetEntity(bs->entitynum);
	trap_GetUserinfo(bs->entitynum, userinfo, sizeof(userinfo));
	name = Info_ValueForKey(userinfo, "scriptName");
	if (!name || !name[0])
	{
		return qfalse;
	}

	// find the script data for this bot
	bsgd = botCharacterScriptData;
	for (i = 0; i < numScriptCharacters; i++, bsgd++)
	{
		if (Q_stricmp(name, bsgd->name) != 0)
		{
			continue;
		}
		// check params
		p = bsgd->params;
		//
		// eliminate them with each condition not met
		while (qtrue)
		{
			token = COM_ParseExt(&p, qfalse);
			if (!token || !token[0])
			{
				// we're done, we found a match
				break;
			}
			//
			if (token[0] != '/')
			{
				G_Error("BotScript, line %i: condition identifier expected, '%s' found\n", bsgd->lineNum, token);
			}
			//
			if (!Q_stricmp(token, "/team"))
			{
				token = COM_ParseExt(&p, qfalse);
				if (!token || !token[0] || token[0] == '/')
				{
					G_Error("BotScript, line %i: unexpected end of /team parameter", bsgd->lineNum);
				}
				//
				if (!Q_stricmp(token, "axis"))
				{
					val = TEAM_AXIS;
				}
				else if (!Q_stricmp(token, "allies"))
				{
					val = TEAM_ALLIES;
				}
				else
				{
					G_Error("BotScript, line %i: unknown team \"%s\"", bsgd->lineNum, token);
				}
				// eliminate player
				if (bs->mpTeam != val)
				{
					break;
				}
			}
			else
			//
			if (!Q_stricmp(token, "/class"))
			{
				token = COM_ParseExt(&p, qfalse);
				if (!token || !token[0] || token[0] == '/')
				{
					G_Error("BotScript, line %i: unexpected end of /class parameter", bsgd->lineNum);
				}
				//
				val = Team_ClassForString(token);
				if (val < 0)
				{
					G_Error("BotScript, line %i: unknown class \"%s\"", bsgd->lineNum, token);
				}
				if (bs->mpClass != val)
				{
					break;
				}
			}
			else
			//
			if (!Q_stricmp(token, "/weapon"))
			{
				memset(weapons, 0, sizeof(weapons));
				// for each weapon
				while (qtrue)
				{
					// read the weapon
					token = COM_ParseExt(&p, qfalse);
					if (!token || !token[0] || token[0] == '/')
					{
						G_Error("BotScript, line %i: unexpected end of /weapon parameter", bsgd->lineNum);
					}
					//
					if ((item = BG_FindItem(token)))
					{
						if (!item->giTag)
						{
							G_Error("BotScript, line %i: unknown weapon \"%s\"", bsgd->lineNum, token);
						}
						COM_BitSet(weapons, item->giTag);
					}
					else
					{
						G_Error("BotScript, line %i: unknown weapon \"%s\"", bsgd->lineNum, token);
					}
					//
					pBackup = p;
					token   = COM_ParseExt(&p, qfalse);
					if (Q_stricmp(token, "or") != 0)
					{
						// not OR, so drop out of here
						p = pBackup;
						break;
					}
				}
				if (!(ent->client->ps.weapons[0] & weapons[0]) && !(ent->client->ps.weapons[1] & weapons[1]))
				{
					break;
				}
			}
			else
			//
			if (!Q_stricmp(token, "/within_range"))
			{
				// targetname
				token = COM_ParseExt(&p, qfalse);
				if (!token || !token[0] || token[0] == '/')
				{
					G_Error("BotScript, line %i: unexpected end of /within_range parameter", bsgd->lineNum);
				}
				trav = G_FindByTargetname(NULL, token);
				if (!trav)
				{
					G_Error("BotScript, line %i: unknown spawn point \"%s\"", bsgd->lineNum, token);
				}
				// range
				token = COM_ParseExt(&p, qfalse);
				if (!token || !token[0] || token[0] == '/')
				{
					G_Error("BotScript, line %i: range expected, not found", bsgd->lineNum);
				}
				//
				// eliminate players
				if (VectorDistanceSquared(ent->r.currentOrigin, trav->s.origin) > SQR(atof(token)))
				{
					break;
				}
			}
		}
		//
		// if there is a NOT a valid token waiting, then we passed all checks
		if (!token[0])
		{
			break;
		}
	}
	//
	if (i < numScriptCharacters)
	{
		// we found a script for this character
		bs->script.data = bsgd->data;
		return qtrue;
	}
	//
	return qfalse;
}
Esempio n. 5
0
/*
===========
ClientUserInfoChanged

Called from ClientConnect when the player first connects and
directly by the server system when the player updates a userinfo variable.

The game can override any of the settings and call trap_SetUserinfo
if desired.
============
*/
void ClientUserinfoChanged(int clientNum)
{
  gentity_t      *ent;
  int             teamTask, teamLeader, team, health;
  char           *s;
  char            model[MAX_QPATH];
  char            oldname[MAX_STRING_CHARS];
  gclient_t      *client;
  char            c1[MAX_INFO_STRING];
  char            c2[MAX_INFO_STRING];
  char            redTeam[MAX_INFO_STRING];
  char            blueTeam[MAX_INFO_STRING];
  char            userinfo[MAX_INFO_STRING];

  ent = g_entities + clientNum;
  client = ent->client;

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

  // check for malformed or illegal info strings
  if(!Info_Validate(userinfo))
  {
    strcpy(userinfo, "\\name\\badinfo");
  }

  // check for local client
  s = Info_ValueForKey(userinfo, "ip");
  if(!strcmp(s, "localhost"))
  {
    client->pers.localClient = qtrue;
  }

  // check the item prediction
  s = Info_ValueForKey(userinfo, "cg_predictItems");
  if(!atoi(s))
  {
    client->pers.predictItemPickup = qfalse;
  }
  else
  {
    client->pers.predictItemPickup = qtrue;
  }

  // set name
  Q_strncpyz(oldname, client->pers.netname, sizeof(oldname));
  s = Info_ValueForKey(userinfo, "name");
  ClientCleanName(s, client->pers.netname, sizeof(client->pers.netname));

  if(client->sess.sessionTeam == TEAM_SPECTATOR)
  {
    if(client->sess.spectatorState == SPECTATOR_SCOREBOARD)
    {
      Q_strncpyz(client->pers.netname, "scoreboard", sizeof(client->pers.netname));
    }
  }

  if(client->pers.connected == CON_CONNECTED)
  {
    if(strcmp(oldname, client->pers.netname))
    {
      trap_SendServerCommand(-1, va("print \"%s" S_COLOR_WHITE " renamed to %s\n\"", oldname, client->pers.netname));
    }
  }

  // set max health
#ifdef MISSIONPACK
  if(client->ps.powerups[PW_GUARD])
  {
    client->pers.maxHealth = 200;
  }
  else
  {
    health = atoi(Info_ValueForKey(userinfo, "handicap"));
    client->pers.maxHealth = health;
    if(client->pers.maxHealth < 1 || client->pers.maxHealth > 100)
    {
      client->pers.maxHealth = 100;
    }
  }
#else
  health = atoi(Info_ValueForKey(userinfo, "handicap"));
  client->pers.maxHealth = health;
  if(client->pers.maxHealth < 1 || client->pers.maxHealth > 100)
  {
    client->pers.maxHealth = 100;
  }
#endif
  client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;

  // set model
  Q_strncpyz(model, Info_ValueForKey(userinfo, "model"), sizeof(model));

  // bots set their team a few frames later
  if(g_gametype.integer >= GT_TEAM && g_entities[clientNum].r.svFlags & SVF_BOT)
  {
    s = Info_ValueForKey(userinfo, "team");
    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);
    }
  }
  else
  {
    team = client->sess.sessionTeam;
  }

/*	NOTE: all client side now

  // team
  switch( team ) {
  case TEAM_RED:
    ForceClientSkin(client, model, "red");
//		ForceClientSkin(client, headModel, "red");
    break;
  case TEAM_BLUE:
    ForceClientSkin(client, model, "blue");
//		ForceClientSkin(client, headModel, "blue");
    break;
  }
  // don't ever use a default skin in teamplay, it would just waste memory
  // however bots will always join a team but they spawn in as spectator
  if ( g_gametype.integer >= GT_TEAM && team == TEAM_SPECTATOR) {
    ForceClientSkin(client, model, "red");
//		ForceClientSkin(client, headModel, "red");
  }
*/

#ifdef MISSIONPACK
  if(g_gametype.integer >= GT_TEAM)
  {
    client->pers.teamInfo = qtrue;
  }
  else
  {
    s = Info_ValueForKey(userinfo, "teamoverlay");
    if(!*s || atoi(s) != 0)
    {
      client->pers.teamInfo = qtrue;
    }
    else
    {
      client->pers.teamInfo = qfalse;
    }
  }
#else
  // teamInfo
  s = Info_ValueForKey(userinfo, "teamoverlay");
  if(!*s || atoi(s) != 0)
  {
    client->pers.teamInfo = qtrue;
  }
  else
  {
    client->pers.teamInfo = qfalse;
  }
#endif
  /*
     s = Info_ValueForKey( userinfo, "cg_pmove_fixed" );
     if ( !*s || atoi( s ) == 0 ) {
     client->pers.pmoveFixed = qfalse;
     }
     else {
     client->pers.pmoveFixed = qtrue;
     }
   */

  // team task (0 = none, 1 = offence, 2 = defence)
  teamTask = atoi(Info_ValueForKey(userinfo, "teamtask"));
  // team Leader (1 = leader, 0 is normal player)
  teamLeader = client->sess.teamLeader;

  // colors
  strcpy(c1, Info_ValueForKey(userinfo, "color1"));
  strcpy(c2, Info_ValueForKey(userinfo, "color2"));

  strcpy(redTeam, Info_ValueForKey(userinfo, "g_redteam"));
  strcpy(blueTeam, Info_ValueForKey(userinfo, "g_blueteam"));

  // send over a subset of the userinfo keys so other clients can
  // print scoreboards, display models, and play custom sounds
#if 0
  if(ent->r.svFlags & SVF_BOT)
  {
    Com_sprintf(userinfo, sizeof(userinfo),
          "n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\g_redteam\\%s\\g_blueteam\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\skill\\%s\\tt\\%d\\tl\\%d",
          client->pers.netname, team, model, headModel, redTeam, blueTeam, c1, c2, client->pers.maxHealth,
          client->sess.wins, client->sess.losses, Info_ValueForKey(userinfo, "skill"), teamTask, teamLeader);
  }
  else
#endif
  {
    Com_sprintf(userinfo, sizeof(userinfo),
          "n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\g_redteam\\%s\\g_blueteam\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\tt\\%d\\tl\\%d",
          client->pers.netname, team, model, "", redTeam, blueTeam, c1, c2, client->pers.maxHealth,
          client->sess.wins, client->sess.losses, teamTask, teamLeader);
  }

  trap_SetConfigstring(CS_PLAYERS + clientNum, userinfo);

#ifdef G_LUA
  // Lua API callbacks
  // This only gets called when the ClientUserinfo is changed, replicating 
  // ETPro's behaviour.
  G_LuaHook_ClientUserinfoChanged(clientNum);
#endif

  // this is not the userinfo, more like the configstring actually
  G_LogPrintf("ClientUserinfoChanged: %i %s\n", clientNum, s);
}
Esempio n. 6
0
static void Svcmd_Kick_f( void ) {
    gclient_t	*cl;
    int			i;
    int			timeout = -1;
    char		sTimeout[MAX_TOKEN_CHARS];
    char		name[MAX_TOKEN_CHARS];

    // make sure server is running
    if ( !G_Is_SV_Running() ) {
        G_Printf( "Server is not running.\n" );
        return;
    }

    if ( trap_Argc() < 2 || trap_Argc() > 3 ) {
        G_Printf ("Usage: kick <player name> [timeout]\n");
        return;
    }

    if( trap_Argc() == 3 ) {
        trap_Argv( 2, sTimeout, sizeof( sTimeout ) );
        timeout = atoi( sTimeout );
    } else {
        timeout = 300;
    }

    trap_Argv(1, name, sizeof(name));
    cl = G_GetPlayerByName( name );//ClientForString( name );

    if ( !cl ) {
        if ( !Q_stricmp(name, "all") ) {
            for (i = 0, cl = level.clients; i < level.numConnectedClients; i++, cl++) {

                // dont kick localclients ...
                if ( cl->pers.localClient ) {
                    continue;
                }

                if ( timeout != -1 ) {
                    char *ip;
                    char userinfo[MAX_INFO_STRING];

                    trap_GetUserinfo( cl->ps.clientNum, userinfo, sizeof( userinfo ) );
                    ip = Info_ValueForKey (userinfo, "ip");

                    // use engine banning system, mods may choose to use their own banlist
                    if (USE_ENGINE_BANLIST) {

                        // kick but dont ban bots, they arent that lame
                        if ( (g_entities[cl->ps.clientNum].r.svFlags & SVF_BOT) ) {
                            timeout = 0;
                        }

                        trap_DropClient(cl->ps.clientNum, "player kicked", timeout);
                    } else {
                        trap_DropClient(cl->ps.clientNum, "player kicked", 0);

                        // kick but dont ban bots, they arent that lame
                        if ( !(g_entities[cl->ps.clientNum].r.svFlags & SVF_BOT) )
                            AddIPBan( ip );
                    }

                } else {
                    trap_DropClient(cl->ps.clientNum, "player kicked", 0);
                }
            }
        } else if ( !Q_stricmp(name, "allbots") ) {
            for (i = 0, cl = level.clients; i < level.numConnectedClients; i++, cl++) {
                if ( !(g_entities[cl->ps.clientNum].r.svFlags & SVF_BOT) ) {
                    continue;
                }
                // kick but dont ban bots, they arent that lame
                trap_DropClient(cl->ps.clientNum, "player kicked", 0);
            }
        }
        return;
    } else {
        // dont kick localclients ...
        if ( cl->pers.localClient ) {
            G_Printf("Cannot kick host player\n");
            return;
        }

        if ( timeout != -1 ) {
            char *ip;
            char userinfo[MAX_INFO_STRING];

            trap_GetUserinfo( cl->ps.clientNum, userinfo, sizeof( userinfo ) );
            ip = Info_ValueForKey (userinfo, "ip");

            // use engine banning system, mods may choose to use their own banlist
            if (USE_ENGINE_BANLIST) {

                // kick but dont ban bots, they arent that lame
                if ( (g_entities[cl->ps.clientNum].r.svFlags & SVF_BOT) ) {
                    timeout = 0;
                }
                trap_DropClient(cl->ps.clientNum, "player kicked", timeout);
            } else {
                trap_DropClient(cl->ps.clientNum, "player kicked", 0);

                // kick but dont ban bots, they arent that lame
                if ( !(g_entities[cl->ps.clientNum].r.svFlags & SVF_BOT) )
                    AddIPBan( ip );
            }

        } else {
            trap_DropClient(cl->ps.clientNum, "player kicked", 0);
        }
    }
}
Esempio n. 7
0
void JMP_AdminExecuteCommand( gentity_t *pEntity, sAdminData_t *am, int trueTarget )
{
	char		zUserInfo[MAX_TOKEN_CHARS];

	char		par1[MAX_TOKEN_CHARS]; // Used
	char		par2[MAX_TOKEN_CHARS];
	char		par3[MAX_TOKEN_CHARS];
	char		par4[MAX_TOKEN_CHARS];
	char		par5[MAX_TOKEN_CHARS];

	int			clientNum = pEntity->s.number;
	int			targetNum = trueTarget;
	int			i = 0;

	trap_Argv( 1, par1, sizeof( par1 ));
	trap_Argv( 2, par2, sizeof( par2 ));
	trap_Argv( 3, par3, sizeof( par3 ));
	trap_Argv( 4, par4, sizeof( par4 ));
	trap_Argv( 5, par5, sizeof( par5 ));

	if ( targetNum == -1 )
	{
		if ( JMP_AdminNoAccess( clientNum, am->iCmdFlag ))
		{
			return;
		}

		targetNum = JMP_GetTarget( pEntity, par1 );

		if ( targetNum == -1 && !am->bAllowAll )
		{
			JMP_AdminMessage( clientNum, "You are not allowed to use this command on multiple persons" );
			return;
		}
		else if ( targetNum == -2 )
		{
			JMP_AdminMessage( clientNum, "No target has been found in your crosshair" );
			return;
		}
		else if ( targetNum == -3 )
		{
			JMP_AdminMessage( clientNum, "No target matching your specifications has been found" );
			return;
		}
		else if ( targetNum == -4 )
		{
			JMP_AdminMessage( clientNum, "Multiple matches have been found, only one is allowed" );
			return;
		}
		else if ( targetNum == clientNum && !am->bAllowSelf )
		{
#ifndef _DEBUG
			JMP_AdminMessage( clientNum, "This command may not be executed upon yourself" );
			return;
#endif
		}
		else if ( targetNum != -1 && targetNum != clientNum && sPlayerData[targetNum]->iAdminLogged && sPlayerData[targetNum]->iAdminLogged <= sPlayerData[clientNum]->iAdminLogged && JMP_AdminEvilCommand( am->iCmdFlag ))
		{
			JMP_AdminMessage( clientNum, "This command may not be executed upon an equal/higher ranked admin" );
			return;
		}
	}

	if ( targetNum == -1 )
	{
		for ( i = 0; i < MAX_CLIENTS; i++ )
		{
			if ( !sPlayerData[i]->iInUse
				|| ( i == clientNum && !am->bAllowSelf )
				|| ( i != clientNum && sPlayerData[i]->iAdminLogged && sPlayerData[i]->iAdminLogged <= sPlayerData[clientNum]->iAdminLogged && JMP_AdminEvilCommand( am->iCmdFlag )))
			{
				continue;
			}

			JMP_AdminExecuteCommand( pEntity, am, i );
		}

		return;
	}

	if ( !sPlayerData[targetNum]->iInUse )
	{
		return;
	}

	switch( am->iCmdFlag )
	{
		case DS_KICK:
		{
			if ( !strlen( par2 ))
			{
				JMP_DropPlayer( g_entities[targetNum], "has been kicked." );
			}
			else
			{
				JMP_DropPlayer( g_entities[targetNum], va( "has been kicked. (^3 Reason^7: ^1%s ^7)", ConcatArgs( 2 )));
			}

			break;
		}

		case DS_KICKBAN:
		case DS_BANRANGE:
		{
			// Initialize the ban for each type of command.
			if ( am->iCmdFlag == DS_KICKBAN )
			{
				trap_SendConsoleCommand( EXEC_APPEND, va("addip %i.%i.%i.%i", sPlayerData[targetNum]->iPlayerIP[0], sPlayerData[targetNum]->iPlayerIP[1], sPlayerData[targetNum]->iPlayerIP[2], sPlayerData[targetNum]->iPlayerIP[3] ));
			}
			else
			{
				trap_SendConsoleCommand( EXEC_APPEND, va("addip %i.%i.0.0", sPlayerData[targetNum]->iPlayerIP[0], sPlayerData[targetNum]->iPlayerIP[1] ));
			}

			// Give the message for the ban, good bye player!
			if ( !strlen( par2 ))
			{
				JMP_DropPlayer( g_entities[targetNum], "has been banned." );
			}
			else
			{
				JMP_DropPlayer( g_entities[targetNum], va( "has been banned. (^3 Reason^7: ^1%s ^7)", ConcatArgs( 2 )));
			}

			break;
		}

		case DS_SLAP:
		{
			if ( g_clients[targetNum]->stats[STAT_HEALTH] <= 0 )
			{
				JMP_AdminMessage( clientNum, "This player is not alive!" );
				break;
			}

			if ( !( sPlayerData[targetNum]->iClientEffect & ( 1 << F_SLEEP )) && !( sPlayerData[targetNum]->iClientEffect & ( 1 << F_PUNISH )))
			{
				int				iAngle;
				vec3_t			vDir;

				if ( g_clients[targetNum]->saberHolstered != 2 )
				{
					g_clients[targetNum]->saberHolstered = 2;
				}

				VectorNormalize2( g_clients[clientNum]->velocity, vDir );
				VectorScale( vDir, -1, vDir );
				iAngle = g_clients[clientNum]->viewangles[YAW] * ( M_PI * 2 / 360 );
				
				vDir[1] = ( sin( iAngle ) * 500 );
				vDir[0] = ( cos( iAngle ) * 500 );

				g_clients[targetNum]->velocity[0] = vDir[0];
				g_clients[targetNum]->velocity[1] = vDir[1];
				g_clients[targetNum]->velocity[2] = 500;

				g_clients[targetNum]->forceHandExtend = HANDEXTEND_KNOCKDOWN + bMovieBattles;
				g_clients[targetNum]->forceHandExtendTime = sWorldData->iTime + 3000;
				g_clients[targetNum]->forceDodgeAnim = 0;
			}

			break;
		}

		case DS_SLEEP:
		{
			if ( !( sPlayerData[targetNum]->iClientEffect & ( 1 << F_SLEEP )) && !( sPlayerData[targetNum]->iClientEffect & ( 1 << F_PUNISH )))
			{
				if ( g_clients[targetNum]->saberHolstered != 2 )
				{
					g_clients[targetNum]->saberHolstered = 2;
				}

				sPlayerData[targetNum]->iClientEffect |= ( 1 << F_SLEEP );
				g_clients[targetNum]->forceHandExtend = HANDEXTEND_KNOCKDOWN + bMovieBattles;
				g_clients[targetNum]->forceHandExtendTime = sWorldData->iTime + INFINITE;
				g_clients[targetNum]->forceDodgeAnim = 0;
			}

			break;
		}

		case DS_WAKE:
		{
			if ( sPlayerData[targetNum]->iClientEffect & ( 1 << F_SLEEP ))
			{
				sPlayerData[targetNum]->iClientEffect &= ~( 1 << F_SLEEP );
				g_clients[targetNum]->forceHandExtendTime = sWorldData->iTime + 500;
			}

			break;
		}

		case DS_PUNISH:
		{
			if ( !( sPlayerData[targetNum]->iClientEffect & ( 1 << F_SLEEP )) && !( sPlayerData[targetNum]->iClientEffect & ( 1 << F_PUNISH )))
			{
				if ( g_clients[targetNum]->saberHolstered != 2 )
				{
					g_clients[targetNum]->saberHolstered = 2;
				}

				sPlayerData[targetNum]->iClientEffect |= ( 1 << F_PUNISH );

				g_clients[targetNum]->forceHandExtend = HANDEXTEND_CHOKE + bMovieBattles;
				g_clients[targetNum]->forceHandExtendTime = sWorldData->iTime + INFINITE;
				g_clients[targetNum]->forceGripChangeMovetype = PM_FLOAT;
			}

			break;
		}

		case DS_UNPUNISH:
		{
			if ( sPlayerData[targetNum]->iClientEffect & ( 1 << F_PUNISH ))
			{
				sPlayerData[targetNum]->iClientEffect &= ~( 1 << F_PUNISH );

				g_clients[targetNum]->forceHandExtend = HANDEXTEND_NONE + bMovieBattles;
				g_clients[targetNum]->forceHandExtendTime = sWorldData->iTime;
				g_clients[targetNum]->forceGripChangeMovetype = PM_NORMAL;
			}

			break;
		}

		case DS_SILENCE:
		{
			if ( !( sPlayerData[targetNum]->iClientEffect & ( 1 << F_SILENCE )))
			{
				sPlayerData[targetNum]->iClientEffect |= ( 1 << F_SILENCE );
			}

			break;
		}

		case DS_UNSILENCE:
		{
			if ( sPlayerData[targetNum]->iClientEffect & ( 1 << F_SILENCE ))
			{
				sPlayerData[targetNum]->iClientEffect &= ~( 1 << F_SILENCE );
			}

			break;
		}

		case DS_PSAY:
		{
			if ( trap_Argc() < 2 )
			{
				JMP_AdminMessage( clientNum, "Enter a message to broadcast" );
				return;
			}

			JMP_StringEscape( ConcatArgs( 2 ), zUserInfo );
			JMP_SendCommand( targetNum, "cp", zUserInfo );
			break;
		}

		case DS_RENAME:
		{
			if ( trap_Argc() < 3 )
			{
				JMP_AdminMessage( clientNum, "Please enter a new name to set for the player" );
				return;
			}

			JMP_SendCommand( -1, "print", va( "%s ^7has been renamed to %s ^7by %s^7.\n", sPlayerData[targetNum]->zPlayerName, ConcatArgs( 2 ), sPlayerData[clientNum]->zPlayerName ));
				
			trap_GetUserinfo( targetNum, zUserInfo, MAX_INFO_STRING );
			Info_SetValueForKey( zUserInfo, "name", ConcatArgs( 2 ));
			trap_SetUserinfo( targetNum, zUserInfo );

			( *pVmMain )( GAME_CLIENT_USERINFO_CHANGED, targetNum, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
			break;
		}

		case DS_EXPLODE:
		{
			if ( g_clients[targetNum]->stats[STAT_HEALTH] <= 0 )
			{
				JMP_AdminMessage( clientNum, "This player is not alive!" );
				break;
			}

			if ( g_clients[targetNum]->clientNum == targetNum )
			{
				void ( *pCmd_Kill_f )( gentity_t * ) = ( void ( * )( gentity_t * )) dlsym( hHandle, "Cmd_Kill_f" );

				if ( pCmd_Kill_f == NULL )
				{
					JMP_AdminMessage( clientNum, "This function is not supported on this modification or operating system!" );
					return;
				}

				pCmd_Kill_f( g_entities[targetNum] );
			}

			break;
		}

		case DS_FORCETEAM:
		{
			if ( par2[0] == 'R' || par2[0] == 'r' || Q_stricmpn( par2, "red", 3 )
				|| par2[0] == 'B' || par2[0] == 'b' || Q_stricmpn( par2, "blue", 4 )
				|| par2[0] == 'S' || par2[0] == 's' || Q_stricmpn( par2, "spec", 4 ))
			{
				trap_SendConsoleCommand( EXEC_APPEND, va( "forceteam %i %s", targetNum, par2 ));
			}
			else
			{
				JMP_AdminMessage( clientNum, "The specified team is not recognized!" );
			}

			break;
		}

		case DS_CONTROLHUMAN:
		{
			if ( sPlayerData[clientNum]->bControlMaster )
			{
				if ( sPlayerData[clientNum]->iControlMaster == targetNum )
				{
					// Release him from your control.
					sPlayerData[sPlayerData[clientNum]->iControlMaster]->bControlSlave = qfalse;
					sPlayerData[sPlayerData[clientNum]->iControlMaster]->iControlMaster = 0;

					// Release self from underpression.
					sPlayerData[clientNum]->bControlMaster = qfalse;
					sPlayerData[clientNum]->iControlMaster = 0;
				}
				else
				{
					// Release previous target from your control.
					sPlayerData[sPlayerData[clientNum]->iControlMaster]->bControlSlave = qfalse;
					sPlayerData[sPlayerData[clientNum]->iControlMaster]->iControlMaster = 0;

					// Put the new target under your juristiction!
					sPlayerData[targetNum]->bControlSlave = qtrue;
					sPlayerData[targetNum]->iControlMaster = clientNum;

					// Set self to static mode.
					sPlayerData[clientNum]->bControlMaster = qtrue;
					sPlayerData[clientNum]->iControlMaster = targetNum;
				}
			}
			else
			{
				// Put the new target under your juristiction!
				sPlayerData[targetNum]->bControlSlave = qtrue;
				sPlayerData[targetNum]->iControlMaster = clientNum;

				// Set self to static mode.
				sPlayerData[clientNum]->bControlMaster = qtrue;
				sPlayerData[clientNum]->iControlMaster = targetNum;
			}

			break;
		}

		case DS_IGNORE:
		{
			if ( sPlayerData[clientNum]->iIgnoreList & ( 1 << targetNum ))
			{
				sPlayerData[clientNum]->iIgnoreList &= ~( 1 << targetNum );
				JMP_AdminMessage( clientNum, va( "%s ^7is now unignored", sPlayerData[targetNum]->zPlayerName ));
			}
			else
			{
				sPlayerData[clientNum]->iIgnoreList |= ( 1 <<  targetNum );
				JMP_AdminMessage( clientNum, va( "%s ^7is now ignored", sPlayerData[targetNum]->zPlayerName ));
			}

			break;
		}
	}
}
Esempio n. 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;
}
Esempio n. 9
0
/**
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		name[MAX_NETNAME];
	char		*value, *nameError;
	gclient_t	*client;
	char		userinfo[MAX_INFO_STRING];
	gentity_t	*ent;

	ent = &g_entities[ clientNum ];

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

	if (G_BanCheck(userinfo)) {
		return "You are banned from this server.";
	}

	value = Info_ValueForKey(userinfo, "ip");

	nameError = Info_ValueForKey(userinfo, "name");
	nameError = ClientCleanName(nameError, name, sizeof name);

	// 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")) {
		// check for invalid player name
		if (nameError) {
			return nameError;
		}

		// 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";
		}
	}
	// 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;

	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";
		}
	}

	// don't do the "xxx connected" messages if they were caried over from previous level
	if (firstTime) {
		ClientScreenPrint(NULL, "%s ^7connected", name);
	}

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

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

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

	return NULL;
}
Esempio n. 10
0
/**
Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
*/
void ClientSpawn(gentity_t *ent)
{
	int		index;
	vec3_t	spawn_origin, spawn_angles;
	gclient_t	*client;
	clientPersistant_t	saved;
	clientSession_t		savedSess;
	int				persistant[MAX_PERSISTANT];
	gentity_t		*spawnPoint;
	gentity_t		*tent;
	int		flags;
	int		eventSequence;
	char	userinfo[MAX_INFO_STRING];

	index = ent - g_entities;
	client = ent->client;

	// follow other players when eliminated
	if (!level.warmupTime && g_gametype.integer == GT_ELIMINATION
		&& client->sess.sessionTeam != TEAM_SPECTATOR)
	{
		if (level.roundStarted) {
			client->sess.spectatorState = SPECTATOR_FREE;
			client->eliminated = qtrue;
			return;
		} else {
			client->sess.spectatorState = SPECTATOR_NOT;
			client->eliminated = qfalse;
		}
	}

	VectorClear(spawn_origin);

	// find a spawn point
	// do it before setting health back up, so farthest
	// ranging doesn't count this client
	if (client->sess.sessionTeam == TEAM_SPECTATOR) {
		SelectSpectatorSpawnPoint(spawn_origin, spawn_angles);
	} else if (g_gametype.integer == GT_DEFRAG) {
		spawnPoint = SelectDefragSpawnPoint(spawn_origin, spawn_angles);
	} else if (g_gametype.integer == GT_CTF) {
		spawnPoint = SelectCTFSpawnPoint(client->sess.sessionTeam,
			spawn_origin, spawn_angles, !!(ent->r.svFlags & SVF_BOT));
	} else if (client->pers.lastKiller) {
		spawnPoint = SelectSpawnPoint(client->pers.lastKiller->ps.origin, spawn_origin,
			spawn_angles, ent->r.svFlags & SVF_BOT);
	} else {
		spawnPoint = SelectSpawnPoint(client->ps.origin, spawn_origin,
			spawn_angles, ent->r.svFlags & SVF_BOT);
	}

	if (!spawnPoint) {
		G_Error("Cannot find a spawn point.\n");
		return;
	}

	// toggle the teleport bit so the client knows to not lerp
	flags = ent->client->ps.eFlags & (EF_TELEPORT_BIT);
	flags ^= EF_TELEPORT_BIT;

	// unlagged - backward reconciliation #3
	// we don't want players being backward-reconciled to the place they died
	G_ResetHistory( ent );
	// and this is as good a time as any to clear the saved state
	ent->client->saved.leveltime = 0;

	// clear everything but the persistant data

	saved = client->pers;
	savedSess = client->sess;
	eventSequence = client->ps.eventSequence;
	Com_Memcpy(persistant, client->ps.persistant, sizeof persistant);

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

	client->pers = saved;
	client->sess = savedSess;
	client->ps.eventSequence = eventSequence;
	Com_Memcpy(client->ps.persistant, persistant, sizeof client->ps.persistant);

	// increment the spawncount so the client will detect the respawn
	client->ps.persistant[PERS_SPAWN_COUNT]++;
	client->ps.persistant[PERS_TEAM] = client->sess.sessionTeam;

	client->airOutTime = level.time + 12000;

	trap_GetUserinfo(index, userinfo, sizeof(userinfo));
	// set max health
	client->pers.maxHealth = atoi(Info_ValueForKey(userinfo, "handicap"));
	if (client->pers.maxHealth < 1 || client->pers.maxHealth > 100) {
		client->pers.maxHealth = 100;
	}
	// clear entity values
	client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;
	client->ps.eFlags = flags;

	ent->s.groundEntityNum = ENTITYNUM_NONE;
	ent->client = &level.clients[index];
	ent->takedamage = qtrue;
	ent->inuse = qtrue;
	ent->classname = "player";
	ent->r.contents = CONTENTS_BODY;
	ent->clipmask = MASK_PLAYERSOLID;
	ent->die = player_die;
	ent->waterlevel = 0;
	ent->watertype = 0;
	ent->flags &= ~FL_NO_KNOCKBACK;
	ent->flags &= ~FL_FORCE_GESTURE;

	VectorCopy(playerMins, ent->r.mins);
	VectorCopy(playerMaxs, ent->r.maxs);

	client->ps.clientNum = index;

	ClientGiveWeapons(client);

	if (g_gametype.integer == GT_ELIMINATION) {
		client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] * 2;
		client->ps.stats[STAT_ARMOR] = client->ps.stats[STAT_MAX_HEALTH] * 1.5;
	} else {
		client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] + 25;
	}
	ent->health = client->ps.stats[STAT_HEALTH];

	G_SetOrigin(ent, spawn_origin);
	VectorCopy(spawn_origin, client->ps.origin);

	// the respawned flag will be cleared after the attack and jump keys come up
	client->ps.pm_flags |= PMF_RESPAWNED;

	trap_GetUsercmd(client - level.clients, &ent->client->pers.cmd);
	SetClientViewAngle(ent, spawn_angles);
	// don't allow full run speed for a bit
	client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
	client->ps.pm_time = 100;

	client->respawnTime = level.time;
	client->inactivityTime = level.time + g_inactivity.integer * 1000;
	client->latched_buttons = 0;

	// set default animations
	client->ps.torsoAnim = TORSO_STAND;
	client->ps.legsAnim = LEGS_IDLE;

	if (level.intermissiontime) {
		// move players to intermission
		MoveClientToIntermission(ent);
	} else if (ent->client->sess.sessionTeam != TEAM_SPECTATOR) {
		G_KillBox(ent);

		// fire the targets of the spawn point
		G_UseTargets(spawnPoint, ent);

		// positively link the client, even if the command times are weird
		VectorCopy(ent->client->ps.origin, ent->r.currentOrigin);

		tent = G_TempEntity(ent->client->ps.origin, EV_PLAYER_TELEPORT_IN);
		tent->s.clientNum = ent->s.clientNum;

		trap_LinkEntity (ent);
	}

	// run a client frame to drop exactly to the floor,
	// initialize animations and other things
	client->ps.commandTime = level.totalTime - 100;
	client->pers.cmd.serverTime = level.totalTime;
	ClientThink(ent-g_entities);
	// run the presend to set anything else, follow spectators wait
	// until all clients have been reconnected after map_restart
	if (ent->client->sess.spectatorState != SPECTATOR_FOLLOW) {
		ClientEndFrame(ent);
	}

	// clear entity state values
	BG_PlayerStateToEntityState(&client->ps, &ent->s, qtrue);
}
Esempio n. 11
0
/**
Called from ClientConnect when the player first connects and
directly by the server system when the player updates a userinfo variable.

The game can override any of the settings and call trap_SetUserinfo
if desired.
*/
void ClientUserinfoChanged(int clientNum)
{
	gentity_t *ent;
	int		teamTask, teamLeader, team, health;
	char	*s;
	char	oldname[MAX_STRING_CHARS];
	gclient_t	*client;
	char	userinfo[MAX_INFO_STRING];
	char	*nameError;

	ent = g_entities + clientNum;
	client = ent->client;

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

	// check for malformed or illegal info strings
	if (!Info_Validate(userinfo)) {
		strcpy (userinfo, "\\name\\badinfo");
		// don't keep those clients and userinfo
		trap_DropClient(clientNum, "Invalid userinfo");
	}

	// check for local client
	s = Info_ValueForKey(userinfo, "ip");
	if (!strcmp(s, "localhost")) {
		client->pers.localClient = qtrue;
	}

	// check the item prediction
	s = Info_ValueForKey(userinfo, "cg_predictItems");
	if (!atoi(s)) {
		client->pers.predictItemPickup = qfalse;
	} else {
		client->pers.predictItemPickup = qtrue;
	}

	// set name
	Q_strncpyz(oldname, client->pers.netname, sizeof(oldname));
	s = Info_ValueForKey(userinfo, "name");
	nameError = ClientCleanName(s, client->pers.netname, sizeof client->pers.netname);

	if (client->pers.connected == CON_CONNECTED && strcmp(oldname, s)) {
		if (client->pers.muted) {
			ClientPrint(ent, "You cannot change your name while you are muted.");
		} else if (nameError) {
			ClientPrint(ent, "%s", nameError);
		} else {
			G_LogPrintf("%s ^7renamed to %s\n", oldname, client->pers.netname);
		}

		if (nameError || client->pers.muted) {
			Q_strncpyz(client->pers.netname, oldname, sizeof client->pers.netname);
		}
	}

	if (client->sess.sessionTeam == TEAM_SPECTATOR) {
		if (client->sess.spectatorState == SPECTATOR_SCOREBOARD) {
			Q_strncpyz(client->pers.netname, "scoreboard", sizeof(client->pers.netname));
		}
	}

	// set max health
	health = atoi(Info_ValueForKey(userinfo, "handicap"));
	client->pers.maxHealth = health;
	if (client->pers.maxHealth < 1 || client->pers.maxHealth > 100) {
		client->pers.maxHealth = 100;
	}
	client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;

	// bots set their team a few frames later
	if (g_gametype.integer >= GT_TEAM && g_entities[clientNum].r.svFlags & SVF_BOT) {
		s = Info_ValueForKey(userinfo, "team");
		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);
		}
	}
	else {
		team = client->sess.sessionTeam;
	}

	// team task (0 = none, 1 = offence, 2 = defence)
	teamTask = atoi(Info_ValueForKey(userinfo, "teamtask"));
	// team Leader (1 = leader, 0 is normal player)
	teamLeader = client->sess.teamLeader;

	// send over a subset of the userinfo keys so other clients can
	// print scoreboards, display models, and play custom sounds
	if (ent->r.svFlags & SVF_BOT) {
		s = va("n\\%s\\t\\%i\\hc\\%i\\w\\%i\\l\\%i\\skill\\%s\\tt\\%d\\tl\\%d",
			client->pers.netname, team, client->pers.maxHealth,
			client->sess.wins, client->sess.losses,
			Info_ValueForKey(userinfo, "skill"), teamTask, teamLeader);
	}
	else {
		s = va("n\\%s\\t\\%i\\s\\%d\\r\\%i\\hc\\%i\\w\\%i\\l\\%i\\tt\\%d\\tl\\%d",
			client->pers.netname, team, client->sess.specOnly,
			client->pers.ready, client->pers.maxHealth,
			client->sess.wins, client->sess.losses, teamTask, teamLeader);
	}

	trap_SetConfigstring(CS_PLAYERS+clientNum, s);

	// this is not the userinfo, more like the configstring actually
	G_LogPrintf("ClientUserinfoChanged: %i %s\n", clientNum, s);
}
Esempio n. 12
0
File: g_bot.c Progetto: jwginge/ojpa
//[TABBot]
//added bot type varible
static void G_AddBot( const char *name, float skill, const char *team, int delay, char *altname, int bottype) {
//static void G_AddBot( const char *name, float skill, const char *team, int delay, char *altname) {
//[/TABBot]
	int				clientNum;
	char			*botinfo;
	gentity_t		*bot;
	char			*key;
	char			*s;
	char			*botname;
	char			*model;
//	char			*headmodel;
	char			userinfo[MAX_INFO_STRING];
	int				preTeam = 0;
	//[DuelGuns][EnhancedImpliment]
	/*
	char			*firearm; //** change gun model	
	qboolean		bot_dualguns = qfalse;
	int				gunoption=0;
	*/
	//[/DuelGuns][EnhancedImpliment]

	// get the botinfo from bots.txt
	botinfo = G_GetBotInfoByName( name );
	if ( !botinfo ) {
		G_Printf( S_COLOR_RED "Error: Bot '%s' not defined\n", name );
		return;
	}

	// create the bot's userinfo
	userinfo[0] = '\0';

	botname = Info_ValueForKey( botinfo, "funname" );
	if( !botname[0] ) {
		botname = Info_ValueForKey( botinfo, "name" );
	}
	// check for an alternative name
	if (altname && altname[0]) {
		botname = altname;
	}
	Info_SetValueForKey( userinfo, "name", botname );
	Info_SetValueForKey( userinfo, "rate", "25000" );
	Info_SetValueForKey( userinfo, "snaps", "20" );
	Info_SetValueForKey( userinfo, "skill", va("%1.2f", skill) );

	if ( skill >= 1 && skill < 2 ) {
		Info_SetValueForKey( userinfo, "handicap", "50" );
	}
	else if ( skill >= 2 && skill < 3 ) {
		Info_SetValueForKey( userinfo, "handicap", "70" );
	}
	else if ( skill >= 3 && skill < 4 ) {
		Info_SetValueForKey( userinfo, "handicap", "90" );
	}

	key = "model";
	model = Info_ValueForKey( botinfo, key );
	if ( !*model ) {
		model = "kyle/default";
	}
	Info_SetValueForKey( userinfo, key, model );

/*	key = "headmodel";
	headmodel = Info_ValueForKey( botinfo, key );
	if ( !*headmodel ) {
		headmodel = model;
	}
	Info_SetValueForKey( userinfo, key, headmodel );
	key = "team_headmodel";
	Info_SetValueForKey( userinfo, key, headmodel );
*/
	key = "gender";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "male";
	}
	Info_SetValueForKey( userinfo, "sex", s );

	key = "color1";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "4";
	}
	Info_SetValueForKey( userinfo, key, s );

	key = "color2";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "4";
	}
	Info_SetValueForKey( userinfo, key, s );

	key = "saber1";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "single_1";
	}
	Info_SetValueForKey( userinfo, key, s );

	key = "saber2";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "none";
	}
	Info_SetValueForKey( userinfo, key, s );

	s = Info_ValueForKey(botinfo, "personality");
	if (!*s )
	{
		Info_SetValueForKey( userinfo, "personality", "botfiles/default.jkb" );
	}
	else
	{
		Info_SetValueForKey( userinfo, "personality", s );
	}

	//[DuelGuns][EnhancedImpliment]
	/*
//	if(1)//f_dualguns.integer)
//	{
		key = "dualgun";
		s = Info_ValueForKey(botinfo, key);
		if (*s)
		{
			gunoption = atoi(s);
		}
		if(gunoption>0)
			bot_dualguns = qtrue;
//	}

	firearm = Info_ValueForKey( botinfo, "firearm");
	if (!*firearm)
	{
		Info_SetValueForKey( userinfo, "firearm", botname );
	}
	else
	{
		Info_SetValueForKey( userinfo, "firearm", firearm);
	}
	*/
	//[/DuelGuns][EnhancedImpliment]

	//[RGBSabers]
	key = "rgb_saber1";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "255,0,0";
	}
	Info_SetValueForKey( userinfo, key, s );

	key = "rgb_saber2";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "0,255,255";
	}
	Info_SetValueForKey( userinfo, key, s );

	key = "rgb_script1";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "none";
	}
	Info_SetValueForKey( userinfo, key, s );

	key = "rgb_script2";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "none";
	}
	Info_SetValueForKey( userinfo, key, s );
	//[/RGBSabers]

	//[ClientPlugInDetect]
	//set it so that the bots are assumed to have the OJP client plugin
	//this should be CURRENT_OJPENHANCED_CLIENTVERSION
	Info_SetValueForKey( userinfo, "ojp_clientplugin", CURRENT_OJPENHANCED_CLIENTVERSION );
	//[/ClientPlugInDetect]

	// have the server allocate a client slot
	clientNum = trap_BotAllocateClient();
	if ( clientNum == -1 ) {
//		G_Printf( S_COLOR_RED "Unable to add bot.  All player slots are in use.\n" );
//		G_Printf( S_COLOR_RED "Start server with more 'open' slots.\n" );
		trap_SendServerCommand( -1, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "UNABLE_TO_ADD_BOT")));
		return;
	}

	//[DuelGuns][EnhancedImpliment]
	/*
	if(bot_dualguns)
	{
		g_entities[clientNum].client->ps.dualguns = 1;		
	}
	*/
	//[/DuelGuns][EnhancedImpliment]

	// initialize the bot settings
	if( !team || !*team ) {
		if( g_gametype.integer >= GT_TEAM ) {
			//[AdminSys]
			if( PickTeam(clientNum, qtrue) == TEAM_RED) {
			//if( PickTeam(clientNum) == TEAM_RED) {
			//[/AdminSys]
				team = "red";
			}
			else {
				team = "blue";
			}
		}
		else {
			team = "red";
		}
	}
//	Info_SetValueForKey( userinfo, "characterfile", Info_ValueForKey( botinfo, "aifile" ) );
	Info_SetValueForKey( userinfo, "skill", va( "%5.2f", skill ) );
	Info_SetValueForKey( userinfo, "team", team );
	//[TABBot]
	Info_SetValueForKey( userinfo, "bottype", va( "%i", bottype) );
	//[/TABBot]

	bot = &g_entities[ clientNum ];
	bot->r.svFlags |= SVF_BOT;
	bot->inuse = qtrue;

	// register the userinfo
	trap_SetUserinfo( clientNum, userinfo );

	//[NewGameTypes][EnhancedImpliment]
	//if (g_gametype.integer >= GT_TEAM && g_gametype.integer != GT_RPG)
	if (g_gametype.integer >= GT_TEAM)
	//[/NewGameTypes][EnhancedImpliment]
	{
		if (team && Q_stricmp(team, "red") == 0)
		{
			bot->client->sess.sessionTeam = TEAM_RED;
		}
		else if (team && Q_stricmp(team, "blue") == 0)
		{
			bot->client->sess.sessionTeam = TEAM_BLUE;
		}
		else
		{
			//[AdminSys]
			bot->client->sess.sessionTeam = PickTeam( -1, qtrue );
			//bot->client->sess.sessionTeam = PickTeam( -1 );
			//[/AdminSys]
		}
	}

	if (g_gametype.integer == GT_SIEGE)
	{
		bot->client->sess.siegeDesiredTeam = bot->client->sess.sessionTeam;
		bot->client->sess.sessionTeam = TEAM_SPECTATOR;
	}

	preTeam = bot->client->sess.sessionTeam;

	// have it connect to the game as a normal client
	if ( ClientConnect( clientNum, qtrue, qtrue ) ) {
		return;
	}

	if (bot->client->sess.sessionTeam != preTeam)
	{
		trap_GetUserinfo(clientNum, userinfo, MAX_INFO_STRING);

		if (bot->client->sess.sessionTeam == TEAM_SPECTATOR)
		{
			bot->client->sess.sessionTeam = preTeam;
		}

		if (bot->client->sess.sessionTeam == TEAM_RED)
		{
			team = "Red";
		}
		else
		{
			if (g_gametype.integer == GT_SIEGE)
			{
				if (bot->client->sess.sessionTeam == TEAM_BLUE)
				{
					team = "Blue";
				}
				else
				{
					team = "s";
				}
			}
			else
			{
				team = "Blue";
			}
		}

		Info_SetValueForKey( userinfo, "team", team );

		trap_SetUserinfo( clientNum, userinfo );

		bot->client->ps.persistant[ PERS_TEAM ] = bot->client->sess.sessionTeam;

		G_ReadSessionData( bot->client );
		ClientUserinfoChanged( clientNum );
	}

	if (g_gametype.integer == GT_DUEL ||
		g_gametype.integer == GT_POWERDUEL)
	{
		int loners = 0;
		int doubles = 0;

		bot->client->sess.duelTeam = 0;
		G_PowerDuelCount(&loners, &doubles, qtrue);

		if (!doubles || loners > (doubles/2))
		{
            bot->client->sess.duelTeam = DUELTEAM_DOUBLE;
		}
		else
		{
            bot->client->sess.duelTeam = DUELTEAM_LONE;
		}

		bot->client->sess.sessionTeam = TEAM_SPECTATOR;
		SetTeam(bot, "s");
	}
	else
	{
		if( delay == 0 ) {
			ClientBegin( clientNum, qfalse );
			//UNIQUEFIX - what's the purpose of this?
			//ClientUserinfoChanged( clientNum );
			return;
		}

		AddBotToSpawnQueue( clientNum, delay );
		//UNIQUEFIX - what's the purpose of this?
		//ClientUserinfoChanged( clientNum );
	}
}
Esempio n. 13
0
/*
===============
G_AddBot
===============
*/
static void G_AddBot( const char *name, float skill, const char *team, int delay, char *altname) {
	int				clientNum;
	char			*botinfo;
	gentity_t		*bot;
	char			*key;
	char			*s;
	char			*botname;
	char			*model;
//	char			*headmodel;
	char			userinfo[MAX_INFO_STRING];
	int				preTeam = 0;

	// get the botinfo from bots.txt
	botinfo = G_GetBotInfoByName( name );
	if ( !botinfo ) {
		G_Printf( S_COLOR_RED "Error: Bot '%s' not defined\n", name );
		return;
	}

	// create the bot's userinfo
	userinfo[0] = '\0';

	botname = Info_ValueForKey( botinfo, "funname" );
	if( !botname[0] ) {
		botname = Info_ValueForKey( botinfo, "name" );
	}
	// check for an alternative name
	if (altname && altname[0]) {
		botname = altname;
	}
	Info_SetValueForKey( userinfo, "name", botname );
	Info_SetValueForKey( userinfo, "rate", "25000" );
	Info_SetValueForKey( userinfo, "snaps", "20" );
	Info_SetValueForKey( userinfo, "skill", va("%1.2f", skill) );

	if ( skill >= 1 && skill < 2 ) {
		Info_SetValueForKey( userinfo, "handicap", "50" );
	}
	else if ( skill >= 2 && skill < 3 ) {
		Info_SetValueForKey( userinfo, "handicap", "70" );
	}
	else if ( skill >= 3 && skill < 4 ) {
		Info_SetValueForKey( userinfo, "handicap", "90" );
	}

	key = "model";
	model = Info_ValueForKey( botinfo, key );
	if ( !*model ) {
		model = "visor/default";
	}
	Info_SetValueForKey( userinfo, key, model );
	key = "team_model";
	Info_SetValueForKey( userinfo, key, model );

/*	key = "headmodel";
	headmodel = Info_ValueForKey( botinfo, key );
	if ( !*headmodel ) {
		headmodel = model;
	}
	Info_SetValueForKey( userinfo, key, headmodel );
	key = "team_headmodel";
	Info_SetValueForKey( userinfo, key, headmodel );
*/
	key = "gender";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "male";
	}
	Info_SetValueForKey( userinfo, "sex", s );

	key = "color1";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "4";
	}
	Info_SetValueForKey( userinfo, key, s );

	key = "color2";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "5";
	}
	Info_SetValueForKey( userinfo, key, s );

	s = Info_ValueForKey(botinfo, "personality");
	if (!*s )
	{
		Info_SetValueForKey( userinfo, "personality", "botfiles/default.jkb" );
	}
	else
	{
		Info_SetValueForKey( userinfo, "personality", s );
	}

	// have the server allocate a client slot
	clientNum = trap_BotAllocateClient();
	if ( clientNum == -1 ) {
//		G_Printf( S_COLOR_RED "Unable to add bot.  All player slots are in use.\n" );
//		G_Printf( S_COLOR_RED "Start server with more 'open' slots.\n" );
		trap_SendServerCommand( -1, va("print \"%s\n\"", G_GetStripEdString("SVINGAME", "UNABLE_TO_ADD_BOT")));
		return;
	}

	// initialize the bot settings
	if( !team || !*team ) {
		if( g_gametype.integer >= GT_TEAM ) {
			if( PickTeam(clientNum) == TEAM_RED) {
				team = "red";
			}
			else {
				team = "blue";
			}
		}
		else {
			team = "red";
		}
	}
//	Info_SetValueForKey( userinfo, "characterfile", Info_ValueForKey( botinfo, "aifile" ) );
	Info_SetValueForKey( userinfo, "skill", va( "%5.2f", skill ) );
	Info_SetValueForKey( userinfo, "team", team );

	bot = &g_entities[ clientNum ];
	bot->r.svFlags |= SVF_BOT;
	bot->inuse = qtrue;

	// register the userinfo
	trap_SetUserinfo( clientNum, userinfo );

	if (g_gametype.integer >= GT_TEAM)
	{
		if (team && Q_stricmp(team, "red") == 0)
		{
			bot->client->sess.sessionTeam = TEAM_RED;
		}
		else if (team && Q_stricmp(team, "blue") == 0)
		{
			bot->client->sess.sessionTeam = TEAM_BLUE;
		}
		else
		{
			bot->client->sess.sessionTeam = PickTeam( -1 );
		}
	}

	preTeam = bot->client->sess.sessionTeam;

	// have it connect to the game as a normal client
	if ( ClientConnect( clientNum, qtrue, qtrue ) ) {
		return;
	}

	if (bot->client->sess.sessionTeam != preTeam)
	{
		trap_GetUserinfo(clientNum, userinfo, MAX_INFO_STRING);

		if (bot->client->sess.sessionTeam == TEAM_SPECTATOR)
		{
			bot->client->sess.sessionTeam = preTeam;
		}

		if (bot->client->sess.sessionTeam == TEAM_RED)
		{
			team = "Red";
		}
		else
		{
			team = "Blue";
		}

		Info_SetValueForKey( userinfo, "team", team );

		trap_SetUserinfo( clientNum, userinfo );

		bot->client->ps.persistant[ PERS_TEAM ] = bot->client->sess.sessionTeam;

		G_ReadSessionData( bot->client );
		ClientUserinfoChanged( clientNum );
	}

	if( delay == 0 ) {
		ClientBegin( clientNum, qfalse );
		return;
	}

	AddBotToSpawnQueue( clientNum, delay );
}
Esempio n. 14
0
/*
===============
G_AddBot
===============
*/
static void G_AddBot( const char *name, float skill, const char *team, const char *pclass, int delay, char *altname) {
	int				clientNum;
	char			*botinfo;
	gentity_t		*bot;
	char			*key;
	char			*s;
	char			*botname;
	char			*model;
	char			userinfo[MAX_INFO_STRING];
	int				preTeam = 0;

	// get the botinfo from bots.txt
	botinfo = G_GetBotInfoByName( name );
	if ( !botinfo ) {
		G_Printf( S_COLOR_RED "Error: Bot '%s' not defined\n", name );
		return;
	}

	// create the bot's userinfo
	userinfo[0] = '\0';

	botname = Info_ValueForKey( botinfo, "funname" );
	if( !botname[0] ) {
		botname = Info_ValueForKey( botinfo, "name" );
	}
	// check for an alternative name
	if (altname && altname[0]) {
		botname = altname;
	}
	Info_SetValueForKey( userinfo, "name", botname );
	Info_SetValueForKey( userinfo, "rate", "25000" );
	Info_SetValueForKey( userinfo, "snaps", "20" );
	Info_SetValueForKey( userinfo, "skill", va("%1.2f", skill) );

/*	if ( skill >= 1 && skill < 2 ) {
		Info_SetValueForKey( userinfo, "handicap", "50" );
	}
	else if ( skill >= 2 && skill < 3 ) {
		Info_SetValueForKey( userinfo, "handicap", "70" );
	}
	else if ( skill >= 3 && skill < 4 ) {
		Info_SetValueForKey( userinfo, "handicap", "90" );
	} */

	key = "model";
	model = Info_ValueForKey( botinfo, key );
	if ( !*model ) {
		model = "munro/main/default"; //RPG-X MODEL SYSTEM
	}
	Info_SetValueForKey( userinfo, key, model );

	key = "gender";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "male";
	}
	Info_SetValueForKey( userinfo, "sex", s );

	key = "color";
	s = Info_ValueForKey( botinfo, key );
	if ( !*s ) {
		s = "4";
	}
	Info_SetValueForKey( userinfo, key, s );

	s = Info_ValueForKey(botinfo, "aifile");
	if (!*s ) {
		trap_Printf( S_COLOR_RED "Error: bot has no aifile specified\n" );
		return;
	}

	// have the server allocate a client slot
	clientNum = trap_BotAllocateClient();
	if ( clientNum == -1 ) {
		G_Printf( S_COLOR_RED "Unable to add bot.  All player slots are in use.\n" );
		G_Printf( S_COLOR_RED "Start server with more 'open' slots (or check setting of sv_maxclients cvar).\n" );
		return;
	}

	// initialize the bot settings
	if( !team || !*team ) {
		if( g_gametype.integer >= GT_TEAM ) {
			if( G_Client_PickTeam(clientNum) == TEAM_RED) {
				team = "red";
			}
			else {
				team = "blue";
			}
		}
		else {
			team = "red";
		}
	}
	Info_SetValueForKey( userinfo, "characterfile", Info_ValueForKey( botinfo, "aifile" ) );
	Info_SetValueForKey( userinfo, "skill", va( "%5.2f", skill ) );
	Info_SetValueForKey( userinfo, "team", team );

	bot = &g_entities[ clientNum ];
	bot->r.svFlags |= SVF_BOT;
	bot->inuse = qtrue;

	// register the userinfo
	trap_SetUserinfo( clientNum, userinfo );

	if (g_gametype.integer >= GT_TEAM)
	{
		if (team && Q_stricmp(team, "red") == 0)
		{
			bot->client->sess.sessionTeam = TEAM_RED;
		}
		else if (team && Q_stricmp(team, "blue") == 0)
		{
			bot->client->sess.sessionTeam = TEAM_BLUE;
		}
		else
		{
			bot->client->sess.sessionTeam = G_Client_PickTeam( -1 );
		}
	}

	preTeam = bot->client->sess.sessionTeam;

	// have it connect to the game as a normal client
	if ( G_Client_Connect( clientNum, qtrue, qtrue ) ) {
		return;
	}

	if (bot->client->sess.sessionTeam != preTeam)
	{
		trap_GetUserinfo(clientNum, userinfo, MAX_INFO_STRING);

		if (bot->client->sess.sessionTeam == TEAM_SPECTATOR)
		{
			bot->client->sess.sessionTeam = preTeam;
		}

		if (bot->client->sess.sessionTeam == TEAM_RED)
		{
			team = "Red";
		}
		else
		{
			team = "Blue";
		}

		Info_SetValueForKey( userinfo, "team", team );

		trap_SetUserinfo( clientNum, userinfo );

		bot->client->ps.persistant[ PERS_TEAM ] = bot->client->sess.sessionTeam;

		G_ReadSessionData( bot->client );
		G_Client_UserinfoChanged( clientNum );
	}

	if( delay == 0 ) {
		G_Client_Begin( clientNum, qfalse, qfalse, qfalse );
		return;
	}

	AddBotToSpawnQueue( clientNum, delay );
}
Esempio n. 15
0
// ************** PLAYERS
//
// Show client info
void G_players_cmd( gentity_t *ent, unsigned int dwCommand, qboolean fValue ) {
	int i, idnum, max_rate, cnt = 0, tteam;
	int user_rate, user_snaps;
	gclient_t *cl;
	gentity_t *cl_ent;
	char n2[MAX_NETNAME], ready[16], ref[16], rate[256];
	const char *s;
    const char* tc;
    const char* coach;
    char userinfo[MAX_INFO_STRING];


	if ( g_gamestate.integer == GS_PLAYING ) {
		if ( ent ) {
			CP( "print \"\n^3 ID^1 : ^3Player                    Nudge  Rate  MaxPkts  Snaps\n\"" );
			CP(  "print \"^1-----------------------------------------------------------^7\n\"" );
		} else {
			G_Printf( " ID : Player                    Nudge  Rate  MaxPkts  Snaps\n" );
			G_Printf( "-----------------------------------------------------------\n" );
		}
	} else {
		if ( ent ) {
			CP( "print \"\n^3Status^1   : ^3ID^1 : ^3Player                    Nudge  Rate  MaxPkts  Snaps\n\"" );
			CP(  "print \"^1---------------------------------------------------------------------^7\n\"" );
		} else {
			G_Printf( "Status   : ID : Player                    Nudge  Rate  MaxPkts  Snaps\n" );
			G_Printf( "---------------------------------------------------------------------\n" );
		}
	}

	max_rate = trap_Cvar_VariableIntegerValue( "sv_maxrate" );

	for ( i = 0; i < level.numConnectedClients; i++ ) {
		idnum = level.sortedClients[i]; //level.sortedNames[i];
		cl = &level.clients[idnum];
		cl_ent = g_entities + idnum;

		SanitizeString( cl->pers.netname, n2, qtrue );
		n2[26] = 0;
		ref[0] = 0;
		ready[0] = 0;

		// Rate info
		if ( cl_ent->r.svFlags & SVF_BOT ) {
			strcpy( rate, va( "%s%s%s%s", "[BOT]", " -----", "       --", "     --" ) );
		} else if ( cl->pers.connected == CON_CONNECTING ) {
			strcpy( rate, va( "%s", "^3>>> CONNECTING <<<" ) );
		} else {
			trap_GetUserinfo( idnum, userinfo, sizeof( userinfo ) );
			s = Info_ValueForKey( userinfo, "rate" );
			user_rate = ( max_rate > 0 && atoi( s ) > max_rate ) ? max_rate : atoi( s );
			s = Info_ValueForKey( userinfo, "snaps" );
			user_snaps = atoi( s );

			strcpy( rate, va( "%5d%6d%9d%7d", cl->pers.clientTimeNudge, user_rate, cl->pers.clientMaxPackets, user_snaps ) );
		}

		if ( g_gamestate.integer != GS_PLAYING ) {
			if ( cl->sess.sessionTeam == TEAM_SPECTATOR || cl->pers.connected == CON_CONNECTING ) {
				strcpy( ready, ( ( ent ) ? "^5--------^1 :" : "-------- :" ) );
			} else if ( cl->pers.ready || ( g_entities[idnum].r.svFlags & SVF_BOT ) ) {
				strcpy( ready, ( ( ent ) ? "^3(READY)^1  :" : "(READY)  :" ) );
			} else {
				strcpy( ready, ( ( ent ) ? "NOTREADY^1 :" : "NOTREADY :" ) );
			}
		}

		if ( cl->sess.referee ) {
			strcpy( ref, "REF" );
		}

		if ( cl->sess.coach_team ) {
			tteam = cl->sess.coach_team;
			coach = ( ent ) ? "^3C" : "C";
		} else {
			tteam = cl->sess.sessionTeam;
			coach = " ";
		}

		tc = ( ent ) ? "^7 " : " ";
		if ( g_gametype.integer >= GT_WOLF ) {
			if ( tteam == TEAM_AXIS ) {
				tc = ( ent ) ? "^1X^7" : "X";
			}
			if ( tteam == TEAM_ALLIES ) {
				tc = ( ent ) ? "^4L^7" : "L";
			}
		}

		if ( ent ) {
			CP( va( "print \"%s%s%2d%s^1:%s %-26s^7%s  ^3%s\n\"", ready, tc, idnum, coach, ( ( ref[0] ) ? "^3" : "^7" ), n2, rate, ref ) );
		} else { G_Printf( "%s%s%2d%s: %-26s%s  %s\n", ready, tc, idnum, coach, n2, rate, ref );}

		cnt++;
	}

	if ( ent ) {
		CP( va( "print \"\n^3%2d^7 total players\n\n\"", cnt ) );
	} else { G_Printf( "\n%2d total players\n\n", cnt );}

	// Team speclock info
	if ( g_gametype.integer >= GT_WOLF ) {
		for ( i = TEAM_AXIS; i <= TEAM_ALLIES; i++ ) {
			if ( teamInfo[i].spec_lock ) {
				if ( ent ) {
					CP( va( "print \"** %s team is speclocked.\n\"", aTeams[i] ) );
				} else { G_Printf( "** %s team is speclocked.\n", aTeams[i] );}
			}
		}
	}
}
Esempio n. 16
0
void Svcmd_BanUser_f( void )
{
	char		str[MAX_TOKEN_CHARS];
	char		userInfo[MAX_TOKEN_CHARS];
	idFilter_t	id;
	int			playerNum;
	char		*ip;

	if ( trap_Argc() < 2 )
	{
		G_Printf("Usage: banUser <client ID> <reason for banning>\n");
		return;		
	}

	trap_Argv( 1, str, sizeof( str ) );

	playerNum = atoi(str);
	if ( playerNum > MAX_CLIENTS || playerNum < 0 || !g_entities[playerNum].client )
	{
		G_Printf("Error: Player ID wasn't valid.\n");
		return;			
	}
	
	trap_GetUserinfo( playerNum, userInfo, sizeof( userInfo ) );
	if ( !userInfo[0] )
		return;

	//get unique Ban ID
	id.playerID = atoul( Info_ValueForKey( userInfo, "sv_securityCode" ) );
	
	//Get player name and clean it of color tags
	Q_strncpyz( id.playerName, Q_CleanStr(Info_ValueForKey( userInfo, "name" )), sizeof( id.playerName ) );
	
	//get ban reason
	trap_Argv( 2, id.banReason, sizeof( id.banReason ) );

	if ( !id.banReason[0] )
		Q_strncpyz( id.banReason, "No reason given.", sizeof( id.banReason ) );

	AddID( &id );
	
	ip = g_entities[playerNum].client->pers.ip;

	UpdateIDBans();

	//Scooter's filter list
	if( Q_stricmp( ip, "localhost" )		//localhost
		&& Q_strncmp( ip, "10.", 3 )		//class A
		&& Q_strncmp( ip, "172.16.", 7 )	//class B
		&& Q_strncmp( ip, "192.168.", 8 )	//class C
		&& Q_strncmp( ip, "127.", 4 )		//loopback
		&& Q_strncmp( ip, "169.254.", 8 )	//link-local
		)
	{
		AddIP( ip );
		G_Printf( "User: %s ( %i - %s ) ^7was successfully banned.\n", Info_ValueForKey( userInfo, "name" ), playerNum, ip );
	}

	trap_DropClient( playerNum, "Banned from the server" );
	G_Printf( "User: %s ( %i ) ^7was successfully banned.\n", id.playerName, playerNum );
}
Esempio n. 17
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 )
{
  char      *value;
  char      *userInfoError;
  gclient_t *client;
  char      userinfo[ MAX_INFO_STRING ];
  gentity_t *ent;
  char      reason[ MAX_STRING_CHARS ] = {""};
  int       i;

  ent = &g_entities[ clientNum ];
  client = &level.clients[ clientNum ];

  // ignore if client already connected
  if( client->pers.connected != CON_DISCONNECTED )
    return NULL;

  ent->client = client;
  memset( client, 0, sizeof( *client ) );

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

  value = Info_ValueForKey( userinfo, "cl_guid" );
  Q_strncpyz( client->pers.guid, value, sizeof( client->pers.guid ) );

  value = Info_ValueForKey( userinfo, "ip" );
  // check for local client
  if( !strcmp( value, "localhost" ) )
    client->pers.localClient = qtrue;
  G_AddressParse( value, &client->pers.ip );

  client->pers.admin = G_admin_admin( client->pers.guid );

  // check for admin ban
  if( G_admin_ban_check( ent, reason, sizeof( reason ) ) )
  {
    return va( "%s", reason );
  }

  // 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";

  // add guid to session so we don't have to keep parsing userinfo everywhere
  for( i = 0; i < sizeof( client->pers.guid ) - 1 &&
              isxdigit( client->pers.guid[ i ] ); i++ );

  if( i < sizeof( client->pers.guid ) - 1 && !( ent->r.svFlags & SVF_BOT ) )
    return "Invalid GUID";
  
  for( i = 0; i < level.maxclients; i++ )
  {
    if( level.clients[ i ].pers.connected == CON_DISCONNECTED )
      continue;

    if( !Q_stricmp( client->pers.guid, level.clients[ i ].pers.guid ) && !( ent->r.svFlags & SVF_BOT ) )
    {
      if( !G_ClientIsLagging( level.clients + i ) )
      {
        trap_SendServerCommand( i, "cp \"Your GUID is not secure\"" );
        return "Duplicate GUID";
      }
      trap_DropClient( i, "Ghost" );
    }
  }

  client->pers.connected = CON_CONNECTING;

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

  G_ReadSessionData( client );

  // get and distribute relevent paramters
  G_namelog_connect( client );
  userInfoError = ClientUserinfoChanged( clientNum, qfalse );
  if( userInfoError != NULL && !( ent->r.svFlags & SVF_BOT ) )
    return userInfoError;

  G_LogPrintf( "ClientConnect: %i [%s] (%s) \"%s^7\" \"%c%s%c^7\"\n",
               clientNum, client->pers.ip.str, client->pers.guid,
               client->pers.netname,
               DECOLOR_OFF, client->pers.netname, DECOLOR_ON );

  // 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( client->pers.admin )
    G_admin_authlog( ent );

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

  // if this is after !restart keepteams or !restart switchteams, apply said selection
  if ( client->sess.restartTeam != TEAM_NONE )
  {
    G_ChangeTeam( ent, client->sess.restartTeam );
    client->sess.restartTeam = TEAM_NONE;
  }

  
  return NULL;
}
Esempio n. 18
0
/*
===========
ClientSpawn

Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
============
*/
void ClientSpawn(gentity_t * ent)
{
  int             index;
  vec3_t          spawn_origin, spawn_angles;
  gclient_t      *client;
  int             i;
  clientPersistant_t saved;
  clientSession_t savedSess;
  int             persistant[MAX_PERSISTANT];
  gentity_t      *spawnPoint;
  int             flags;
  int             savedPing;

//  char    *savedAreaBits;
  int             accuracy_hits, accuracy_shots;
  int             eventSequence;
  char            userinfo[MAX_INFO_STRING];

  index = ent - g_entities;
  client = ent->client;

  // find a spawn point
  // do it before setting health back up, so farthest
  // ranging doesn't count this client
  if(client->sess.sessionTeam == TEAM_SPECTATOR)
  {
    spawnPoint = SelectSpectatorSpawnPoint(spawn_origin, spawn_angles);
  }
  else if(g_gametype.integer >= GT_CTF)
  {
    // all base oriented team games use the CTF spawn points
    spawnPoint = SelectCTFSpawnPoint(client->sess.sessionTeam, client->pers.teamState.state, spawn_origin, spawn_angles);
  }
  else
  {
    do
    {
      // the first spawn should be at a good looking spot
      if(!client->pers.initialSpawn && client->pers.localClient)
      {
        client->pers.initialSpawn = qtrue;
        spawnPoint = SelectInitialSpawnPoint(spawn_origin, spawn_angles);
      }
      else
      {
        // don't spawn near existing origin if possible
        spawnPoint = SelectSpawnPoint(client->ps.origin, spawn_origin, spawn_angles);
      }

      // Tim needs to prevent bots from spawning at the initial point
      // on q3dm0...
      if((spawnPoint->flags & FL_NO_BOTS) && (ent->r.svFlags & SVF_BOT))
      {
        continue;		// try again
      }
      // just to be symetric, we have a nohumans option...
      if((spawnPoint->flags & FL_NO_HUMANS) && !(ent->r.svFlags & SVF_BOT))
      {
        continue;		// try again
      }

      break;

    } while(1);
  }
  client->pers.teamState.state = TEAM_ACTIVE;

  // always clear the kamikaze flag
  ent->s.eFlags &= ~EF_KAMIKAZE;

  // toggle the teleport bit so the client knows to not lerp
  // and never clear the voted flag
  flags = ent->client->ps.eFlags & (EF_TELEPORT_BIT | EF_VOTED | EF_TEAMVOTED);
  flags ^= EF_TELEPORT_BIT;

  // clear everything but the persistant data

  saved = client->pers;
  savedSess = client->sess;
  savedPing = client->ps.ping;
//  savedAreaBits = client->areabits;
  accuracy_hits = client->accuracy_hits;
  accuracy_shots = client->accuracy_shots;
  for(i = 0; i < MAX_PERSISTANT; i++)
  {
    persistant[i] = client->ps.persistant[i];
  }
  eventSequence = client->ps.eventSequence;

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

  client->pers = saved;
  client->sess = savedSess;
  client->ps.ping = savedPing;
//  client->areabits = savedAreaBits;
  client->accuracy_hits = accuracy_hits;
  client->accuracy_shots = accuracy_shots;
  client->lastkilled_client = -1;

  for(i = 0; i < MAX_PERSISTANT; i++)
  {
    client->ps.persistant[i] = persistant[i];
  }
  client->ps.eventSequence = eventSequence;
  // increment the spawncount so the client will detect the respawn
  client->ps.persistant[PERS_SPAWN_COUNT]++;
  client->ps.persistant[PERS_TEAM] = client->sess.sessionTeam;

  client->airOutTime = level.time + 12000;

  trap_GetUserinfo(index, userinfo, sizeof(userinfo));
  // set max health
  client->pers.maxHealth = atoi(Info_ValueForKey(userinfo, "handicap"));
  if(client->pers.maxHealth < 1 || client->pers.maxHealth > 100)
  {
    client->pers.maxHealth = 100;
  }
  // clear entity values
  client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;
  client->ps.eFlags = flags;

  ent->s.groundEntityNum = ENTITYNUM_NONE;
  ent->client = &level.clients[index];
  ent->takedamage = qtrue;
  ent->inuse = qtrue;
  ent->classname = "player";
  ent->r.contents = CONTENTS_BODY;
  ent->clipmask = MASK_PLAYERSOLID;
  ent->die = player_die;
  ent->waterlevel = 0;
  ent->watertype = 0;
  ent->flags = 0;

  VectorCopy(playerMins, ent->r.mins);
  VectorCopy(playerMaxs, ent->r.maxs);

  client->ps.clientNum = index;

  /*
  client->ps.stats[STAT_WEAPONS] = (1 << WP_MACHINEGUN);
  if(g_gametype.integer == GT_TEAM)
  {
    client->ps.ammo[WP_MACHINEGUN] = 50;
  }
  else
  {
    client->ps.ammo[WP_MACHINEGUN] = 100;
  }
  */

  /*
  client->ps.stats[STAT_WEAPONS] |= (1 << WP_GAUNTLET);
  client->ps.ammo[WP_GAUNTLET] = -1;
  */

  // health will count down towards max_health
  ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] + 25;
  client->ps.stats[STAT_ARMOR] = client->ps.stats[STAT_MAX_HEALTH];

  G_SetOrigin(ent, spawn_origin);
  VectorCopy(spawn_origin, client->ps.origin);

  // the respawned flag will be cleared after the attack and jump keys come up
  client->ps.pm_flags |= PMF_RESPAWNED;

  trap_GetUsercmd(client - level.clients, &ent->client->pers.cmd);
  SetClientViewAngle(ent, spawn_angles);

  if(ent->client->sess.sessionTeam == TEAM_SPECTATOR)
  {

  }
  else
  {
    G_KillBox(ent);
    trap_LinkEntity(ent);

    // force the base weapon up
    //client->ps.weapon = WP_MACHINEGUN;
    client->ps.weaponstate = WEAPON_READY;

  }

  // don't allow full run speed for a bit
  client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
  client->ps.pm_time = 100;

  client->respawnTime = level.time;
  client->inactivityTime = level.time + g_inactivity.integer * 1000;
  client->latched_buttons = 0;

  // set default animations
  client->ps.torsoAnim = TORSO_STAND;
  client->ps.legsAnim = LEGS_IDLE;

  if(level.intermissiontime)
  {
    MoveClientToIntermission(ent);
  }
  else
  {
    // fire the targets of the spawn point
    G_UseTargets(spawnPoint, ent);
#ifdef G_LUA
    // Lua API callbacks
    if(spawnPoint && spawnPoint->luaTrigger)
    {
      G_LuaHook_EntityTrigger(spawnPoint->luaTrigger, spawnPoint->s.number, ent->s.number);
    }
#endif

    // select the highest weapon number available, after any
    // spawn given items have fired
    client->ps.weapon = 0;
    for(i = WP_NUM_WEAPONS - 1; i > 0; i--)
    {
      if(client->ps.stats[STAT_WEAPONS] & (1 << i))
      {
        client->ps.weapon = i;
        break;
      }
    }
  }

#if defined(ACEBOT)
  if(ent->r.svFlags & SVF_BOT)
  {
    ACESP_SetupBotState(ent);
  }
#endif

#ifdef G_LUA
  // Lua API callbacks
  G_LuaHook_ClientSpawn(ent->s.number);
#endif

  // run a client frame to drop exactly to the floor,
  // initialize animations and other things
  client->ps.commandTime = level.time - 100;
  ent->client->pers.cmd.serverTime = level.time;
  ClientThink(ent - g_entities);

  // positively link the client, even if the command times are weird
  if(ent->client->sess.sessionTeam != TEAM_SPECTATOR)
  {
    BG_PlayerStateToEntityState(&client->ps, &ent->s, qtrue);
    VectorCopy(ent->client->ps.origin, ent->r.currentOrigin);
    trap_LinkEntity(ent);
  }

  // run the presend to set anything else
  ClientEndFrame(ent);

  // clear entity state values
  BG_PlayerStateToEntityState(&client->ps, &ent->s, qtrue);
}
Esempio n. 19
0
/*
===========
ClientSpawn

Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
============
*/
void ClientSpawn( gentity_t *ent, gentity_t *spawn, vec3_t origin, vec3_t angles )
{
  int                 index;
  vec3_t              spawn_origin, spawn_angles;
  gclient_t           *client;
  int                 i;
  clientPersistant_t  saved;
  clientSession_t     savedSess;
  int                 persistant[ MAX_PERSISTANT ];
  gentity_t           *spawnPoint = NULL;
  int                 flags;
  int                 savedPing;
  int                 teamLocal;
  int                 eventSequence;
  char                userinfo[ MAX_INFO_STRING ];
  vec3_t              up = { 0.0f, 0.0f, 1.0f };
  int                 maxAmmo, maxClips;
  weapon_t            weapon;

  index = ent - g_entities;
  client = ent->client;

  teamLocal = client->pers.teamSelection;

  //if client is dead and following teammate, stop following before spawning
  if( client->sess.spectatorClient != -1 )
  {
    client->sess.spectatorClient = -1;
    client->sess.spectatorState = SPECTATOR_FREE;
  }

  // only start client if chosen a class and joined a team
  if( client->pers.classSelection == PCL_NONE && teamLocal == TEAM_NONE )
    client->sess.spectatorState = SPECTATOR_FREE;
  else if( client->pers.classSelection == PCL_NONE )
    client->sess.spectatorState = SPECTATOR_LOCKED;

  // if client is dead and following teammate, stop following before spawning
  if( ent->client->sess.spectatorState == SPECTATOR_FOLLOW )
    G_StopFollowing( ent );

  if( origin != NULL )
    VectorCopy( origin, spawn_origin );

  if( angles != NULL )
    VectorCopy( angles, spawn_angles );

  // find a spawn point
  // do it before setting health back up, so farthest
  // ranging doesn't count this client
  if( client->sess.spectatorState != SPECTATOR_NOT )
  {
    if( teamLocal == TEAM_NONE )
      spawnPoint = G_SelectSpectatorSpawnPoint( spawn_origin, spawn_angles );
    else if( teamLocal == TEAM_ALIENS )
      spawnPoint = G_SelectAlienLockSpawnPoint( spawn_origin, spawn_angles );
    else if( teamLocal == TEAM_HUMANS )
      spawnPoint = G_SelectHumanLockSpawnPoint( spawn_origin, spawn_angles );
  }
  else
  {
    if( spawn == NULL )
    {
      G_Error( "ClientSpawn: spawn is NULL\n" );
      return;
    }

    spawnPoint = spawn;

    if( ent != spawn )
    {
      //start spawn animation on spawnPoint
      G_SetBuildableAnim( spawnPoint, BANIM_SPAWN1, qtrue );

      if( spawnPoint->buildableTeam == TEAM_ALIENS )
        spawnPoint->clientSpawnTime = ALIEN_SPAWN_REPEAT_TIME;
      else if( spawnPoint->buildableTeam == TEAM_HUMANS )
        spawnPoint->clientSpawnTime = HUMAN_SPAWN_REPEAT_TIME;
    }
  }

  // toggle the teleport bit so the client knows to not lerp
  flags = ( ent->client->ps.eFlags & EF_TELEPORT_BIT ) ^ EF_TELEPORT_BIT;
  G_UnlaggedClear( ent );

  // clear everything but the persistant data

  saved = client->pers;
  savedSess = client->sess;
  savedPing = client->ps.ping;

  for( i = 0; i < MAX_PERSISTANT; i++ )
    persistant[ i ] = client->ps.persistant[ i ];

  eventSequence = client->ps.eventSequence;
  memset( client, 0, sizeof( *client ) );

  client->pers = saved;
  client->sess = savedSess;
  client->ps.ping = savedPing;
  client->lastkilled_client = -1;

  for( i = 0; i < MAX_PERSISTANT; i++ )
    client->ps.persistant[ i ] = persistant[ i ];

  client->ps.eventSequence = eventSequence;

  // increment the spawncount so the client will detect the respawn
  client->ps.persistant[ PERS_SPAWN_COUNT ]++;
  client->ps.persistant[ PERS_SPECSTATE ] = client->sess.spectatorState;

  client->airOutTime = level.time + 12000;

  trap_GetUserinfo( index, userinfo, sizeof( userinfo ) );
  client->ps.eFlags = flags;

  //Com_Printf( "ent->client->pers->pclass = %i\n", ent->client->pers.classSelection );

  ent->s.groundEntityNum = ENTITYNUM_NONE;
  ent->client = &level.clients[ index ];
  ent->takedamage = qtrue;
  ent->inuse = qtrue;
  ent->classname = "player";
  ent->r.contents = CONTENTS_BODY;
  ent->clipmask = MASK_PLAYERSOLID;
  ent->die = player_die;
  ent->waterlevel = 0;
  ent->watertype = 0;
  ent->flags = 0;
  ent->pathid = -1; //LEPE: 0 exists

  // calculate each client's acceleration
  ent->evaluateAcceleration = qtrue;

  client->ps.stats[ STAT_MISC ] = 0;

  client->ps.eFlags = flags;
  client->ps.clientNum = index;

  BG_ClassBoundingBox( ent->client->pers.classSelection, ent->r.mins, ent->r.maxs, NULL, NULL, NULL );

  if( client->sess.spectatorState == SPECTATOR_NOT )
    client->ps.stats[ STAT_MAX_HEALTH ] =
      BG_Class( ent->client->pers.classSelection )->health;
  else
    client->ps.stats[ STAT_MAX_HEALTH ] = 100;

  // clear entity values
  if( ent->client->pers.classSelection == PCL_HUMAN )
  {
    BG_AddUpgradeToInventory( UP_MEDKIT, client->ps.stats );
    weapon = client->pers.humanItemSelection;
  }
  else if( client->sess.spectatorState == SPECTATOR_NOT )
    weapon = BG_Class( ent->client->pers.classSelection )->startWeapon;
  else
    weapon = WP_NONE;

  maxAmmo = BG_Weapon( weapon )->maxAmmo;
  maxClips = BG_Weapon( weapon )->maxClips;
  client->ps.stats[ STAT_WEAPON ] = weapon;
  client->ps.ammo = maxAmmo;
  client->ps.clips = maxClips;

  // We just spawned, not changing weapons
  client->ps.persistant[ PERS_NEWWEAPON ] = 0;

  ent->client->ps.stats[ STAT_CLASS ] = ent->client->pers.classSelection;
  ent->client->ps.stats[ STAT_TEAM ] = ent->client->pers.teamSelection;

  ent->client->ps.stats[ STAT_BUILDABLE ] = BA_NONE;
  ent->client->ps.stats[ STAT_STATE ] = 0;
  VectorSet( ent->client->ps.grapplePoint, 0.0f, 0.0f, 1.0f );

  // health will count down towards max_health
  ent->health = client->ps.stats[ STAT_HEALTH ] = client->ps.stats[ STAT_MAX_HEALTH ]; //* 1.25;

  //if evolving scale health
  if( ent == spawn )
  {
    ent->health *= ent->client->pers.evolveHealthFraction;
    client->ps.stats[ STAT_HEALTH ] *= ent->client->pers.evolveHealthFraction;
  }

  //clear the credits array
  for( i = 0; i < MAX_CLIENTS; i++ )
    ent->credits[ i ] = 0;

  client->ps.stats[ STAT_STAMINA ] = STAMINA_MAX;

  G_SetOrigin( ent, spawn_origin );
  VectorCopy( spawn_origin, client->ps.origin );

#define UP_VEL  150.0f
#define F_VEL   50.0f

  //give aliens some spawn velocity
  if( client->sess.spectatorState == SPECTATOR_NOT &&
      client->ps.stats[ STAT_TEAM ] == TEAM_ALIENS )
  {
    if( ent == spawn )
    {
      //evolution particle system
      G_AddPredictableEvent( ent, EV_ALIEN_EVOLVE, DirToByte( up ) );
    }
    else
    {
      spawn_angles[ YAW ] += 180.0f;
      AngleNormalize360( spawn_angles[ YAW ] );

      if( spawnPoint->s.origin2[ 2 ] > 0.0f )
      {
        vec3_t  forward, dir;

        AngleVectors( spawn_angles, forward, NULL, NULL );
        VectorScale( forward, F_VEL, forward );
        VectorAdd( spawnPoint->s.origin2, forward, dir );
        VectorNormalize( dir );

        VectorScale( dir, UP_VEL, client->ps.velocity );
      }

      G_AddPredictableEvent( ent, EV_PLAYER_RESPAWN, 0 );
    }
  }
  else if( client->sess.spectatorState == SPECTATOR_NOT &&
           client->ps.stats[ STAT_TEAM ] == TEAM_HUMANS )
  {
    spawn_angles[ YAW ] += 180.0f;
    AngleNormalize360( spawn_angles[ YAW ] );
  }

  // the respawned flag will be cleared after the attack and jump keys come up
  client->ps.pm_flags |= PMF_RESPAWNED;

  trap_GetUsercmd( client - level.clients, &ent->client->pers.cmd );
  G_SetClientViewAngle( ent, spawn_angles );

  if( client->sess.spectatorState == SPECTATOR_NOT )
  {
    trap_LinkEntity( ent );

    // force the base weapon up
    if( client->pers.teamSelection == TEAM_HUMANS )
      G_ForceWeaponChange( ent, weapon );

    client->ps.weaponstate = WEAPON_READY;
  }

  // don't allow full run speed for a bit
  client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
  client->ps.pm_time = 100;

  client->respawnTime = level.time;
  ent->nextRegenTime = level.time;

  client->inactivityTime = level.time + g_inactivity.integer * 1000;
  client->latched_buttons = 0;

  // set default animations
  client->ps.torsoAnim = TORSO_STAND;
  client->ps.legsAnim = LEGS_IDLE;

  if( level.intermissiontime )
    MoveClientToIntermission( ent );
  else
  {
    // fire the targets of the spawn point
    if( !spawn )
      G_UseTargets( spawnPoint, ent );

    // select the highest weapon number available, after any
    // spawn given items have fired
    client->ps.weapon = 1;

    for( i = WP_NUM_WEAPONS - 1; i > 0 ; i-- )
    {
      if( BG_InventoryContainsWeapon( i, client->ps.stats ) )
      {
        client->ps.weapon = i;
        break;
      }
    }
  }

  // run a client frame to drop exactly to the floor,
  // initialize animations and other things
  client->ps.commandTime = level.time - 100;
  ent->client->pers.cmd.serverTime = level.time;
  ClientThink( ent-g_entities );

  // positively link the client, even if the command times are weird
  if( client->sess.spectatorState == SPECTATOR_NOT )
  {
    BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
    VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
    trap_LinkEntity( ent );
  }

  // must do this here so the number of active clients is calculated
  CalculateRanks( );

  // run the presend to set anything else
  ClientEndFrame( ent );

  // clear entity state values
  BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
}
Esempio n. 20
0
/**
 * @brief kick a user off of the server
 */
static void Svcmd_KickNum_f(void)
{
	gclient_t *cl;
	int       timeout;
	char      *ip;
	char      userinfo[MAX_INFO_STRING];
	char      sTimeout[MAX_TOKEN_CHARS];
	char      name[MAX_TOKEN_CHARS];
	int       clientNum;

	// make sure server is running
	if (!G_Is_SV_Running())
	{
		G_Printf("Server is not running.\n");
		return;
	}

	if (trap_Argc() < 2 || trap_Argc() > 3)
	{
		G_Printf("Usage: kick <client number> [timeout]\n");
		return;
	}

	if (trap_Argc() == 3)
	{
		trap_Argv(2, sTimeout, sizeof(sTimeout));
		timeout = atoi(sTimeout);
	}
	else
	{
		timeout = 300;
	}

	trap_Argv(1, name, sizeof(name));
	clientNum = atoi(name);

	cl = G_GetPlayerByNum(clientNum);
	if (!cl)
	{
		return;
	}
	if (cl->pers.localClient)
	{
		G_Printf("Cannot kick host player\n");
		return;
	}

	trap_GetUserinfo(cl->ps.clientNum, userinfo, sizeof(userinfo));
	ip = Info_ValueForKey(userinfo, "ip");
	// use engine banning system, mods may choose to use their own banlist
	if (USE_ENGINE_BANLIST)
	{

		// kick but dont ban bots, they arent that lame
		if ((g_entities[cl->ps.clientNum].r.svFlags & SVF_BOT))
		{
			timeout = 0;
		}
		trap_DropClient(cl->ps.clientNum, "player kicked", timeout);
	}
	else
	{
		trap_DropClient(cl->ps.clientNum, "player kicked", 0);

		// kick but dont ban bots, they arent that lame
		if (!(g_entities[cl->ps.clientNum].r.svFlags & SVF_BOT))
		{
			AddIPBan(ip);
		}
	}
}
Esempio n. 21
0
/*
===========
ClientUserInfoChanged

Called from ClientConnect when the player first connects and
directly by the server system when the player updates a userinfo variable.

The game can override any of the settings and call trap_SetUserinfo
if desired.
============
*/
char *ClientUserinfoChanged( int clientNum, qboolean forceName )
{
  gentity_t *ent;
  char      *s;
  char      model[ MAX_QPATH ];
  char      buffer[ MAX_QPATH ];
  char      filename[ MAX_QPATH ];
  char      oldname[ MAX_NAME_LENGTH ];
  char      newname[ MAX_NAME_LENGTH ];
  char      s_newname[ MAX_NAME_LENGTH ];
  char      err[ MAX_STRING_CHARS ];
  qboolean  revertName = qfalse;
  qboolean  hasbotinname= qfalse;
  gclient_t *client;
  char      userinfo[ MAX_INFO_STRING ];

  ent = g_entities + clientNum;
  client = ent->client;

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

  // check for malformed or illegal info strings
  if( !Info_Validate(userinfo) )
  {
    trap_SendServerCommand( ent - g_entities,
        "disconnect \"illegal or malformed userinfo\n\"" );
    trap_DropClient( ent - g_entities, 
        "dropped: illegal or malformed userinfo");
    return "Illegal or malformed userinfo";
  }
  // If their userinfo overflowed, tremded is in the process of disconnecting them.
  // If we send our own disconnect, it won't work, so just return to prevent crashes later
  //  in this function. This check must come after the Info_Validate call.
  else if( !userinfo[ 0 ] )
    return "Empty (overflowed) userinfo";

  // stickyspec toggle
  s = Info_ValueForKey( userinfo, "cg_stickySpec" );  
  client->pers.stickySpec = atoi( s ) != 0;

  // set name
  Q_strncpyz( oldname, client->pers.netname, sizeof( oldname ) );
  s = Info_ValueForKey( userinfo, "name" );
  G_ClientCleanName( s, newname, sizeof( newname ) );

  // check if the name contains [BOT]
  G_DecolorString(newname, s_newname, sizeof(newname));
  hasbotinname = Com_StringContains(s_newname, "[BOT]", 0) ? qtrue : qfalse;
  
  if( strcmp( oldname, newname ) )
  {
    if( !forceName && client->pers.namelog->nameChangeTime &&
      level.time - client->pers.namelog->nameChangeTime <=
      g_minNameChangePeriod.value * 1000 )
    {
      trap_SendServerCommand( ent - g_entities, va(
        "print \"Name change spam protection (g_minNameChangePeriod = %d)\n\"",
         g_minNameChangePeriod.integer ) );
      revertName = qtrue;
    }
    else if( !forceName && g_maxNameChanges.integer > 0 &&
      client->pers.namelog->nameChanges >= g_maxNameChanges.integer  )
    {
      trap_SendServerCommand( ent - g_entities, va(
        "print \"Maximum name changes reached (g_maxNameChanges = %d)\n\"",
         g_maxNameChanges.integer ) );
      revertName = qtrue;
    }
    else if( !forceName && client->pers.namelog->muted )
    {
      trap_SendServerCommand( ent - g_entities,
        "print \"You cannot change your name while you are muted\n\"" );
      revertName = qtrue;
    }
    else if( !G_admin_name_check( ent, newname, err, sizeof( err ) ) )
    {
      trap_SendServerCommand( ent - g_entities, va( "print \"%s\n\"", err ) );
      revertName = qtrue;
    }
	//LEPE: Players are not allowed to have [BOT] or [bot] in names
	if(!(ent->r.svFlags & SVF_BOT) && g_bot_tagname.integer == 1) {
		if (hasbotinname) {
		  trap_SendServerCommand( ent - g_entities,
			"print \"You cannot use [BOT] in your name\n\"" );
		  revertName = qtrue;
		  hasbotinname = qfalse;
		}
	}

    if( revertName )
    {
      Q_strncpyz( client->pers.netname, *oldname ? oldname : "UnnamedPlayer",
        sizeof( client->pers.netname ) );
      Info_SetValueForKey( userinfo, "name", oldname );
      trap_SetUserinfo( clientNum, userinfo );
    }
    else
    {
      G_CensorString( client->pers.netname, newname,
        sizeof( client->pers.netname ), ent );
      if( !forceName && client->pers.connected == CON_CONNECTED )
      {
        client->pers.namelog->nameChangeTime = level.time;
        client->pers.namelog->nameChanges++;
      }
      if( *oldname )
      {
        G_LogPrintf( "ClientRename: %i [%s] (%s) \"%s^7\" -> \"%s^7\" \"%c%s%c^7\"\n",
                   clientNum, client->pers.ip.str, client->pers.guid,
                   oldname, client->pers.netname,
                   DECOLOR_OFF, client->pers.netname, DECOLOR_ON );
      }
    }
    G_namelog_update_name( client );
  }

  if( client->pers.classSelection == PCL_NONE )
  {
    //This looks hacky and frankly it is. The clientInfo string needs to hold different
    //model details to that of the spawning class or the info change will not be
    //registered and an axis appears instead of the player model. There is zero chance
    //the player can spawn with the battlesuit, hence this choice.
    Com_sprintf( buffer, MAX_QPATH, "%s/%s",  BG_ClassConfig( PCL_HUMAN_BSUIT )->modelName,
                                              BG_ClassConfig( PCL_HUMAN_BSUIT )->skinName );
  }
  else
  {
    Com_sprintf( buffer, MAX_QPATH, "%s/%s%s",  BG_ClassConfig( client->pers.classSelection )->modelName,
                                              BG_ClassConfig( client->pers.classSelection )->skinName,
											  g_bot_skins.integer && hasbotinname == qtrue ? "_bot" : "");

    //model segmentation
    Com_sprintf( filename, sizeof( filename ), "models/players/%s/animation.cfg",
                 BG_ClassConfig( client->pers.classSelection )->modelName );

    if( G_NonSegModel( filename ) )
      client->ps.persistant[ PERS_STATE ] |= PS_NONSEGMODEL;
    else
      client->ps.persistant[ PERS_STATE ] &= ~PS_NONSEGMODEL;
  }
  Q_strncpyz( model, buffer, sizeof( model ) );

  // wallwalk follow
  s = Info_ValueForKey( userinfo, "cg_wwFollow" );

  if( atoi( s ) )
    client->ps.persistant[ PERS_STATE ] |= PS_WALLCLIMBINGFOLLOW;
  else
    client->ps.persistant[ PERS_STATE ] &= ~PS_WALLCLIMBINGFOLLOW;

  // wallwalk toggle
  s = Info_ValueForKey( userinfo, "cg_wwToggle" );

  if( atoi( s ) )
    client->ps.persistant[ PERS_STATE ] |= PS_WALLCLIMBINGTOGGLE;
  else
    client->ps.persistant[ PERS_STATE ] &= ~PS_WALLCLIMBINGTOGGLE;

  // always sprint
  s = Info_ValueForKey( userinfo, "cg_sprintToggle" );

  if( atoi( s ) )
    client->ps.persistant[ PERS_STATE ] |= PS_SPRINTTOGGLE;
  else
    client->ps.persistant[ PERS_STATE ] &= ~PS_SPRINTTOGGLE;

  // fly speed
  s = Info_ValueForKey( userinfo, "cg_flySpeed" );

  if( *s )
    client->pers.flySpeed = atoi( s );
  else
    client->pers.flySpeed = BG_Class( PCL_NONE )->speed;

  // disable blueprint errors
  s = Info_ValueForKey( userinfo, "cg_disableBlueprintErrors" );

  if( atoi( s ) )
    client->pers.disableBlueprintErrors = qtrue;
  else
    client->pers.disableBlueprintErrors = qfalse;

  // teamInfo
  s = Info_ValueForKey( userinfo, "teamoverlay" );

  if( atoi( s ) != 0 )
    client->pers.teamInfo = qtrue;
  else
    client->pers.teamInfo = qfalse;

  s = Info_ValueForKey( userinfo, "cg_unlagged" );
  if( !s[0] || atoi( s ) != 0 )
    client->pers.useUnlagged = qtrue;
  else
    client->pers.useUnlagged = qfalse;

  Q_strncpyz( client->pers.voice, Info_ValueForKey( userinfo, "voice" ),
    sizeof( client->pers.voice ) );

  // send over a subset of the userinfo keys so other clients can
  // print scoreboards, display models, and play custom sounds

  Com_sprintf( userinfo, sizeof( userinfo ),
    "n\\%s\\t\\%i\\model\\%s\\ig\\%16s\\v\\%s",
    client->pers.netname, client->pers.teamSelection, model,
    Com_ClientListString( &client->sess.ignoreList ),
    client->pers.voice );

  trap_SetConfigstring( CS_PLAYERS + clientNum, userinfo );

  /*G_LogPrintf( "ClientUserinfoChanged: %i %s\n", clientNum, userinfo );*/

  return NULL;
}
Esempio n. 22
0
int Pickup_PersistantPowerup(gentity_t *ent, gentity_t *other)
{
	int		clientNum;
	char	userinfo[MAX_INFO_STRING];
	float	handicap;
	int		max;

	other->client->ps.stats[STAT_PERSISTANT_POWERUP] = ent->item - bg_itemlist;
	other->client->persistantPowerup = ent;

	switch (ent->item->giTag)
	{
	case PW_GUARD:
		clientNum = other->client->ps.clientNum;
		trap_GetUserinfo(clientNum, userinfo, sizeof(userinfo));
		handicap = atof(Info_ValueForKey(userinfo, "handicap"));
		if (handicap <= 0.0f || handicap > 100.0f)
		{
			handicap = 100.0f;
		}
		max = (int)(2 *  handicap);

		other->health = max;
		other->client->ps.stats[STAT_HEALTH] = max;
		other->client->ps.stats[STAT_MAX_HEALTH] = max;
		other->client->ps.stats[STAT_ARMOR] = max;
		other->client->pers.maxHealth = max;

		break;

	case PW_SCOUT:
		clientNum = other->client->ps.clientNum;
		trap_GetUserinfo(clientNum, userinfo, sizeof(userinfo));
		handicap = atof(Info_ValueForKey(userinfo, "handicap"));
		if (handicap <= 0.0f || handicap > 100.0f)
		{
			handicap = 100.0f;
		}
		other->client->pers.maxHealth = handicap;
		other->client->ps.stats[STAT_ARMOR] = 0;
		break;

	case PW_DOUBLER:
		clientNum = other->client->ps.clientNum;
		trap_GetUserinfo(clientNum, userinfo, sizeof(userinfo));
		handicap = atof(Info_ValueForKey(userinfo, "handicap"));
		if (handicap <= 0.0f || handicap > 100.0f)
		{
			handicap = 100.0f;
		}
		other->client->pers.maxHealth = handicap;
		break;
	case PW_AMMOREGEN:
		clientNum = other->client->ps.clientNum;
		trap_GetUserinfo(clientNum, userinfo, sizeof(userinfo));
		handicap = atof(Info_ValueForKey(userinfo, "handicap"));
		if (handicap <= 0.0f || handicap > 100.0f)
		{
			handicap = 100.0f;
		}
		other->client->pers.maxHealth = handicap;
		memset(other->client->ammoTimes, 0, sizeof(other->client->ammoTimes));
		break;
	default:
		clientNum = other->client->ps.clientNum;
		trap_GetUserinfo(clientNum, userinfo, sizeof(userinfo));
		handicap = atof(Info_ValueForKey(userinfo, "handicap"));
		if (handicap <= 0.0f || handicap > 100.0f)
		{
			handicap = 100.0f;
		}
		other->client->pers.maxHealth = handicap;
		break;
	}

	return -1;
}
Esempio n. 23
0
/*
=================
G_UpdateCharacter
=================
*/
void G_UpdateCharacter(gclient_t *client)
{
	char           infostring[MAX_INFO_STRING];
	char           *s;
	int            characterIndex;
	bg_character_t *character;

	trap_GetUserinfo(client->ps.clientNum, infostring, sizeof(infostring));
	s = Info_ValueForKey(infostring, "ch");
	if (*s)
	{
		characterIndex = atoi(s);
		if (characterIndex < 0 || characterIndex >= MAX_CHARACTERS)
		{
			goto set_default_character;
		}

		if (client->pers.characterIndex != characterIndex)
		{
			client->pers.characterIndex = characterIndex;
			trap_GetConfigstring(CS_CHARACTERS + characterIndex, infostring, MAX_INFO_STRING);
			if (!(client->pers.character = BG_FindCharacter(infostring)))
			{
				// not found - create it (this should never happen as we should have everything precached)
				client->pers.character = BG_FindFreeCharacter(infostring);

				if (!client->pers.character)
				{
					goto set_default_character;
				}

				Q_strncpyz(client->pers.character->characterFile, infostring, sizeof(client->pers.character->characterFile));

				if (!G_RegisterCharacter(infostring, client->pers.character))
				{
					G_Printf(S_COLOR_YELLOW "WARNING: G_UpdateCharacter: failed to load character file '%s' for %s\n", infostring,
					         client->pers.netname);

					goto set_default_character;
				}
			}

			// reset anims so client's dont freak out

			// xkan: this can only be done if the model really changed - otherwise, the
			// animation may get screwed up if we are in the middle of some animation
			// and we come into this function;
			// plus, also reset the timer so we can properly start the next animation

			client->ps.legsAnim   = 0;
			client->ps.torsoAnim  = 0;
			client->ps.legsTimer  = 0;
			client->ps.torsoTimer = 0;
		}
		return;
	}

set_default_character:
	// set default character
	character = BG_GetCharacter(client->sess.sessionTeam, client->sess.playerType);
	if (client->pers.character != character)
	{
		client->pers.characterIndex = -1;
		client->pers.character      = character;

		client->ps.legsAnim   = 0;
		client->ps.torsoAnim  = 0;
		client->ps.legsTimer  = 0;
		client->ps.torsoTimer = 0;
	}
}
Esempio n. 24
0
/*
===========
ClientSpawn

Called every time a client is placed fresh in the world:
after the first ClientBegin, and after each respawn
Initializes all non-persistant parts of playerState
============
*/
void ClientSpawn(gentity_t *ent) {
	int		index;
	vec3_t	spawn_origin, spawn_angles;
	gclient_t	*client;
	int		i;
	clientPersistant_t	saved;
	clientSession_t		savedSess;
	int		persistant[MAX_PERSISTANT];
	gentity_t	*spawnPoint;
	int		flags;
	int		savedPing;
//	char	*savedAreaBits;
	int		accuracy_hits, accuracy_shots;
	int		eventSequence;
	char	userinfo[MAX_INFO_STRING];

	index = ent - g_entities;
	client = ent->client;

	// find a spawn point
	// do it before setting health back up, so farthest
	// ranging doesn't count this client
	if ( client->sess.sessionTeam == TEAM_SPECTATOR ) {
		spawnPoint = SelectSpectatorSpawnPoint ( 
						spawn_origin, spawn_angles);
	} else {
		do {
			// the first spawn should be at a good looking spot
			if ( !client->pers.initialSpawn && client->pers.localClient ) {
				client->pers.initialSpawn = qtrue;
				spawnPoint = SelectInitialSpawnPoint( spawn_origin, spawn_angles );
			} else {
				// don't spawn near existing origin if possible
				spawnPoint = SelectSpawnPoint ( 
					client->ps.origin, 
					spawn_origin, spawn_angles);
			}

			// Tim needs to prevent bots from spawning at the initial point
			// on q3dm0...
			if ( ( spawnPoint->flags & FL_NO_BOTS ) && ( ent->r.svFlags & SVF_BOT ) ) {
				continue;	// try again
			}
			// just to be symetric, we have a nohumans option...
			if ( ( spawnPoint->flags & FL_NO_HUMANS ) && !( ent->r.svFlags & SVF_BOT ) ) {
				continue;	// try again
			}

			break;

		} while ( 1 );
	}
	client->pers.teamState.state = TEAM_ACTIVE;

	// always clear the kamikaze flag
//	ent->s.eFlags &= ~EF_KAMIKAZE;

	// toggle the teleport bit so the client knows to not lerp
	// and never clear the voted flag
	flags = ent->s.eFlags & (EF_TELEPORT_BIT | EF_VOTED | EF_TEAMVOTED);
	flags ^= EF_TELEPORT_BIT;

	// clear everything but the persistant data

	saved = client->pers;
	savedSess = client->sess;
	savedPing = client->ps.ping;
//	savedAreaBits = client->areabits;
	accuracy_hits = client->accuracy_hits;
	accuracy_shots = client->accuracy_shots;

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

	client->ps.stats[STAT_ATTACKERCLIENT] = -1;
	client->ps.stats[STAT_INFOCLIENT] = -1;

	client->pers = saved;
	client->sess = savedSess;
	client->ps.ping = savedPing;
//	client->areabits = savedAreaBits;
	client->accuracy_hits = accuracy_hits;
	client->accuracy_shots = accuracy_shots;
	client->lastkilled_client = -1;

	client->airOutTime = level.time + 12000;

	trap_GetUserinfo( index, userinfo, sizeof(userinfo) );
	// set max health
	client->pers.maxHealth = atoi( Info_ValueForKey( userinfo, "handicap" ) );
	if ( client->pers.maxHealth < 1 || client->pers.maxHealth > 100 ) {
		client->pers.maxHealth = 100;
	}
	// clear entity values
	client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;
	ent->s.eFlags = flags;

	ent->s.groundEntityNum = ENTITYNUM_NONE;
	ent->client = &level.clients[index];
	ent->takedamage = qtrue;
	ent->inuse = qtrue;
	ent->classname = "player";
	ent->r.contents = CONTENTS_BODY;
	ent->clipmask = MASK_PLAYERSOLID;
	ent->die = player_die;
	ent->waterlevel = 0;
	ent->watertype = 0;
	ent->flags = 0;
	
	VectorCopy (playerMins, ent->r.mins);
	VectorCopy (playerMaxs, ent->r.maxs);

	client->ps.clientNum = index;



	// health will count down towards max_health
	ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] + 25;

	G_SetOrigin( ent, spawn_origin );
	VectorCopy( spawn_origin, client->ps.origin );

	// the respawned flag will be cleared after the attack and jump keys come up
	client->ps.pm_flags |= PMF_RESPAWNED;

	trap_GetUsercmd( client - level.clients, &ent->client->pers.cmd );
	SetClientViewAngle( ent, spawn_angles );

	if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {

	} else {
		G_KillBox( ent );
		trap_LinkEntity (ent);

	

	}

	// don't allow full run speed for a bit
	client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
	client->ps.pm_time = 100;

	client->respawnTime = level.time;
	client->inactivityTime = level.time + g_inactivity.integer * 1000;
	client->latched_buttons = 0;

	if ( level.intermissiontime ) {
		MoveClientToIntermission( ent );
	} else {
		// fire the targets of the spawn point
		G_UseTargets( spawnPoint, ent );

	}

	// run a client frame to drop exactly to the floor,
	// initialize animations and other things
	client->ps.commandTime = level.time - 100;
	ent->client->pers.cmd.serverTime = level.time;
	ClientThink( ent-g_entities );

	// positively link the client, even if the command times are weird
	if ( ent->client->sess.sessionTeam != TEAM_SPECTATOR ) {
		BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );
		VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
		trap_LinkEntity( ent );
	}

	// run the presend to set anything else
	ClientEndFrame( ent );

	// clear entity state values
	BG_PlayerStateToEntityState( &client->ps, &ent->s, qtrue );

	ent->s.modelindex = G_ModelIndex("models/human/coxswain.tik");
}
Esempio n. 25
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) {
	char      *value;
	gclient_t *client;
	char      userinfo[MAX_INFO_STRING];
	gentity_t *ent;
	char      userinfo2[MAX_INFO_STRING]; // Nico, used in connections limit check
	int       i = 0;
	int       clientNum2; // Nico, used in connections limit check
	int       conn_per_ip = 1; // Nico, connections per IP counter
	char      ip[20], ip2[20]; // Nico, used in connections limit check
	char      parsedIp[20], parsedIp2[20]; // Nico, used in connections limit check
	char      cs_name[MAX_NETNAME];

	ent = &g_entities[clientNum];

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

	// IP filtering
	// 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_FilterIPBanPacket(value)) {
		return "You are banned from this server.";
	}

	// Nico, check maximum connections per IP (from ETpub)
	// (prevents fakeplayers DOS http://aluigi.altervista.org/fakep.htm )
	// note: value is the client ip
	if (!getParsedIp(value, parsedIp)) {
		return "Invalid IP address";
	}
	Q_strncpyz(ip, parsedIp, sizeof (ip));
	for (i = 0; i < level.numConnectedClients; ++i) {
		clientNum2 = level.sortedClients[i];
		if (clientNum == clientNum2) {
			continue;
		}
		trap_GetUserinfo(clientNum2, userinfo2, sizeof (userinfo2));
		value = Info_ValueForKey(userinfo2, "ip");
		if (!getParsedIp(value, parsedIp2)) {
			continue;
		}
		Q_strncpyz(ip2, parsedIp2, sizeof (ip2));
		if (strcmp(ip, ip2) == 0) {
			conn_per_ip++;
		}
	}
	if (conn_per_ip > g_maxConnsPerIP.integer) {
		G_LogPrintf("%s: possible DoS attack, rejecting client from %s (%d connections already)\n", GAME_VERSION, ip, g_maxConnsPerIP.integer);
		return "Too many connections from your IP.";
	}
	// Nico, end of check maximum connections per IP

	// Nico, check name
	value = Info_ValueForKey(userinfo, "name");
	Q_strncpyz(cs_name, value, sizeof (cs_name));
	if (CheckName(cs_name) != qtrue) {
		return "Bad name: extended ASCII characters or too long name. Please change your name.";
	}

	// 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 (strcmp(Info_ValueForKey(userinfo, "ip"), "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 &&
			(!sv_privatepassword.string[0] || strcmp(sv_privatepassword.string, value) != 0)) {
			return "Invalid password";
		}
	}

	// Gordon: porting q3f flag bug fix
	// 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: %d\n", (int)(ent - g_entities));
		// so lets just fix up anything that should happen on a disconnect
		ClientDisconnect(ent - g_entities);
	}

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

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

	client->pers.connected   = CON_CONNECTING;

	// read or initialize the session data
	if (firstTime) {
		G_InitSessionData(client);
		client->pers.enterTime            = level.time;
		client->ps.persistant[PERS_SCORE] = 0;
	} else {
		G_ReadSessionData(client);
	}
	client->pers.enterTime = level.time;

	if (firstTime) {
		// force into spectator
		client->sess.sessionTeam     = TEAM_SPECTATOR;
		client->sess.spectatorState  = SPECTATOR_FREE;
		client->sess.spectatorClient = 0;

		// unlink the entity - just in case they were already connected
		trap_UnlinkEntity(ent);
	}

	// Nico, GeoIP
	if (gidb != NULL) {
		value = Info_ValueForKey (userinfo, "ip");
		if (!strcmp(value, "localhost")) {
			client->sess.countryCode = 0;
		} else {
			char realIP[IP_MAX_LENGTH] = {0};// Nico, used to store IP without :port
			unsigned long ip;

			// Nico, remove :port from IP
			sscanf(value, "%15[0-9.]:%*d", realIP);

			ip = GeoIP_addr_to_num(realIP);

			if (((ip & 0xFF000000) == 0x0A000000) ||
				((ip & 0xFFF00000) == 0xAC100000) ||
				((ip & 0xFFFF0000) == 0xC0A80000) ||
				( ip == 0x7F000001) ) {
				client->sess.countryCode = 246;
			} else {
				unsigned int ret = GeoIP_seek_record(gidb, ip);
				if (ret > 0) {
					client->sess.countryCode = ret;
				} else {
					client->sess.countryCode = 246;
					G_LogPrintf("GeoIP: This IP:%s cannot be located\n", realIP);
				}
			}
		}
	} else {
		client->sess.countryCode = 255;
	}
	// Nico, end of GeoIP

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

	// don't do the "xxx connected" messages if they were caried over from previous level
	//		TAT 12/10/2002 - Don't display connected messages in single player

	if (firstTime) {
		trap_SendServerCommand(-1, va("cpm \"%s" S_COLOR_WHITE " connected\n\"", client->pers.netname));
	}

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

	return NULL;
}
Esempio n. 26
0
/*
===========
ClientUserInfoChanged

Called from ClientConnect when the player first connects and
directly by the server system when the player updates a userinfo variable.

The game can override any of the settings and call trap_SetUserinfo
if desired.
============
*/
void ClientUserinfoChanged( int clientNum ) {
	gentity_t *ent;
	int		teamTask, teamLeader;
	char	*s;
	char	model[MAX_QPATH];
	char	headModel[MAX_QPATH];
	char	oldname[MAX_STRING_CHARS];
	gclient_t	*client;
	char	c1[MAX_INFO_STRING];
	char	c2[MAX_INFO_STRING];
	char	userinfo[MAX_INFO_STRING];

	ent = g_entities + clientNum;
	client = ent->client;

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

	// check for malformed or illegal info strings
	if ( !Info_Validate(userinfo) ) {
		strcpy (userinfo, "\\name\\badinfo");
		// don't keep those clients and userinfo
		trap_DropClient(clientNum, "Invalid userinfo");
	}

	// check for local client
	s = Info_ValueForKey( userinfo, "ip" );
	if ( !strcmp( s, "localhost" ) ) {
		client->pers.localClient = qtrue;
	}

	// check the item prediction
	s = Info_ValueForKey( userinfo, "cg_predictItems" );
	if ( !atoi( s ) ) {
		client->pers.predictItemPickup = qfalse;
	} else {
		client->pers.predictItemPickup = qtrue;
	}

	// set name
	Q_strncpyz ( oldname, client->pers.netname, sizeof( oldname ) );
	s = Info_ValueForKey (userinfo, "name");
	ClientCleanName( s, client->pers.netname, sizeof(client->pers.netname) );

	if ( client->sess.sessionTeam == TEAM_SPECTATOR ) {
		if ( client->sess.spectatorState == SPECTATOR_SCOREBOARD ) {
			Q_strncpyz( client->pers.netname, "scoreboard", sizeof(client->pers.netname) );
		}
	}

	if ( client->pers.connected == CON_CONNECTED ) {
		if ( strcmp( oldname, client->pers.netname ) ) {
			trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " renamed to %s\n\"", oldname, 
				client->pers.netname) );
		}
	}

	// set max health
#ifdef MISSIONPACK
	if (client->ps.powerups[PW_GUARD]) {
		client->pers.maxHealth = 200;
	} else {
		client->pers.maxHealth = ClientHandicap( client );
	}
#else
	client->pers.maxHealth = ClientHandicap( client );
#endif
	client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;

	// set model
	if( g_gametype.integer >= GT_TEAM ) {
		Q_strncpyz( model, Info_ValueForKey (userinfo, "team_model"), sizeof( model ) );
		Q_strncpyz( headModel, Info_ValueForKey (userinfo, "team_headmodel"), sizeof( headModel ) );
	} else {
		Q_strncpyz( model, Info_ValueForKey (userinfo, "model"), sizeof( model ) );
		Q_strncpyz( headModel, Info_ValueForKey (userinfo, "headmodel"), sizeof( headModel ) );
	}

/*	NOTE: all client side now

	// team
	switch( team ) {
	case TEAM_RED:
		ForceClientSkin(client, model, "red");
//		ForceClientSkin(client, headModel, "red");
		break;
	case TEAM_BLUE:
		ForceClientSkin(client, model, "blue");
//		ForceClientSkin(client, headModel, "blue");
		break;
	}
	// don't ever use a default skin in teamplay, it would just waste memory
	// however bots will always join a team but they spawn in as spectator
	if ( g_gametype.integer >= GT_TEAM && team == TEAM_SPECTATOR) {
		ForceClientSkin(client, model, "red");
//		ForceClientSkin(client, headModel, "red");
	}
*/

#ifdef MISSIONPACK
	if (g_gametype.integer >= GT_TEAM) {
		client->pers.teamInfo = qtrue;
	} else {
		s = Info_ValueForKey( userinfo, "teamoverlay" );
		if ( ! *s || atoi( s ) != 0 ) {
			client->pers.teamInfo = qtrue;
		} else {
			client->pers.teamInfo = qfalse;
		}
	}
#else
	// teamInfo
	s = Info_ValueForKey( userinfo, "teamoverlay" );
	if ( ! *s || atoi( s ) != 0 ) {
		client->pers.teamInfo = qtrue;
	} else {
		client->pers.teamInfo = qfalse;
	}
#endif
	/*
	s = Info_ValueForKey( userinfo, "cg_pmove_fixed" );
	if ( !*s || atoi( s ) == 0 ) {
		client->pers.pmoveFixed = qfalse;
	}
	else {
		client->pers.pmoveFixed = qtrue;
	}
	*/

	// team task (0 = none, 1 = offence, 2 = defence)
	teamTask = atoi(Info_ValueForKey(userinfo, "teamtask"));
	// team Leader (1 = leader, 0 is normal player)
	teamLeader = client->sess.teamLeader;

	// colors
	strcpy(c1, Info_ValueForKey( userinfo, "color1" ));
	strcpy(c2, Info_ValueForKey( userinfo, "color2" ));

	// send over a subset of the userinfo keys so other clients can
	// print scoreboards, display models, and play custom sounds
	if (ent->r.svFlags & SVF_BOT)
	{
		s = va("n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\skill\\%s\\tt\\%d\\tl\\%d",
			client->pers.netname, client->sess.sessionTeam, model, headModel, c1, c2, 
			client->pers.maxHealth, client->sess.wins, client->sess.losses,
			Info_ValueForKey( userinfo, "skill" ), teamTask, teamLeader );
	}
	else
	{
		s = va("n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\tt\\%d\\tl\\%d",
			client->pers.netname, client->sess.sessionTeam, model, headModel, c1, c2, 
			client->pers.maxHealth, client->sess.wins, client->sess.losses, teamTask, teamLeader);
	}

	trap_SetConfigstring( CS_PLAYERS+clientNum, s );

	// this is not the userinfo, more like the configstring actually
	G_LogPrintf( "ClientUserinfoChanged: %i %s\n", clientNum, s );
}
Esempio n. 27
0
/*
===========
ClientUserInfoChanged

Called from ClientConnect when the player first connects and
directly by the server system when the player updates a userinfo variable.

The game can override any of the settings and call trap_SetUserinfo
if desired.
============
*/
void ClientUserinfoChanged(int clientNum) {
	gentity_t *ent;
	char      *s;
	char      oldname[MAX_STRING_CHARS];
	char      userinfo[MAX_INFO_STRING];
	gclient_t *client;
	char      *ip   = NULL; // Nico, used to store client ip
	char      *rate   = NULL; // Nico, used to store client rate
	char      *snaps   = NULL; // Nico, used to store client snaps
	char      *name = NULL; // Nico, used to store client name
	char      oldAuthToken[MAX_QPATH]; // Nico, used to see if auth token was changed

	ent    = g_entities + clientNum;
	client = ent->client;

	client->ps.clientNum = clientNum;

	// Nico, flood protection
	if (ClientIsFlooding(ent)) {
		G_LogPrintf("Dropping client %d: flooded userinfo\n", clientNum);
		trap_DropClient(clientNum, "^1You were kicked because of flooded userinfo", 0);
		return;
	}

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

	// Nico, perform security checks on userinfo string
	if (!checkUserinfoString(clientNum, userinfo)) {
		return;
	}

	if (g_developer.integer || *g_log.string || g_dedicated.integer) {
		G_Printf("Userinfo: %s\n", userinfo);
	}

	// check for local client
	ip = Info_ValueForKey(userinfo, "ip");
	Q_strncpyz(client->pers.ip, ip, IP_MAX_LENGTH);
	if (ip && !strcmp(ip, "localhost")) {
		client->pers.localClient = qtrue;
		level.fLocalHost         = qtrue;
		client->sess.referee     = RL_REFEREE;
	}

	// Nico, store rate and snaps
	rate = Info_ValueForKey(userinfo, "rate");
	client->pers.rate = atoi(rate);
	snaps = Info_ValueForKey(userinfo, "snaps");
	client->pers.snaps = atoi(snaps);

	// Nico, backup old auth token
	Q_strncpyz(oldAuthToken, client->pers.authToken, sizeof (oldAuthToken));

	s = Info_ValueForKey(userinfo, "cg_uinfo");
	sscanf(s, "%i %i %i %i %s %i %i %i %i %i %i %i %i %i",
	       &client->pers.clientFlags,
	       &client->pers.clientTimeNudge,
	       &client->pers.clientMaxPackets,

	       // Nico, max FPS
	       &client->pers.maxFPS,

	       // Nico, auth Token
	       (char *)&client->pers.authToken,

	       // Nico, load view angles on load
	       &client->pers.loadViewAngles,

		   // Nico, load weapon on load
	       &client->pers.loadWeapon,

	       // Nico, load position when player dies
	       &client->pers.autoLoad,

	       // Nico, cgaz
	       &client->pers.cgaz,

	       // Nico, hideme
	       &client->pers.hideme,

	       // Nico, client auto demo record setting
	       &client->pers.autoDemo,

	       // Nico, automatically load checkpoints
	       &client->pers.autoLoadCheckpoints,

	       // Nico, persistant specLock
	       (int *)&client->sess.specLocked,

	       // Nico, keep all demos
	       &client->pers.keepAllDemos

	       );

	// Nico, check if auth token was changed
	if (oldAuthToken[0] != '\0' &&
		Q_stricmp(oldAuthToken, client->pers.authToken) &&
		client->sess.logged) {
		// Nico, auth token was changed => logout player if he was logged in
		CP("cp \"You are no longer logged in!\n\"");
		G_LogPrintf("ClientUserinfoChanged: authToken changed for client %d, forcing logout\n", clientNum);
		ent->client->sess.logged = qfalse;
	}

	client->pers.autoActivate      = (client->pers.clientFlags & CGF_AUTOACTIVATE) ? PICKUP_TOUCH : PICKUP_ACTIVATE;
	client->pers.predictItemPickup = ((client->pers.clientFlags & CGF_PREDICTITEMS) != 0);

	if (client->pers.clientFlags & CGF_AUTORELOAD) {
		client->pers.bAutoReloadAux = qtrue;
		client->pmext.bAutoReload   = qtrue;
	} else {
		client->pers.bAutoReloadAux = qfalse;
		client->pmext.bAutoReload   = qfalse;
	}

	// Nico, pmove_fixed
	client->pers.pmoveFixed = client->pers.clientFlags & CGF_PMOVEFIXED;

	// Nico, autologin
	client->pers.autoLogin = client->pers.clientFlags & CGF_AUTOLOGIN;

	//
	// Nico, name handling
	//

	// Backup old name
	Q_strncpyz(oldname, client->pers.netname, sizeof (oldname));

	// Get new name from userinfo string
	name = Info_ValueForKey(userinfo, "name");

	// Clean the new name
	ClientCleanName(name, client->pers.netname, sizeof (client->pers.netname));

	// Check it's valid
	if (CheckName(client->pers.netname) != qtrue) {
		// Invalid name, restore old name
		Q_strncpyz(client->pers.netname, oldname, sizeof (client->pers.netname));
		Info_SetValueForKey(userinfo, "name", oldname);
		trap_SetUserinfo(clientNum, userinfo);
		CPx(clientNum, "print \"^1Invalid name, name change refused\n\"");
		G_LogPrintf("Client %d name change refused\n", clientNum);
	} else {
		// Name is valid
		// Now, check if name was changed or not
		if (client->pers.connected == CON_CONNECTED && strcmp(oldname, client->pers.netname) != 0) {
			// Name was changed
			// Now, check name changes limit
			if (g_maxNameChanges.integer > -1 && client->pers.nameChanges >= g_maxNameChanges.integer) {
				// Nico, limit reached, forbid name change
				Q_strncpyz(client->pers.netname, oldname, sizeof (client->pers.netname));
				Info_SetValueForKey(userinfo, "name", oldname);
				trap_SetUserinfo(clientNum, userinfo);
				CPx(clientNum, "print \"^1You had too many namechanges\n\"");
				G_LogPrintf("Client %d name change refused\n", clientNum);
				return;
			}
			client->pers.nameChanges++;
			trap_SendServerCommand(-1, va("print \"%s" S_COLOR_WHITE " renamed to %s\n\"", oldname, client->pers.netname));
		}
	}

	//
	// Nico, end of name handling
	//

	client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth;

	// To communicate it to cgame
	client->ps.stats[STAT_PLAYER_CLASS] = client->sess.playerType;
	// Gordon: Not needed any more as it's in clientinfo?

	// send over a subset of the userinfo keys so other clients can
	// print scoreboards, display models, and play custom sounds

	s = va("n\\%s\\t\\%i\\c\\%i\\w\\%i\\lw\\%i\\sw\\%i\\mu\\%i\\ref\\%i\\pm\\%i\\l\\%i\\h\\%i\\cc\\%i",
	       client->pers.netname,
	       client->sess.sessionTeam,
	       client->sess.playerType,
	       client->sess.playerWeapon,
	       client->sess.latchPlayerWeapon,
	       client->sess.latchPlayerWeapon2,
	       client->sess.muted ? 1 : 0,
	       client->sess.referee,
	       client->pers.pmoveFixed ? 1 : 0, // Nico, pmove_fixed
	       client->sess.logged ? 1 : 0, // Nico, login status
	       client->pers.hideme, // Nico, hideme
		   client->sess.countryCode// Nico, country code (GeoIP)
	       );

	trap_GetConfigstring(CS_PLAYERS + clientNum, oldname, sizeof (oldname));

	trap_SetConfigstring(CS_PLAYERS + clientNum, s);

	if (!Q_stricmp(oldname, s)) {
		return;
	}

	G_LogPrintf("ClientUserinfoChanged: %i %s\n", clientNum, s);
	G_DPrintf("ClientUserinfoChanged: %i :: %s\n", clientNum, s);
}
Esempio n. 28
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 )
{
	char            *value;
	char            *userInfoError;
	gclient_t       *client;
	char            userinfo[ MAX_INFO_STRING ];
	char            pubkey[ RSA_STRING_LENGTH ];
	gentity_t       *ent;
	char            reason[ MAX_STRING_CHARS ] = { "" };
	int             i;

	ent = &g_entities[ clientNum ];
	client = &level.clients[ clientNum ];

	// ignore if client already connected
	if ( client->pers.connected != CON_DISCONNECTED )
	{
		return NULL;
	}

	ent->client = client;
	memset( client, 0, sizeof( *client ) );

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

	value = Info_ValueForKey( userinfo, "ip" );

	// check for local client
	if ( !strcmp( value, "localhost" ) )
	{
		client->pers.localClient = qtrue;
	}

	G_AddressParse( value, &client->pers.ip );

	trap_GetPlayerPubkey( clientNum, pubkey, sizeof( pubkey ) );

	if ( strlen( pubkey ) != RSA_STRING_LENGTH - 1 )
	{
		return "Invalid pubkey key";
	}
	
	trap_GenFingerprint( pubkey, sizeof( pubkey ), client->pers.guid, sizeof( client->pers.guid ) );

	client->pers.admin = G_admin_admin( client->pers.guid );
	client->pers.pubkey_authenticated = 0;

	if ( client->pers.admin )
	{
		trap_RealTime( &client->pers.admin->lastSeen );
	}

	// check for admin ban
	if ( G_admin_ban_check( ent, reason, sizeof( reason ) ) )
	{
		return va( "%s", reason ); // reason is local
	}

	// 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";
	}

	// 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", (int)( ent - g_entities ) );
		// so lets just fix up anything that should happen on a disconnect
		ClientDisconnect( ent-g_entities );
	}

	for ( i = 0; i < level.maxclients; i++ )
	{
		if ( level.clients[ i ].pers.connected == CON_DISCONNECTED )
		{
			continue;
		}
		
		if ( !Q_stricmp( client->pers.guid, level.clients[ i ].pers.guid ) )
		{
			if ( !G_ClientIsLagging( level.clients + i ) )
			{
				trap_SendServerCommand( i, "cp \"Your GUID is not secure\"" );
				return "Duplicate GUID";
			}
			
			trap_DropClient( i, "Ghost" );
		}
	}
	
	client->pers.connected = CON_CONNECTING;

	// read or initialize the session data
	if ( firstTime )
	{
		G_InitSessionData( client, userinfo );
	}

	G_ReadSessionData( client );

	// get and distribute relevent paramters
	G_namelog_connect( client );
	userInfoError = ClientUserinfoChanged( clientNum, qfalse );

	if ( userInfoError != NULL )
	{
		return userInfoError;
	}

	G_LogPrintf( "ClientConnect: %i [%s] (%s) \"%s^7\" \"%c%s%c^7\"\n",
	             clientNum, client->pers.ip.str, client->pers.guid,
	             client->pers.netname,
	             DECOLOR_OFF, client->pers.netname, DECOLOR_ON );

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

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

	// if this is after !restart keepteams or !restart switchteams, apply said selection
	if ( client->sess.restartTeam != TEAM_NONE )
	{
		G_ChangeTeam( ent, client->sess.restartTeam );
		client->sess.restartTeam = TEAM_NONE;
	}

	return NULL;
}
Esempio n. 29
0
/*
===========
PlayerUserinfoChanged

Called from PlayerConnect when the player first connects and
directly by the server system when the player updates a userinfo variable.

The game can override any of the settings and call trap_SetUserinfo
if desired.
============
*/
void PlayerUserinfoChanged( int playerNum ) {
	gentity_t *ent;
	int		teamTask, teamLeader;
	char	*s;
	char	model[MAX_QPATH];
	char	headModel[MAX_QPATH];
	char	oldname[MAX_STRING_CHARS];
	gplayer_t	*player;
	char	c1[MAX_INFO_STRING];
	char	c2[MAX_INFO_STRING];
	char	userinfo[MAX_INFO_STRING];

	ent = g_entities + playerNum;
	player = ent->player;

	trap_GetUserinfo( playerNum, userinfo, sizeof( userinfo ) );

	// check for malformed or illegal info strings
	if ( !Info_Validate(userinfo) ) {
		strcpy (userinfo, "\\name\\badinfo");
		// don't keep those players and userinfo
		trap_DropPlayer(playerNum, "Invalid userinfo");
	}

	// check the item prediction
	s = Info_ValueForKey( userinfo, "cg_predictItems" );
	if ( !atoi( s ) ) {
		player->pers.predictItemPickup = qfalse;
	} else {
		player->pers.predictItemPickup = qtrue;
	}

	// check the anti lag
	s = Info_ValueForKey( userinfo, "cg_antiLag" );
	player->pers.antiLag = atoi( s );

	// set name
	Q_strncpyz ( oldname, player->pers.netname, sizeof( oldname ) );
	s = Info_ValueForKey (userinfo, "name");
	PlayerCleanName( s, player->pers.netname, sizeof(player->pers.netname) );

	if ( player->sess.sessionTeam == TEAM_SPECTATOR ) {
		if ( player->sess.spectatorState == SPECTATOR_SCOREBOARD ) {
			Q_strncpyz( player->pers.netname, "scoreboard", sizeof(player->pers.netname) );
		}
	}

	if ( player->pers.connected == CON_CONNECTED ) {
		if ( strcmp( oldname, player->pers.netname ) ) {
			trap_SendServerCommand( -1, va("print \"%s" S_COLOR_WHITE " renamed to %s\n\"", oldname, 
				player->pers.netname) );
		}
	}

	// set max health
#ifdef MISSIONPACK
	if (player->ps.powerups[PW_GUARD]) {
		player->pers.maxHealth = 200;
	} else {
		player->pers.maxHealth = PlayerHandicap( player );
	}
#else
	player->pers.maxHealth = PlayerHandicap( player );
#endif
	player->ps.stats[STAT_MAX_HEALTH] = player->pers.maxHealth;

	// set model
	if( g_gametype.integer >= GT_TEAM ) {
		Q_strncpyz( model, Info_ValueForKey (userinfo, "team_model"), sizeof( model ) );
		Q_strncpyz( headModel, Info_ValueForKey (userinfo, "team_headmodel"), sizeof( headModel ) );
	} else {
		Q_strncpyz( model, Info_ValueForKey (userinfo, "model"), sizeof( model ) );
		Q_strncpyz( headModel, Info_ValueForKey (userinfo, "headmodel"), sizeof( headModel ) );
	}

	// teamInfo
	s = Info_ValueForKey( userinfo, "teamoverlay" );
	if ( ! *s || atoi( s ) != 0 ) {
		player->pers.teamInfo = qtrue;
	} else {
		player->pers.teamInfo = qfalse;
	}

	/*
	s = Info_ValueForKey( userinfo, "cg_pmove_fixed" );
	if ( !*s || atoi( s ) == 0 ) {
		player->pers.pmoveFixed = qfalse;
	}
	else {
		player->pers.pmoveFixed = qtrue;
	}
	*/

	// team task (0 = none, 1 = offence, 2 = defence)
	teamTask = atoi(Info_ValueForKey(userinfo, "teamtask"));
	// team Leader (1 = leader, 0 is normal player)
	teamLeader = player->sess.teamLeader;

	// colors
	strcpy(c1, Info_ValueForKey( userinfo, "color1" ));
	strcpy(c2, Info_ValueForKey( userinfo, "color2" ));

	// send over a subset of the userinfo keys so other clients can
	// print scoreboards, display models, and play custom sounds
	if (ent->r.svFlags & SVF_BOT)
	{
		s = va("n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\skill\\%s\\tt\\%d\\tl\\%d",
			player->pers.netname, player->sess.sessionTeam, model, headModel, c1, c2, 
			player->pers.maxHealth, player->sess.wins, player->sess.losses,
			Info_ValueForKey( userinfo, "skill" ), teamTask, teamLeader );
	}
	else
	{
		s = va("n\\%s\\t\\%i\\model\\%s\\hmodel\\%s\\c1\\%s\\c2\\%s\\hc\\%i\\w\\%i\\l\\%i\\tt\\%d\\tl\\%d",
			player->pers.netname, player->sess.sessionTeam, model, headModel, c1, c2, 
			player->pers.maxHealth, player->sess.wins, player->sess.losses, teamTask, teamLeader);
	}

	trap_SetConfigstring( CS_PLAYERS+playerNum, s );

	// this is not the userinfo, more like the configstring actually
	G_LogPrintf( "PlayerUserinfoChanged: %i %s\n", playerNum, s );
}