Exemple #1
0
/*
===============
G_ParseMapRotationFile

Load the map rotations from a map rotation file
===============
*/
static bool G_ParseMapRotationFile( const char *fileName )
{
  char          *text_p;
  int           i;
  int           len;
  char          *token;
  char          text[ 20000 ];
  char          mrName[ MAX_QPATH ];
  bool      mrNameSet = false;
  fileHandle_t  f;

  // load the file
  len = trap_FS_FOpenFile( fileName, &f, FS_READ );
  if( len <= 0 )
    return false;

  if( len >= sizeof( text ) - 1 )
  {
    G_Printf( S_COLOR_RED "ERROR: map rotation file %s too long\n", fileName );
    return false;
  }

  trap_FS_Read( text, len, f );
  text[ len ] = 0;
  trap_FS_FCloseFile( f );

  // parse the text
  text_p = text;

  // read optional parameters
  while( 1 )
  {
    token = COM_Parse( &text_p );

    if( !token )
      break;

    if( !Q_stricmp( token, "" ) )
      break;

    if( !Q_stricmp( token, "{" ) )
    {
      if( mrNameSet )
      {
        //check for name space clashes
        for( i = 0; i < mapRotations.numRotations; i++ )
        {
          if( !Q_stricmp( mapRotations.rotations[ i ].name, mrName ) )
          {
            G_Printf( S_COLOR_RED "ERROR: a map rotation is already named %s\n", mrName );
            return false;
          }
        }

        Q_strncpyz( mapRotations.rotations[ mapRotations.numRotations ].name, mrName, MAX_QPATH );

        if( !G_ParseMapRotation( &mapRotations.rotations[ mapRotations.numRotations ], &text_p ) )
        {
          G_Printf( S_COLOR_RED "ERROR: %s: failed to parse map rotation %s\n", fileName, mrName );
          return false;
        }

        //start parsing particle systems again
        mrNameSet = false;

        if( mapRotations.numRotations == MAX_MAP_ROTATIONS )
        {
          G_Printf( S_COLOR_RED "ERROR: maximum number of map rotations (%d) reached\n",
                    MAX_MAP_ROTATIONS );
          return false;
        }
        else
          mapRotations.numRotations++;

        continue;
      }
      else
      {
        G_Printf( S_COLOR_RED "ERROR: unamed map rotation\n" );
        return false;
      }
    }

    if( !mrNameSet )
    {
      Q_strncpyz( mrName, token, sizeof( mrName ) );
      mrNameSet = true;
    }
    else
    {
      G_Printf( S_COLOR_RED "ERROR: map rotation already named\n" );
      return false;
    }
  }

  return true;
}
Exemple #2
0
/*
===================
Svcmd_EntityShow_f
===================
*/
void Svcmd_EntityShow_f( void )
{
	int       entityNum;
	int       lastTargetIndex, targetIndex;
	gentity_t *selection;
	gentity_t *possibleTarget = NULL;
	char argument[ 6 ];


	if (trap_Argc() != 2)
	{
		G_Printf("usage: entityShow <entityId>\n");
		return;
	}

	trap_Argv( 1, argument, sizeof( argument ) );
	entityNum = atoi( argument );

	if (entityNum >= level.num_entities || entityNum < MAX_CLIENTS)
	{
		G_Printf("entityId %d is out of range\n", entityNum);
		return;
	}

	selection = &g_entities[entityNum];

	if (!selection->inuse)
	{
		G_Printf("entity slot %d is unused/free\n", entityNum);
		return;
	}

	G_Printf( "⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼\n" );
	G_Printf( S_COLOR_CYAN "#%3i" S_COLOR_WHITE ": %16s", entityNum, Com_EntityTypeName( selection->s.eType ) );
	if (IS_NON_NULL_VEC3(selection->s.origin))
	{
		G_Printf("%26s", vtos( selection->s.origin ) );
	}
	G_Printf( "\n⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼\n" );
	G_Printf( "Classname: " S_COLOR_CYAN "%s" S_COLOR_WHITE "\n", selection->classname );
	G_Printf( "Capabilities:%s%s%s%s%s%s%s\n\n",
			selection->act ? " acts" : "",
			selection->think ? " thinks" : "",
			selection->pain ? " pains" : "",
			selection->die ? " dies" : "",
			selection->reset ? " resets" : "",
			selection->touch ? " touchable" : "",
			selection->use ? " usable" : "");
	if (selection->names[0])
	{
		G_Printf( "Names: ");
		G_PrintEntityNameList( selection );
	}

	G_Printf("State: %s\n", selection->enabled ? "enabled" : "disabled");

	if (selection->groupName)
	{
		G_Printf("Member of Group: %s%s\n", selection->groupName, !selection->groupMaster ? " [master]" : "");
	}

	G_Printf( "\n");

	if(selection->targetCount)
	{
		G_Printf( "Aims at\n");

		while ((possibleTarget = G_IterateTargets(possibleTarget, &targetIndex, selection)) != NULL )
		{
			G_Printf(" • %s %s\n", etos( possibleTarget ), vtos( possibleTarget->s.origin));
		}
		G_Printf( "\n");
	}

	if(selection->callTargetCount)
	{
		lastTargetIndex = -1;
		while ((possibleTarget = G_IterateCallEndpoints(possibleTarget, &targetIndex, selection)) != NULL )
		{

			if(lastTargetIndex != targetIndex)
			{
				G_Printf("Calls %s \"%s:%s\"\n",
						selection->calltargets[ targetIndex ].event ? selection->calltargets[ targetIndex ].event : "onUnknown",
						selection->calltargets[ targetIndex ].name,
						selection->calltargets[ targetIndex ].action ? selection->calltargets[ targetIndex ].action : "default");
				lastTargetIndex = targetIndex;
			}

			G_Printf(" • %s", etos(possibleTarget));
			if(possibleTarget->names[1])
			{
				G_Printf(" using \"%s\" ∈ ", selection->calltargets[ targetIndex ].name);
				G_PrintEntityNameList( possibleTarget );
			}
			G_Printf("\n");
		}
	}
	G_Printf( "\n" );
}
Exemple #3
0
/*
===============
G_AddBot
===============
*/
static void G_AddBot( const char *name, float skill, const char *team, int delay, char *altname) {
	int				clientNum;
	char			*botinfo;
	char			*key;
	char			*s;
	char			*botname;
	char			*model;
	char			*headmodel;
	char			userinfo[MAX_INFO_STRING];

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

	// get the botinfo from bots.txt
	botinfo = G_GetBotInfoByName( name );
	if ( !botinfo ) {
		G_Printf( S_COLOR_RED "Error: Bot '%s' not defined\n", name );
		trap->BotFreeClient( clientNum );
		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("%.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, "aifile");
	if (!*s ) {
		trap->Print( S_COLOR_RED "Error: bot has no aifile specified\n" );
		trap->BotFreeClient( clientNum );
		return;
	}
	Info_SetValueForKey( userinfo, "characterfile", s );

	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, "team", team );

	// register the userinfo
	trap->SetUserinfo( clientNum, userinfo );

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

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

	AddBotToSpawnQueue( clientNum, delay );
}
/*
=================
G_ScriptAction_PlayAnim

  syntax: playanim <startframe> <endframe> [looping <FOREVER/duration>] [rate <FPS>]

  NOTE: all source animations must be at 20fps
=================
*/
qboolean G_ScriptAction_PlayAnim( gentity_t *ent, const char* params ) {
    const char* pString;
    char* token;
    char tokens[2][MAX_QPATH];
	int i, endtime = 0; // TTimo: init
	qboolean looping = qfalse, forever = qfalse;
	int startframe, endframe, idealframe;
	int rate = 20;

	if ( ( ent->scriptStatus.scriptFlags & SCFL_ANIMATING ) && ( ent->scriptStatus.scriptStackChangeTime == level.time ) ) {
		// this is a new call, so cancel the previous animation
		ent->scriptStatus.scriptFlags &= ~SCFL_ANIMATING;
	}

	pString = params;

	for ( i = 0; i < 2; i++ ) {
		token = COM_ParseExt( &pString, qfalse );
		if ( !token || !token[0] ) {
			G_Printf( "G_Scripting: syntax error\n\nplayanim <startframe> <endframe> [LOOPING <duration>]\n" );
			return qtrue;
		} else {
			Q_strncpyz( tokens[i], token, sizeof( tokens[i] ) );
		}
	}

	startframe = atoi( tokens[0] );
	endframe = atoi( tokens[1] );

	// check for optional parameters
	token = COM_ParseExt( &pString, qfalse );
	if ( token[0] ) {
		if ( !Q_strcasecmp( token, "looping" ) ) {
			looping = qtrue;

			token = COM_ParseExt( &pString, qfalse );
			if ( !token || !token[0] ) {
				G_Printf( "G_Scripting: syntax error\n\nplayanim <startframe> <endframe> [LOOPING <duration>]\n" );
				return qtrue;
			}
			if ( !Q_strcasecmp( token, "untilreachmarker" ) ) {
				if ( level.time < ent->s.pos.trTime + ent->s.pos.trDuration ) {
					endtime = level.time + 100;
				} else {
					endtime = 0;
				}
			} else if ( !Q_strcasecmp( token, "forever" ) ) {
				ent->scriptStatus.animatingParams = params;
				ent->scriptStatus.scriptFlags |= SCFL_ANIMATING;
				endtime = level.time + 100;     // we don't care when it ends, since we are going forever!
				forever = qtrue;
			} else {
				endtime = ent->scriptStatus.scriptStackChangeTime + atoi( token );
			}

			token = COM_ParseExt( &pString, qfalse );
		}

		if ( token[0] && !Q_strcasecmp( token, "rate" ) ) {
			token = COM_ParseExt( &pString, qfalse );
			if ( !token[0] ) {
				G_Error( "G_Scripting: playanim has RATE parameter without an actual rate specified" );
			}
			rate = atoi( token );
		}

		if ( !looping ) {
			endtime = ent->scriptStatus.scriptStackChangeTime + ( ( endframe - startframe ) * ( 1000 / 20 ) );
		}
	}

	idealframe = startframe + (int)c::floor( (float)( level.time - ent->scriptStatus.scriptStackChangeTime ) / ( 1000.0 / (float)rate ) );
	if ( looping ) {
		ent->s.frame = startframe + ( idealframe - startframe ) % ( endframe - startframe );
		ent->s.eFlags |= EF_MOVER_ANIMATE;
	} else {
		if ( idealframe > endframe ) {
			ent->s.frame = endframe;
			ent->s.eFlags &= ~EF_MOVER_ANIMATE; // stop interpolation, since we have gone passed the endframe
		} else {
			ent->s.frame = idealframe;
			ent->s.eFlags |= EF_MOVER_ANIMATE;
		}
	}

	if ( forever ) {
		ent->s.eFlags |= EF_MOVER_ANIMATE;
		return qtrue;   // continue to the next command
	}

	if ( endtime <= level.time ) {
		ent->s.eFlags &= ~EF_MOVER_ANIMATE; // stop animating
		return qtrue;
	} else {
		return qfalse;
	}
}
Exemple #5
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];

	// 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	|| ( Q_stricmp(team, "red") && Q_stricmp(team, "blue") ) ) {
		team = "";
	}


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

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

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

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

	AddBotToSpawnQueue( clientNum, delay );
}
Exemple #6
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);
}
Exemple #7
0
static gentity_t *SpawnModelOnVictoryPad( gentity_t *pad, vec3_t offset, gentity_t *ent, int place ) {
	gentity_t	*body;
	vec3_t		vec;
	vec3_t		f, r, u;

	body = G_Spawn();
	if ( !body ) {
		G_Printf( S_COLOR_RED "ERROR: out of gentities\n" );
		return NULL;
	}

	body->classname = ent->client->pers.netname;
	body->client = ent->client;
	body->s = ent->s;
	body->s.eType = ET_PLAYER;		// could be ET_INVISIBLE
	body->s.eFlags = 0;				// clear EF_TALK, etc
	body->s.powerups = 0;			// clear powerups
	body->s.loopSound = 0;			// clear lava burning
	body->s.number = body - g_entities;
	body->timestamp = level.time;
	body->physicsObject = qtrue;
	body->physicsBounce = 0;		// don't bounce
	body->s.event = 0;
	body->s.pos.trType = TR_STATIONARY;
	body->s.groundEntityNum = ENTITYNUM_WORLD;
	body->s.legsAnim = LEGS_IDLE;
	body->s.torsoAnim = TORSO_STAND;
	if( body->s.weapon == WP_NONE ) {
		body->s.weapon = WP_MACHINEGUN;
	}
	if( body->s.weapon == WP_GAUNTLET) {
		body->s.torsoAnim = TORSO_STAND2;
	}
	body->s.event = 0;
	body->r.svFlags = ent->r.svFlags;
	VectorCopy (ent->s.mins, body->s.mins);
	VectorCopy (ent->s.maxs, body->s.maxs);
	VectorCopy (ent->r.absmin, body->r.absmin);
	VectorCopy (ent->r.absmax, body->r.absmax);
	body->clipmask = CONTENTS_SOLID | CONTENTS_PLAYERCLIP;
	body->s.contents = CONTENTS_BODY;
	body->r.ownerNum = ent->r.ownerNum;
	body->takedamage = qfalse;

	VectorSubtract( level.intermission_origin, pad->r.currentOrigin, vec );
	vectoangles( vec, body->s.apos.trBase );
	body->s.apos.trBase[PITCH] = 0;
	body->s.apos.trBase[ROLL] = 0;

	AngleVectors( body->s.apos.trBase, f, r, u );
	VectorMA( pad->r.currentOrigin, offset[0], f, vec );
	VectorMA( vec, offset[1], r, vec );
	VectorMA( vec, offset[2], u, vec );

	G_SetOrigin( body, vec );

	trap_LinkEntity (body);

	body->count = place;

	return body;
}
Exemple #8
0
static void G_AddBot(const char *name, int skill, const char *team, const char *spawnPoint, int playerClass, int playerWeapon,
					 int characerIndex, const char *respawn, const char *scriptName, int rank, int skills[], qboolean pow)
{
#define MAX_BOTNAMES 1024
	int             clientNum;
	char           *botinfo;
	gentity_t      *bot;
	char           *key;
	char           *s;
	char           *botname;

//  char            *model;
	char            userinfo[MAX_INFO_STRING];

	// get the botinfo from bots.txt
	botinfo = G_GetBotInfoByName("wolfbot");
	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");
	}
	Info_SetValueForKey(userinfo, "name", botname);
	Info_SetValueForKey(userinfo, "rate", "25000");
	Info_SetValueForKey(userinfo, "snaps", "20");
	Info_SetValueForKey(userinfo, "skill", va("%i", skill));

	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(0);	// Arnout: 0 means no prefered clientslot
	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(PickTeam(clientNum) == TEAM_AXIS)
		{
			team = "red";
		}
		else
		{
			team = "blue";
		}
	}
	Info_SetValueForKey(userinfo, "characterfile", Info_ValueForKey(botinfo, "aifile"));
	//Info_SetValueForKey( userinfo, "skill", va( "%i", skill ) );
	Info_SetValueForKey(userinfo, "team", team);

	if(spawnPoint && spawnPoint[0])
	{
		Info_SetValueForKey(userinfo, "spawnPoint", spawnPoint);
	}

	if(scriptName && scriptName[0])
	{
		Info_SetValueForKey(userinfo, "scriptName", scriptName);
	}

/*	if (playerClass > 0) {
		Info_SetValueForKey( userinfo, "pClass", va("%i", playerClass) );
	}

	if (playerWeapon) {
		Info_SetValueForKey( userinfo, "pWeapon", va("%i", playerWeapon) );
	}*/
	// END Mad Doc - TDF

	key = "wolfbot";
	if(!Q_stricmp((char *)name, key))
	{
		// read the botnames file, and pick a name that doesnt exist
		fileHandle_t    f;
		int             len, i, j, k;
		qboolean        setname = qfalse;
		char            botnames[8192], *pbotnames, *listbotnames[MAX_BOTNAMES], *token, *oldpbotnames;
		int             lengthbotnames[MAX_BOTNAMES];

		len = trap_FS_FOpenFile("botfiles/botnames.txt", &f, FS_READ);

		if(len >= 0)
		{
			if(len > sizeof(botnames))
			{
				G_Error("botfiles/botnames.txt is too big (max = %i)", (int)sizeof(botnames));
			}
			memset(botnames, 0, sizeof(botnames));
			trap_FS_Read(botnames, len, f);
			pbotnames = botnames;
			// read them in
			i = 0;
			oldpbotnames = pbotnames;
			while((token = COM_Parse(&pbotnames)))
			{
				if(!token[0])
				{
					break;
				}
				listbotnames[i] = strstr(oldpbotnames, token);
				lengthbotnames[i] = strlen(token);
				listbotnames[i][lengthbotnames[i]] = 0;
				oldpbotnames = pbotnames;
				if(++i == MAX_BOTNAMES)
				{
					break;
				}
			}
			//
			if(i > 2)
			{
				j = rand() % (i - 1);	// start at a random spot inthe list
				for(k = j + 1; k != j; k++)
				{
					if(k == i)
					{
						k = -1;	// gets increased on next loop
						continue;
					}
					if(ClientFromName(listbotnames[k]) == -1)
					{
						// found an unused name
						Info_SetValueForKey(userinfo, "name", listbotnames[k]);
						setname = qtrue;
						break;
					}
				}
			}
			//
			trap_FS_FCloseFile(f);
		}

		if(!setname)
		{
			Info_SetValueForKey(userinfo, "name", va("wolfbot_%i", clientNum + 1));
		}
	}
	else
	{
		Info_SetValueForKey(userinfo, "name", name);
	}

	// if a character was specified, put the index of that character filename in the CS_CHARACTERS table in the userinfo
	if(characerIndex != -1)
	{
		Info_SetValueForKey(userinfo, "ch", va("%i", characerIndex));
	}

	// if a rank was specified, use that
/*	if (rank != -1) {
		Info_SetValueForKey(userinfo, "rank", va("%i", rank));
	}*/

	// END Mad Doc - TDF

	bot = &g_entities[clientNum];
	bot->r.svFlags |= SVF_BOT;
	if(pow)
	{
		bot->r.svFlags |= SVF_POW;
	}
	bot->inuse = qtrue;
	bot->aiName = bot->client->pers.netname;

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

	// have it connect to the game as a normal client
	if((s = ClientConnect(clientNum, qtrue, qtrue)))
	{
		G_Printf(S_COLOR_RED "Unable to add bot: %s\n", s);
		return;
	}

	SetTeam(bot, (char *)team, qtrue, -1, -1, qfalse);

/*	if( skills ) {
		int i;

		for( i = 0; i < SK_NUM_SKILLS; i++ ) {
			bot->client->sess.skill[i] = skills[i];
		}
	}*/
	return;
}
Exemple #9
0
/*
=======================================================================================================================================
G_Damage

targ:		Entity that is being damaged.
inflictor:	Entity that is causing the damage.
attacker:	Entity that caused the inflictor to damage targ.

example: targ = monster, inflictor = rocket, attacker = player.

dir	:		Direction of the attack for knockback.
point:		Point at which the damage is being inflicted, used for headshots.
damage:		Amount of damage being inflicted.
knockback:	Force to be applied against targ as a result of the damage.

inflictor, attacker, dir, and point can be NULL for environmental effects.

dflags		These flags are used to control how G_Damage works.

 DAMAGE_RADIUS			Damage was indirect (from a nearby explosion).
 DAMAGE_NO_ARMOR		Armor does not protect from this damage.
 DAMAGE_NO_KNOCKBACK	Do not affect velocity, just view angles.
 DAMAGE_NO_PROTECTION	Kills godmode, armor, everything.
=======================================================================================================================================
*/
void G_Damage(gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, vec3_t dir, vec3_t point, int damage, int dflags, int mod) {
	gclient_t *client;
	int take;
	int asave;
	int knockback;
	int max;
#ifdef MISSIONPACK
	vec3_t bouncedir, impactpoint;
#endif
	if (!targ->takedamage) {
		return;
	}
	// the intermission has already been qualified for, so don't allow any extra scoring
	if (level.intermissionQueued) {
		return;
	}
#ifdef MISSIONPACK
	if (targ->client && mod != MOD_JUICED) {
		if (targ->client->invulnerabilityTime > level.time) {
			if (dir && point) {
				G_InvulnerabilityEffect(targ, dir, point, impactpoint, bouncedir);
			}

			return;
		}
	}
#endif
	if (!inflictor) {
		inflictor = &g_entities[ENTITYNUM_WORLD];
	}

	if (!attacker) {
		attacker = &g_entities[ENTITYNUM_WORLD];
	}
	// shootable doors / buttons don't actually have any health
	if (targ->s.eType == ET_MOVER) {
		if (targ->use && targ->moverState == MOVER_POS1) {
			targ->use(targ, inflictor, attacker);
		}

		return;
	}
#ifdef MISSIONPACK
	if (g_gametype.integer == GT_OBELISK && CheckObeliskAttack(targ, attacker)) {
		return;
	}
#endif
	// reduce damage by the attacker's handicap value unless they are rocket jumping
	if (attacker->client && attacker != targ) {
		max = attacker->client->ps.stats[STAT_MAX_HEALTH];
#ifdef MISSIONPACK
		if (bg_itemlist[attacker->client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD) {
			max /= 2;
		}
#endif
		damage = damage * max / 100;
	}

	client = targ->client;

	if (client) {
		if (client->noclip) {
			return;
		}
	}

	if (!dir) {
		dflags |= DAMAGE_NO_KNOCKBACK;
	} else {
		VectorNormalize(dir);
	}

	knockback = damage;

	if (knockback > 200) {
		knockback = 200;
	}

	if (targ->flags & FL_NO_KNOCKBACK) {
		knockback = 0;
	}

	if (dflags & DAMAGE_NO_KNOCKBACK) {
		knockback = 0;
	}
	// figure momentum add, even if the damage won't be taken
	if (knockback && targ->client) {
		vec3_t kvel;
		float mass;

		mass = 200;

		VectorScale(dir, g_knockback.value * (float)knockback / mass, kvel);
		VectorAdd(targ->client->ps.velocity, kvel, targ->client->ps.velocity);
		// set the timer so that the other client can't cancel out the movement immediately
		if (!targ->client->ps.pm_time) {
			int t;

			t = knockback * 2;

			if (t < 50) {
				t = 50;
			}

			if (t > 200) {
				t = 200;
			}

			targ->client->ps.pm_time = t;
			targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
		}
	}
	// check for completely getting out of the damage
	if (!(dflags & DAMAGE_NO_PROTECTION)) {
		// if TF_NO_FRIENDLY_FIRE is set, don't do damage to the target if the attacker was on the same team
#ifdef MISSIONPACK
		if (mod != MOD_JUICED && targ != attacker && !(dflags & DAMAGE_NO_TEAM_PROTECTION) && OnSameTeam(targ, attacker)) {
#else
		if (targ != attacker && OnSameTeam(targ, attacker)) {
#endif
			if (!g_friendlyFire.integer) {
				return;
			}
		}
#ifdef MISSIONPACK
		if (mod == MOD_PROXIMITY_MINE) {
			if (inflictor && inflictor->parent && OnSameTeam(targ, inflictor->parent)) {
				return;
			}

			if (targ == attacker) {
				return;
			}
		}
#endif
		// check for godmode
		if (targ->flags & FL_GODMODE) {
			return;
		}
	}
	// battlesuit protects from all radius damage (but takes knockback) and protects 50% against all damage
	if (client && client->ps.powerups[PW_BATTLESUIT]) {
		G_AddEvent(targ, EV_POWERUP_BATTLESUIT, 0);

		if ((dflags & DAMAGE_RADIUS) || (mod == MOD_FALLING)) {
			return;
		}

		damage *= 0.5;
	}
	// add to the attacker's hit counter (if the target isn't a general entity like a prox mine)
	if (attacker->client && client && targ != attacker && targ->health > 0 && targ->s.eType != ET_MISSILE && targ->s.eType != ET_GENERAL) {
		if (OnSameTeam(targ, attacker)) {
			attacker->client->ps.persistant[PERS_HITS]--;
		} else {
			attacker->client->ps.persistant[PERS_HITS]++;
		}

		attacker->client->ps.persistant[PERS_ATTACKEE_ARMOR] = (targ->health << 8)|(client->ps.stats[STAT_ARMOR]);
	}
	// always give half damage if hurting self, calculated after knockback, so rocket jumping works
	if (targ == attacker) {
		damage *= 0.5;
	}

	if (damage < 1) {
		damage = 1;
	}

	take = damage;
	// save some from armor
	asave = CheckArmor(targ, take, dflags);
	take -= asave;

	if (g_debugDamage.integer) {
		G_Printf("%i: client:%i health:%i damage:%i armor:%i\n", level.time, targ->s.number, targ->health, take, asave);
	}
	// add to the damage inflicted on a player this frame
	// the total will be turned into screen blends and view angle kicks at the end of the frame
	if (client) {
		if (attacker) {
			client->ps.persistant[PERS_ATTACKER] = attacker->s.number;
		} else {
			client->ps.persistant[PERS_ATTACKER] = ENTITYNUM_WORLD;
		}

		client->damage_armor += asave;
		client->damage_blood += take;
		client->damage_knockback += knockback;

		if (dir) {
			VectorCopy(dir, client->damage_from);
			client->damage_fromWorld = qfalse;
		} else {
			VectorCopy(targ->r.currentOrigin, client->damage_from);
			client->damage_fromWorld = qtrue;
		}
	}
	// see if it's the player hurting the emeny flag carrier
#ifdef MISSIONPACK
	if (g_gametype.integer == GT_CTF || g_gametype.integer == GT_1FCTF) {
#else
	if (g_gametype.integer == GT_CTF) {
#endif
		Team_CheckHurtCarrier(targ, attacker);
	}

	if (targ->client) {
		// set the last client who damaged the target
		targ->client->lasthurt_client = attacker->s.number;
		targ->client->lasthurt_mod = mod;
	}
	// do the damage
	if (take) {
		targ->health = targ->health - take;

		if (targ->client) {
			targ->client->ps.stats[STAT_HEALTH] = targ->health;
		}

		if (targ->health <= 0) {
			if (client) {
				targ->flags |= FL_NO_KNOCKBACK;
			}

			if (targ->health < -999) {
				targ->health = -999;
			}

			targ->enemy = attacker;
			targ->die(targ, inflictor, attacker, take, mod);
			return;
		} else if (targ->pain) {
			targ->pain(targ, attacker, take);
		}
	}
}

/*
=======================================================================================================================================
CanDamage

Returns qtrue if the inflictor can directly damage the target. Used for explosions and melee attacks.
=======================================================================================================================================
*/
qboolean CanDamage(gentity_t *targ, vec3_t origin) {
	vec3_t dest;
	trace_t tr;
	vec3_t midpoint;
	vec3_t offsetmins = {-15, -15, -15};
	vec3_t offsetmaxs = {15, 15, 15};

	// use the midpoint of the bounds instead of the origin, because bmodels may have their origin is 0, 0, 0
	VectorAdd(targ->r.absmin, targ->r.absmax, midpoint);
	VectorScale(midpoint, 0.5, midpoint);
	VectorCopy(midpoint, dest);
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);

	if (tr.fraction == 1.0 || tr.entityNum == targ->s.number) {
		return qtrue;
	}
	// this should probably check in the plane of projection, rather than in world coordinate
	VectorCopy(midpoint, dest);
	dest[0] += offsetmaxs[0];
	dest[1] += offsetmaxs[1];
	dest[2] += offsetmaxs[2];
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);

	if (tr.fraction == 1.0) {
		return qtrue;
	}

	VectorCopy(midpoint, dest);
	dest[0] += offsetmaxs[0];
	dest[1] += offsetmins[1];
	dest[2] += offsetmaxs[2];
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);

	if (tr.fraction == 1.0) {
		return qtrue;
	}

	VectorCopy(midpoint, dest);
	dest[0] += offsetmins[0];
	dest[1] += offsetmaxs[1];
	dest[2] += offsetmaxs[2];
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);

	if (tr.fraction == 1.0) {
		return qtrue;
	}

	VectorCopy(midpoint, dest);
	dest[0] += offsetmins[0];
	dest[1] += offsetmins[1];
	dest[2] += offsetmaxs[2];
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);

	if (tr.fraction == 1.0) {
		return qtrue;
	}

	VectorCopy(midpoint, dest);
	dest[0] += offsetmaxs[0];
	dest[1] += offsetmaxs[1];
	dest[2] += offsetmins[2];
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);

	if (tr.fraction == 1.0) {
		return qtrue;
	}

	VectorCopy(midpoint, dest);
	dest[0] += offsetmaxs[0];
	dest[1] += offsetmins[1];
	dest[2] += offsetmins[2];
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);

	if (tr.fraction == 1.0) {
		return qtrue;
	}

	VectorCopy(midpoint, dest);
	dest[0] += offsetmins[0];
	dest[1] += offsetmaxs[1];
	dest[2] += offsetmins[2];
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);

	if (tr.fraction == 1.0) {
		return qtrue;
	}

	VectorCopy(midpoint, dest);
	dest[0] += offsetmins[0];
	dest[1] += offsetmins[1];
	dest[2] += offsetmins[2];
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);

	if (tr.fraction == 1.0) {
		return qtrue;
	}

	return qfalse;
}

/*
=======================================================================================================================================
G_RadiusDamage
=======================================================================================================================================
*/
qboolean G_RadiusDamage(vec3_t origin, gentity_t *attacker, float damage, float radius, gentity_t *ignore, int mod) {
	float points, dist;
	gentity_t *ent;
	int entityList[MAX_GENTITIES];
	int numListedEntities;
	vec3_t mins, maxs;
	vec3_t v;
	vec3_t dir;
	int i, e;
	qboolean hitClient = qfalse;

	if (radius < 1) {
		radius = 1;
	}

	for (i = 0; i < 3; i++) {
		mins[i] = origin[i] - radius;
		maxs[i] = origin[i] + radius;
	}

	numListedEntities = trap_EntitiesInBox(mins, maxs, entityList, MAX_GENTITIES);

	for (e = 0; e < numListedEntities; e++) {
		ent = &g_entities[entityList[e]];

		if (ent == ignore) {
			continue;
		}

		if (!ent->takedamage) {
			continue;
		}
		// find the distance from the edge of the bounding box
		for (i = 0; i < 3; i++) {
			if (origin[i] < ent->r.absmin[i]) {
				v[i] = ent->r.absmin[i] - origin[i];
			} else if (origin[i] > ent->r.absmax[i]) {
				v[i] = origin[i] - ent->r.absmax[i];
			} else {
				v[i] = 0;
			}
		}

		dist = VectorLength(v);

		if (dist >= radius) {
			continue;
		}

		points = damage * (1.0 - dist / radius);

		if (CanDamage(ent, origin)) {
			if (LogAccuracyHit(ent, attacker)) {
				hitClient = qtrue;
			}

			VectorSubtract(ent->r.currentOrigin, origin, dir);
			// push the center of mass higher than the origin so players get knocked into the air more
			dir[2] += 24;

			G_Damage(ent, NULL, attacker, dir, origin, (int)points, DAMAGE_RADIUS, mod);
		}
	}

	return hitClient;
}
Exemple #10
0
//KK-OAX This was moved from g_mem.c to keep functionality from being broken. 
void Svcmd_GameMem_f( void ) {

    int usedMem;
    usedMem = POOLSIZE - freeMem;
	G_Printf( "Game memory status: %i out of %i bytes allocated\n", usedMem, POOLSIZE );
}
Exemple #11
0
/*
==================
G_SpawnBot
==================
*/
void G_SpawnBot(const char *text)
{
	// bot parameters
	char            name[MAX_TOKEN_CHARS] = "wolfBot";

	//GS  prevent bot health from counting down to 70 (i.e. don't set STAT_MAX_HEALTH = 70)
	char            skill[MAX_TOKEN_CHARS] = "4";
	char            team[MAX_TOKEN_CHARS] = "";
	char            pClass[MAX_TOKEN_CHARS] = "";
	char            pWeapon[MAX_TOKEN_CHARS] = "0";
	char            spawnPoint[MAX_TOKEN_CHARS] = "";
	char            respawn[MAX_TOKEN_CHARS] = "";
	char            scriptName[MAX_TOKEN_CHARS] = "wolfBot";
	char            characterFile[MAX_TOKEN_CHARS] = "";

	// START - Mad Doc - TDF
	char            rank[MAX_TOKEN_CHARS] = "";
	char            botSkills[MAX_TOKEN_CHARS] = "";

	// END Mad Doc - TDF

	char            pow[MAX_TOKEN_CHARS] = "no";


	// This is the selection meny index used in SetWolfSpawnWeapons
	int             weaponSpawnNumber = -1;

	// parsing vars
	char           *token, *pStr, *old_pStr;
	char            cmd[MAX_TOKEN_CHARS], last_cmd[MAX_TOKEN_CHARS];
	char            cmd_var[MAX_TOKEN_CHARS];
	char            string[MAX_TOKEN_CHARS];
	int             j, pClassInt;
	int             characterInt, rankNum;
	int             skills[SK_NUM_SKILLS];
	qboolean        prisonerOfWar;
	int             teamNum;

	// parameters
	spawnBotCommand_t params[] = {
		{"/name", name, qfalse, "[name]"},
		{"/skill", skill, qfalse, "[0-4]"},
		{"/team", team, qfalse, "[AXIS/ALLIES]"},
		{"/class", pClass, qfalse, "[SOLDIER/MEDIC/LIEUTENANT/ENGINEER/COVERTOPS/FIELDOPS]"},	// FIXME: remove LIEUTENANT from missionpack
		{"/weapon", pWeapon, qfalse, "[weaponValue]"},
		{"/spawnpoint", spawnPoint, qtrue, "[targetname]"},
		{"/respawn", respawn, qfalse, "[ON/OFF]"},
		{"/scriptName", scriptName, qfalse, "[scriptName]"},
		{"/character", characterFile, qfalse, "[character]"},
		// START Mad Doc - TDF
		{"/rank", rank, qfalse, "[rank]"},
		{"/skills", botSkills, qfalse, "[botskills]"},	// not really to be exposed to script
		// END Mad Doc - TDF
		{"/pow", pow, qfalse, "[yes/no]"},

		{NULL}
	};
	// special tables
	typedef struct
	{
		char           *weapon;
		int             index;
	} spawnBotWeapons_t;

	// TAT 1/16/2003 - uninit'ed data here - getting crazy data for the skills
	memset(&skills, 0, sizeof(skills));

	//
	// parse the vars
	pStr = (char *)text;
	token = COM_Parse(&pStr);
	Q_strncpyz(cmd, token, sizeof(cmd));
	// if this is a question mark, show help info
	if(!Q_stricmp(cmd, "?") || !Q_stricmp(cmd, "/?"))
	{
		G_Printf
			("Spawns a bot into the game, with the given parameters.\n\nSPAWNBOT [/param [value]] [/param [value]] ...\n\n  where [/param [value]] may consist of:\n\n");
		for(j = 0; params[j].cmd; j++)
		{
			G_Printf("  %s %s\n", params[j].cmd, params[j].help);
		}
		return;
	}
	//
	// intitializations
	for(j = 0; params[j].cmd; j++)
	{
		params[j].count = 0;
	}
	memset(last_cmd, 0, sizeof(last_cmd));
	pStr = (char *)text;
	//
	// parse each command
	while(cmd[0])
	{
		//
		// build the string up to the next parameter change
		token = COM_Parse(&pStr);
		Q_strncpyz(cmd, token, sizeof(cmd));
		if(!cmd[0])
		{
			break;
		}
		// if we find an "or", then use the last command
		if(!Q_stricmp(cmd, "or"))
		{
			// use the last command
			Q_strncpyz(cmd, last_cmd, sizeof(cmd));
		}
		//
		// read the parameters
		memset(string, 0, sizeof(string));
		token = COM_Parse(&pStr);
		Q_strncpyz(cmd_var, token, sizeof(cmd_var));
		if(!cmd_var[0])
		{
			break;
		}
		while(qtrue)
		{
			Q_strcat(string, sizeof(string), cmd_var);
			old_pStr = pStr;
			token = COM_Parse(&pStr);
			Q_strncpyz(cmd_var, token, sizeof(cmd_var));
			if(cmd_var[0] && (cmd_var[0] == '/' || !Q_stricmp(cmd_var, "or")))
			{
				pStr = old_pStr;
				break;
			}
			if(!cmd_var[0])
			{
				break;
			}
			Q_strcat(string, sizeof(string), " ");
		}
		//
		// see if this command exists in the parameters table
		for(j = 0; params[j].cmd; j++)
		{
			if(!Q_stricmp(params[j].cmd, cmd))
			{
				// found a match, if this field already has an entry, then randomly override it
				if(!params[j].count || (!params[j].appendParams && ((rand() % (++params[j].count)) == 0)))
				{
					Q_strncpyz(params[j].string, string, sizeof(string));
				}
				else if(params[j].appendParams)
				{
					// append this token
					Q_strcat(params[j].string, sizeof(string), va(" %s", string));
				}
				params[j].count++;
				break;
			}
		}
		if(!params[j].cmd)
		{
			G_Printf("G_SpawnBot: unknown parameter: %s\nFor usage info, use \"spawnbot /?\"\n", cmd);
			return;
		}
		//
		Q_strncpyz(last_cmd, cmd, sizeof(last_cmd));
		Q_strncpyz(cmd, cmd_var, sizeof(cmd));
	}
	//
	if(strlen(pClass))
	{
		pClassInt = 1 + G_ClassForString(pClass);
	}
	else
	{
		pClassInt = 0;
	}

	if(!Q_stricmp(team, "red") || !Q_stricmp(team, "r") || !Q_stricmp(team, "axis"))
	{
		teamNum = TEAM_AXIS;
	}
	else if(!Q_stricmp(team, "blue") || !Q_stricmp(team, "b") || !Q_stricmp(team, "allies"))
	{
		teamNum = TEAM_ALLIES;
	}
	else
	{
		// pick the team with the least number of players
		teamNum = PickTeam(-1);
	}

	G_BotParseCharacterParms(characterFile, &characterInt);

	// Gordon: 27/11/02
	if(*pow && !Q_stricmp(pow, "yes"))
	{
		prisonerOfWar = qtrue;
	}
	else
	{
		prisonerOfWar = qfalse;
	}

	// START Mad Doc - TDF
	// special case: if "NONE" is specified, treat this differently
	if(!Q_stricmp(pWeapon, "NONE"))
	{
		weaponSpawnNumber = -1;
	}
	// END Mad Doc - TDF
	// START    Mad Doctor I changes, 8/17/2002.
	// If we have a weapon specified, and we have a class specified
	else if(isdigit(pWeapon[0]))
	{
		// Just convert the string to a number
		weaponSpawnNumber = atoi(pWeapon);

	}							// if (isdigit(pWeapon[0]))...
	// If we have a weapon specified as a string, and we have a class specified
	else if(pClassInt > 0)
	{
		// Translate the weapon name into a proper weapon index
		// Get the index for the weapon
		weaponSpawnNumber = Bot_GetWeaponForClassAndTeam(pClassInt - 1, teamNum, pWeapon);

		// Get default weapon
		if(weaponSpawnNumber == -1)
		{
			weaponSpawnNumber = BG_GetPlayerClassInfo(teamNum, pClassInt - 1)->classWeapons[0];
		}

	}							// if (Q_stricmp(pWeapon[MAX_TOKEN_CHARS], "0")...
	// Otherwise, no weapon is selected
	else
	{
		// Just use the default
		weaponSpawnNumber = BG_GetPlayerClassInfo(teamNum, pClassInt - 1)->classWeapons[0];

	}							// else...


	// START Mad Doc - TDF
	rankNum = atoi(rank);
	if(rankNum)
	{
		rankNum--;				// people like to start with 1
		// Gordon: coders are people too :(
	}

	if(botSkills[0])
	{
		// parse the skills out
		int             i;
		char           *pString, *token;

		pString = botSkills;
		for(i = 0; i < SK_NUM_SKILLS; i++)
		{
			token = COM_ParseExt(&pString, qfalse);
			skills[i] = atoi(token);
		}
	}


	//  {"/botskills",  botSkills,      qfalse,     "[botskills]"}, // not really to be exposed to script

// END Mad Doc - TDF

	G_AddBot(name, atoi(skill), team, spawnPoint, pClassInt, weaponSpawnNumber, characterInt, respawn, scriptName, rankNum,
			 skills, prisonerOfWar);

// END      Mad Doctor I changes, 8/17/2002.
}
Exemple #12
0
void
G_Say(Gentity *ent, Gentity *target, int mode, const char *chatText)
{
	int	j;
	Gentity *other;
	int	color;
	char	name[64];
	/* don't let text be too long for malicious reasons */
	char	text[MAX_SAY_TEXT];
	char	location[64];

	if(g_gametype.integer < GT_TEAM && mode == SAY_TEAM)
		mode = SAY_ALL;

	switch(mode){
	default:
	case SAY_ALL:
		G_LogPrintf("say: %s: %s\n", ent->client->pers.netname, chatText);
		Q_sprintf (name, sizeof(name), "%s%c%c"EC ": ",
			ent->client->pers.netname, Q_COLOR_ESCAPE,
			COLOR_WHITE);
		color = COLOR_GREEN;
		break;
	case SAY_TEAM:
		G_LogPrintf("sayteam: %s: %s\n", ent->client->pers.netname,
			chatText);
		if(Team_GetLocationMsg(ent, location, sizeof(location)))
			Q_sprintf (name, sizeof(name),
				EC "(%s%c%c"EC ") (%s)"EC ": ",
				ent->client->pers.netname, Q_COLOR_ESCAPE,
				COLOR_WHITE,
				location);
		else
			Q_sprintf (name, sizeof(name),
				EC "(%s%c%c"EC ")"EC ": ",
				ent->client->pers.netname, Q_COLOR_ESCAPE,
				COLOR_WHITE);
		color = COLOR_CYAN;
		break;
	case SAY_TELL:
		if(target && g_gametype.integer >= GT_TEAM &&
		   target->client->sess.team ==
		   ent->client->sess.team &&
		   Team_GetLocationMsg(ent, location, sizeof(location)))
			Q_sprintf (name, sizeof(name),
				EC "[%s%c%c"EC "] (%s)"EC ": ",
				ent->client->pers.netname,
				Q_COLOR_ESCAPE, COLOR_WHITE,
				location);
		else
			Q_sprintf (name, sizeof(name),
				EC "[%s%c%c"EC "]"EC ": ",
				ent->client->pers.netname,
				Q_COLOR_ESCAPE,
				COLOR_WHITE);
		color = COLOR_MAGENTA;
		break;
	}

	Q_strncpyz(text, chatText, sizeof(text));

	if(target){
		G_SayTo(ent, target, mode, color, name, text);
		return;
	}

	/* echo the text to the console */
	if(g_dedicated.integer)
		G_Printf("%s%s\n", name, text);

	/* send it to all the apropriate clients */
	for(j = 0; j < level.maxclients; j++){
		other = &g_entities[j];
		G_SayTo(ent, other, mode, color, name, text);
	}
}
Exemple #13
0
/*
================
FinishSpawningItem

Traces down to find where an item should rest, instead of letting them
free fall from their spawn points
================
*/
void FinishSpawningItem(gentity_t *ent)
{
	trace_t tr;
	vec3_t  dest;
	vec3_t  maxs;

	if (ent->spawnflags & 1)     // suspended
	{
		VectorSet(ent->r.mins, -ITEM_RADIUS, -ITEM_RADIUS, -ITEM_RADIUS);
		VectorSet(ent->r.maxs, ITEM_RADIUS, ITEM_RADIUS, ITEM_RADIUS);
		VectorCopy(ent->r.maxs, maxs);
	}
	else
	{
		// had to modify this so that items would spawn in shelves
		VectorSet(ent->r.mins, -ITEM_RADIUS, -ITEM_RADIUS, 0);
		VectorSet(ent->r.maxs, ITEM_RADIUS, ITEM_RADIUS, ITEM_RADIUS);
		VectorCopy(ent->r.maxs, maxs);
		maxs[2] /= 2;
	}

	ent->r.contents   = CONTENTS_TRIGGER | CONTENTS_ITEM;
	ent->touch        = Touch_Item_Auto;
	ent->s.eType      = ET_ITEM;
	ent->s.modelindex = ent->item - bg_itemlist;        // store item number in modelindex

	ent->s.otherEntityNum2 = 0;     // takes modelindex2's place in signaling a dropped item
	// we don't use this (yet, anyway) so I'm taking it so you can specify a model for treasure items and clipboards
	//ent->s.modelindex2 = 0; // zero indicates this isn't a dropped item
	if (ent->model)
	{
		ent->s.modelindex2 = G_ModelIndex(ent->model);
	}

	// using an item causes it to respawn
	ent->use = Use_Item;

	// moved this up so it happens for suspended items too (and made it a function)
	G_SetAngle(ent, ent->s.angles);

	if (ent->spawnflags & 1)        // suspended
	{
		G_SetOrigin(ent, ent->s.origin);
	}
	else
	{
		VectorSet(dest, ent->s.origin[0], ent->s.origin[1], ent->s.origin[2] - 4096);
		trap_Trace(&tr, ent->s.origin, ent->r.mins, maxs, dest, ent->s.number, MASK_SOLID);

		if (tr.startsolid)
		{
			vec3_t temp;

			VectorCopy(ent->s.origin, temp);
			temp[2] -= ITEM_RADIUS;

			VectorSet(dest, ent->s.origin[0], ent->s.origin[1], ent->s.origin[2] - 4096);
			trap_Trace(&tr, temp, ent->r.mins, maxs, dest, ent->s.number, MASK_SOLID);
		}

		if (tr.startsolid)
		{
			G_Printf("FinishSpawningItem: %s startsolid at %s\n", ent->classname, vtos(ent->s.origin));
			G_FreeEntity(ent);
			return;
		}

		// allow to ride movers
		ent->s.groundEntityNum = tr.entityNum;

		G_SetOrigin(ent, tr.endpos);
	}

	if (ent->spawnflags & 2)          // spin
	{
		ent->s.eFlags |= EF_SPINNING;
	}

	// team slaves and targeted items aren't present at start
	if ((ent->flags & FL_TEAMSLAVE) || ent->targetname)
	{
		ent->flags |= FL_NODRAW;
		//ent->s.eFlags |= EF_NODRAW;
		ent->r.contents = 0;
		return;
	}

	// health/ammo can potentially be multi-stage (multiple use)
	if (ent->item->giType == IT_HEALTH || ent->item->giType == IT_AMMO)
	{
		int i;

		// having alternate models defined in bg_misc.c for a health or ammo item specify it as "multi-stage"
		// - left-hand operand of comma expression has no effect
		// initial line: for(i=0;i<4,ent->item->world_model[i];i++) {}
		for (i = 0; i < 4 && ent->item->world_model[i] ; i++)
		{
		}

		ent->s.density = i - 1;   // store number of stages in 'density' for client (most will have '1')
	}

	trap_LinkEntity(ent);
}
Exemple #14
0
/*
===============
G_ParseMapRotation

Parse a map rotation section
===============
*/
static bool G_ParseMapRotation( mapRotation_t *mr, char **text_p )
{
  char                    *token;
  bool                mnSet = false;
  mapRotationEntry_t      *mre = NULL;
  mapRotationCondition_t  *mrc;

  // read optional parameters
  while( 1 )
  {
    token = COM_Parse( text_p );

    if( !token )
      break;

    if( !Q_stricmp( token, "" ) )
      return false;

    if( !Q_stricmp( token, "{" ) )
    {
      if( !mnSet )
      {
        G_Printf( S_COLOR_RED "ERROR: map settings section with no name\n" );
        return false;
      }

      if( !G_ParseMapCommandSection( mre, text_p ) )
      {
        G_Printf( S_COLOR_RED "ERROR: failed to parse map command section\n" );
        return false;
      }

      mnSet = false;
      continue;
    }
    else if( !Q_stricmp( token, "goto" ) )
    {
      token = COM_Parse( text_p );

      if( !token )
        break;

      mrc = &mre->conditions[ mre->numConditions ];
      mrc->unconditional = true;
      Q_strncpyz( mrc->dest, token, sizeof( mrc->dest ) );

      if( mre->numConditions == MAX_MAP_ROTATION_CONDS )
      {
        G_Printf( S_COLOR_RED "ERROR: maximum number of conditions for one map (%d) reached\n",
                  MAX_MAP_ROTATION_CONDS );
        return false;
      }
      else
        mre->numConditions++;

      continue;
    }
    else if( !Q_stricmp( token, "if" ) )
    {
      token = COM_Parse( text_p );

      if( !token )
        break;

      mrc = &mre->conditions[ mre->numConditions ];

      if( !Q_stricmp( token, "numClients" ) )
      {
        mrc->lhs = MCV_NUMCLIENTS;

        token = COM_Parse( text_p );

        if( !token )
          break;

        if( !Q_stricmp( token, "<" ) )
          mrc->op = MCO_LT;
        else if( !Q_stricmp( token, ">" ) )
          mrc->op = MCO_GT;
        else if( !Q_stricmp( token, "=" ) )
          mrc->op = MCO_EQ;
        else
        {
          G_Printf( S_COLOR_RED "ERROR: invalid operator in expression: %s\n", token );
          return false;
        }

        token = COM_Parse( text_p );

        if( !token )
          break;

        mrc->numClients = atoi( token );
      }
      else if( !Q_stricmp( token, "lastWin" ) )
      {
        mrc->lhs = MCV_LASTWIN;

        token = COM_Parse( text_p );

        if( !token )
          break;

        if( !Q_stricmp( token, "aliens" ) )
          mrc->lastWin = PTE_ALIENS;
        else if( !Q_stricmp( token, "humans" ) )
          mrc->lastWin = PTE_HUMANS;
        else
        {
          G_Printf( S_COLOR_RED "ERROR: invalid right hand side in expression: %s\n", token );
          return false;
        }
      }
      else if( !Q_stricmp( token, "random" ) )
        mrc->lhs = MCV_RANDOM;
      else
      {
        G_Printf( S_COLOR_RED "ERROR: invalid left hand side in expression: %s\n", token );
        return false;
      }

      token = COM_Parse( text_p );

      if( !token )
        break;

      mrc->unconditional = false;
      Q_strncpyz( mrc->dest, token, sizeof( mrc->dest ) );

      if( mre->numConditions == MAX_MAP_ROTATION_CONDS )
      {
        G_Printf( S_COLOR_RED "ERROR: maximum number of conditions for one map (%d) reached\n",
                  MAX_MAP_ROTATION_CONDS );
        return false;
      }
      else
        mre->numConditions++;

      continue;
    }
    else if( !Q_stricmp( token, "}" ) )
      return true; //reached the end of this map rotation

    mre = &mr->maps[ mr->numMaps ];

    if( mr->numMaps == MAX_MAP_ROTATION_MAPS )
    {
      G_Printf( S_COLOR_RED "ERROR: maximum number of maps in one rotation (%d) reached\n",
                MAX_MAP_ROTATION_MAPS );
      return false;
    }
    else
      mr->numMaps++;

    Q_strncpyz( mre->name, token, sizeof( mre->name ) );
    mnSet = true;
  }

  return false;
}
Exemple #15
0
/*
===================
Svcmd_EntityList_f
===================
*/
void    Svcmd_EntityList_f( void ) {
	int e;
	gentity_t       *check;

	check = g_entities + 1;
	for ( e = 1; e < level.num_entities ; e++, check++ ) {
		if ( !check->inuse ) {
			continue;
		}
		G_Printf( "%3i:", e );
		switch ( check->s.eType ) {
		case ET_GENERAL:
			G_Printf( "ET_GENERAL          " );
			break;
		case ET_PLAYER:
			G_Printf( "ET_PLAYER           " );
			break;
		case ET_ITEM:
			G_Printf( "ET_ITEM             " );
			break;
		case ET_MISSILE:
			G_Printf( "ET_MISSILE          " );
			break;
		case ET_MOVER:
			G_Printf( "ET_MOVER            " );
			break;
		case ET_BEAM:
			G_Printf( "ET_BEAM             " );
			break;
		case ET_PORTAL:
			G_Printf( "ET_PORTAL           " );
			break;
		case ET_SPEAKER:
			G_Printf( "ET_SPEAKER          " );
			break;
		case ET_PUSH_TRIGGER:
			G_Printf( "ET_PUSH_TRIGGER     " );
			break;
		case ET_CONCUSSIVE_TRIGGER:
			G_Printf( "ET_CONCUSSIVE_TRIGGR" );
			break;
		case ET_TELEPORT_TRIGGER:
			G_Printf( "ET_TELEPORT_TRIGGER " );
			break;
		case ET_INVISIBLE:
			G_Printf( "ET_INVISIBLE        " );
			break;
		case ET_EXPLOSIVE:
			G_Printf( "ET_EXPLOSIVE        " );
			break;
		case ET_EF_SPOTLIGHT:
			G_Printf( "ET_EF_SPOTLIGHT     " );
			break;
		case ET_ALARMBOX:
			G_Printf( "ET_ALARMBOX          " );
			break;
		default:
			G_Printf( "%3i                 ", check->s.eType );
			break;
		}

		if ( check->classname ) {
			G_Printf( "%s", check->classname );
		}
		G_Printf( "\n" );
	}
}
Exemple #16
0
/*
===================
Svcmd_EntityList_f
===================
*/
void  Svcmd_EntityList_f( void )
{
  int       e;
  gentity_t *check;

  check = g_entities;

  for( e = 0; e < level.num_entities; e++, check++ )
  {
    if( !check->inuse )
      continue;

    G_Printf( "%3i:", e );

    switch( check->s.eType )
    {
      case ET_GENERAL:
        G_Printf( "ET_GENERAL          " );
        break;
      case ET_PLAYER:
        G_Printf( "ET_PLAYER           " );
        break;
      case ET_ITEM:
        G_Printf( "ET_ITEM             " );
        break;
      case ET_BUILDABLE:
        G_Printf( "ET_BUILDABLE        " );
        break;
      case ET_LOCATION:
        G_Printf( "ET_LOCATION         " );
        break;
      case ET_MISSILE:
        G_Printf( "ET_MISSILE          " );
        break;
      case ET_MOVER:
        G_Printf( "ET_MOVER            " );
        break;
      case ET_BEAM:
        G_Printf( "ET_BEAM             " );
        break;
      case ET_PORTAL:
        G_Printf( "ET_PORTAL           " );
        break;
      case ET_SPEAKER:
        G_Printf( "ET_SPEAKER          " );
        break;
      case ET_PUSH_TRIGGER:
        G_Printf( "ET_PUSH_TRIGGER     " );
        break;
      case ET_TELEPORT_TRIGGER:
        G_Printf( "ET_TELEPORT_TRIGGER " );
        break;
      case ET_INVISIBLE:
        G_Printf( "ET_INVISIBLE        " );
        break;
      case ET_GRAPPLE:
        G_Printf( "ET_GRAPPLE          " );
        break;
      case ET_CORPSE:
        G_Printf( "ET_CORPSE           " );
        break;
      case ET_PARTICLE_SYSTEM:
        G_Printf( "ET_PARTICLE_SYSTEM  " );
        break;
      case ET_ANIMMAPOBJ:
        G_Printf( "ET_ANIMMAPOBJ       " );
        break;
      case ET_MODELDOOR:
        G_Printf( "ET_MODELDOOR        " );
        break;
      case ET_LIGHTFLARE:
        G_Printf( "ET_LIGHTFLARE       " );
        break;
      case ET_LEV2_ZAP_CHAIN:
        G_Printf( "ET_LEV2_ZAP_CHAIN   " );
        break;
      default:
        G_Printf( "%-3i                 ", check->s.eType );
        break;
    }

    if( check->classname )
      G_Printf( "%s", check->classname );

    G_Printf( "\n" );
  }
}
Exemple #17
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 ) {
					const 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 ) {
			const 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 );
		}
	}
}
Exemple #18
0
void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
			   vec3_t dir, vec3_t point, int damage, int dflags, int mod ) {
	gclient_t	*client;
	int			take;
	int			save;
	int			asave;
	int			knockback;
	int			max;

	if (!targ->takedamage) {
		return;
	}

	//in entityplus bots cannot harm other bots (unless it's a telefrag)
	if ( IsBot( targ ) && attacker && IsBot( attacker ) && mod != MOD_TELEFRAG )
		return;

	//if attacker is shooter which was configured not to harm target, do nothing
	if ( attacker && strstr(attacker->classname, "shooter_" )) {
		if ( (attacker->spawnflags & 2) && IsBot( targ ) ) //spawnflags 2 == NO_BOTS
			return;
		if ( (attacker->spawnflags & 4) && !IsBot( targ ) ) //spawnflag 4 = NO_HUMANS
			return;
	}

	// the intermission has allready been qualified for, so don't
	// allow any extra scoring
	if ( level.intermissionQueued ) {
		return;
	}

	if ( !inflictor ) {
		inflictor = &g_entities[ENTITYNUM_WORLD];
	}
	if ( !attacker ) {
		attacker = &g_entities[ENTITYNUM_WORLD];
	}


	// shootable doors / buttons don't actually have any health
	if ( targ->s.eType == ET_MOVER ) {
		if ( strcmp(targ->classname, "func_breakable") && targ->use && (targ->moverState == MOVER_POS1 || targ->moverState == ROTATOR_POS1) ) {
			targ->use( targ, inflictor, attacker );
		} else {	// entity is a func_breakable
			if ( (targ->spawnflags & 1024) && attacker == level.player )
				return;
			if ( (targ->spawnflags & 2048) && IsBot(attacker) )
				return;
			if ( (targ->spawnflags & 4096) && strstr(attacker->classname, "shooter_") )
				return;
			
			if ( !strcmp(targ->classname, "func_breakable") ) {
				targ->health -= damage;
				if ( targ->health <= 0 )
					Break_Breakable(targ, attacker);
			}
		}
		return;
	}

	// scale back damage from bots or shooters to humans in single player, based on skill level
	// "I can win" does 0.05 dmg
	// "Bring it on" does 0.15 dmg
	// "Hurt me plenty" does 0.25 dmg
	// "Hardcore" does 0.35 dmg
	// "Nightmare does 0.45 dmg
	if ( 
		attacker && (
			IsBot(attacker) || 
			!strcmp(attacker->classname, "shooter_bfg") || 
			!strcmp(attacker->classname, "shooter_grenade") || 
			!strcmp(attacker->classname, "shooter_plasma") || 
			!strcmp(attacker->classname, "shooter_rocket") 
		)
	) {
		float skill = trap_Cvar_VariableValue( "g_spSkill" );
		int orgdmg = damage;

		if ( attacker->parent && attacker->parent->skill )
			skill += attacker->parent->skill;

		if (skill < 1)
			skill = 1;	//relative skill level should not drop below 1 but is allowed to rise above 5
		
		damage *= ( ( 0.1 * skill  ) - 0.05 ); //damage is always rounded down.
		
		if ( damage < 1 )
			damage = 1;	//make sure bot does at least -some- damage

		//G_Printf("skill: %f -- mp: %f -- orgdmg: %i -- dmg: %i\n", skill, ( 0.1 * skill  ) - 0.05, orgdmg, damage);
	}

	client = targ->client;

	if ( client ) {
		if ( client->noclip ) {
			return;
		}
	}

	if ( !dir ) {
		dflags |= DAMAGE_NO_KNOCKBACK;
	} else {
		VectorNormalize(dir);
	}

	knockback = damage;
	if ( knockback > 200 ) {
		knockback = 200;
	}
	if ( targ->flags & FL_NO_KNOCKBACK ) {
		knockback = 0;
	}
	if ( dflags & DAMAGE_NO_KNOCKBACK ) {
		knockback = 0;
	}

	// figure momentum add, even if the damage won't be taken
	if ( knockback && targ->client ) {
		vec3_t	kvel;
		float	mass;

		mass = 200;

		VectorScale (dir, g_knockback.value * (float)knockback / mass, kvel);
		VectorAdd (targ->client->ps.velocity, kvel, targ->client->ps.velocity);

		// set the timer so that the other client can't cancel
		// out the movement immediately
		if ( !targ->client->ps.pm_time ) {
			int		t;

			t = knockback * 2;
			if ( t < 50 ) {
				t = 50;
			}
			if ( t > 200 ) {
				t = 200;
			}
			targ->client->ps.pm_time = t;
			targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
		}
	}

	// check for completely getting out of the damage
	if ( !(dflags & DAMAGE_NO_PROTECTION) ) {

		// if TF_NO_FRIENDLY_FIRE is set, don't do damage to the target
		// if the attacker was on the same team
		if ( targ != attacker && OnSameTeam (targ, attacker)  ) {
			if ( !g_friendlyFire.integer ) {
				return;
			}
		}

		// check for godmode
		if ( targ->flags & FL_GODMODE ) {
			return;
		}
	}

	// battlesuit protects from all radius damage (but takes knockback)
	// and protects 50% against all damage
	if ( client && client->ps.powerups[PW_BATTLESUIT] ) {
		G_AddEvent( targ, EV_POWERUP_BATTLESUIT, 0 );
		if ( ( dflags & DAMAGE_RADIUS ) || ( mod == MOD_FALLING ) ) {
			return;
		}
		damage *= 0.5;
	}

	// add to the attacker's hit counter (if the target isn't a general entity like a prox mine)
	if ( attacker->client && targ != attacker && targ->health > 0
			&& targ->s.eType != ET_MISSILE
			&& targ->s.eType != ET_GENERAL) {
		if ( OnSameTeam( targ, attacker ) ) {
			attacker->client->ps.persistant[PERS_HITS]--;
		} else {
			attacker->client->ps.persistant[PERS_HITS]++;
		}
		attacker->client->ps.persistant[PERS_ATTACKEE_ARMOR] = (targ->health<<8)|(client->ps.stats[STAT_ARMOR]);
	}

	// always give half damage if hurting self
	// calculated after knockback, so rocket jumping works
	if ( targ == attacker) {
		damage *= 0.5;
	}

	if ( damage < 1 ) {
		damage = 1;
	}
	take = damage;
	save = 0;

	// save some from armor
	asave = CheckArmor (targ, take, dflags);
	take -= asave;

	if ( g_debugDamage.integer ) {
		G_Printf( "%i: client:%i health:%i damage:%i armor:%i\n", level.time, targ->s.number,
			targ->health, take, asave );
	}

	// add to the damage inflicted on a player this frame
	// the total will be turned into screen blends and view angle kicks
	// at the end of the frame
	if ( client ) {
		if ( attacker ) {
			client->ps.persistant[PERS_ATTACKER] = attacker->s.number;
		} else {
			client->ps.persistant[PERS_ATTACKER] = ENTITYNUM_WORLD;
		}
		client->damage_armor += asave;
		client->damage_blood += take;
		client->damage_knockback += knockback;
		if ( dir ) {
			VectorCopy ( dir, client->damage_from );
			client->damage_fromWorld = qfalse;
		} else {
			VectorCopy ( targ->r.currentOrigin, client->damage_from );
			client->damage_fromWorld = qtrue;
		}
	}

	if (targ->client) {
		// set the last client who damaged the target
		targ->client->lasthurt_client = attacker->s.number;
		targ->client->lasthurt_mod = mod;
	}

	// do the damage
	if (take) {
		if ( g_mutators.integer & MT_INSTAGIB && IsBot( targ ) )
			targ->health = -999;
		else
			targ->health = targ->health - take;

		if ( targ->client ) {
			targ->client->ps.stats[STAT_HEALTH] = targ->health;
		}
			
		if ( targ->health <= 0 ) {
			if ( client )
				targ->flags |= FL_NO_KNOCKBACK;

			if (targ->health < -999)
				targ->health = -999;

			targ->enemy = attacker;
			targ->die (targ, inflictor, attacker, take, mod);
			return;
		} else if ( targ->pain ) {
			targ->pain (targ, attacker, take);
		}
	}
}
Exemple #19
0
static bool G_asInitializeGametypeScript( asIScriptModule *asModule ) {
	int error;
	asIScriptContext *ctx;
	int funcCount;
	const char *fdeclstr;

	// grab script function calls
	funcCount = 0;

	fdeclstr = "void GT_InitGametype()";
	level.gametype.initFunc = asModule->GetFunctionByDecl( fdeclstr );
	if( !level.gametype.initFunc ) {
		G_Printf( "* The function '%s' was not found. Can not continue.\n", fdeclstr );
		return false;
	} else {
		funcCount++;
	}

	fdeclstr = "void GT_SpawnGametype()";
	level.gametype.spawnFunc = asModule->GetFunctionByDecl( fdeclstr );
	if( !level.gametype.spawnFunc ) {
		if( developer->integer || sv_cheats->integer ) {
			G_Printf( "* The function '%s' was not present in the script.\n", fdeclstr );
		}
	} else {
		funcCount++;
	}

	fdeclstr = "void GT_MatchStateStarted()";
	level.gametype.matchStateStartedFunc = asModule->GetFunctionByDecl( fdeclstr );
	if( !level.gametype.matchStateStartedFunc ) {
		if( developer->integer || sv_cheats->integer ) {
			G_Printf( "* The function '%s' was not present in the script.\n", fdeclstr );
		}
	} else {
		funcCount++;
	}

	fdeclstr = "bool GT_MatchStateFinished( int incomingMatchState )";
	level.gametype.matchStateFinishedFunc = asModule->GetFunctionByDecl( fdeclstr );
	if( !level.gametype.matchStateFinishedFunc ) {
		if( developer->integer || sv_cheats->integer ) {
			G_Printf( "* The function '%s' was not present in the script.\n", fdeclstr );
		}
	} else {
		funcCount++;
	}

	fdeclstr = "void GT_ThinkRules()";
	level.gametype.thinkRulesFunc = asModule->GetFunctionByDecl( fdeclstr );
	if( !level.gametype.thinkRulesFunc ) {
		if( developer->integer || sv_cheats->integer ) {
			G_Printf( "* The function '%s' was not present in the script.\n", fdeclstr );
		}
	} else {
		funcCount++;
	}

	fdeclstr = "void GT_PlayerRespawn( Entity @ent, int old_team, int new_team )";
	level.gametype.playerRespawnFunc = asModule->GetFunctionByDecl( fdeclstr );
	if( !level.gametype.playerRespawnFunc ) {
		if( developer->integer || sv_cheats->integer ) {
			G_Printf( "* The function '%s' was not present in the script.\n", fdeclstr );
		}
	} else {
		funcCount++;
	}

	fdeclstr = "void GT_ScoreEvent( Client @client, const String &score_event, const String &args )";
	level.gametype.scoreEventFunc = asModule->GetFunctionByDecl( fdeclstr );
	if( !level.gametype.scoreEventFunc ) {
		if( developer->integer || sv_cheats->integer ) {
			G_Printf( "* The function '%s' was not present in the script.\n", fdeclstr );
		}
	} else {
		funcCount++;
	}

	fdeclstr = "String @GT_ScoreboardMessage( uint maxlen )";
	level.gametype.scoreboardMessageFunc = asModule->GetFunctionByDecl( fdeclstr );
	if( !level.gametype.scoreboardMessageFunc ) {
		if( developer->integer || sv_cheats->integer ) {
			G_Printf( "* The function '%s' was not present in the script.\n", fdeclstr );
		}
	} else {
		funcCount++;
	}

	fdeclstr = "Entity @GT_SelectSpawnPoint( Entity @ent )";
	level.gametype.selectSpawnPointFunc = asModule->GetFunctionByDecl( fdeclstr );
	if( !level.gametype.selectSpawnPointFunc ) {
		if( developer->integer || sv_cheats->integer ) {
			G_Printf( "* The function '%s' was not present in the script.\n", fdeclstr );
		}
	} else {
		funcCount++;
	}

	fdeclstr = "bool GT_Command( Client @client, const String &cmdString, const String &argsString, int argc )";
	level.gametype.clientCommandFunc = asModule->GetFunctionByDecl( fdeclstr );
	if( !level.gametype.clientCommandFunc ) {
		if( developer->integer || sv_cheats->integer ) {
			G_Printf( "* The function '%s' was not present in the script.\n", fdeclstr );
		}
	} else {
		funcCount++;
	}

	fdeclstr = "void GT_Shutdown()";
	level.gametype.shutdownFunc = asModule->GetFunctionByDecl( fdeclstr );
	if( !level.gametype.shutdownFunc ) {
		if( developer->integer || sv_cheats->integer ) {
			G_Printf( "* The function '%s' was not present in the script.\n", fdeclstr );
		}
	} else {
		funcCount++;
	}

	//
	// Initialize AI gametype exports
	//
	AI_InitGametypeScript( asModule );

	//
	// execute the GT_InitGametype function
	//

	ctx = game.asExport->asAcquireContext( GAME_AS_ENGINE() );

	error = ctx->Prepare( static_cast<asIScriptFunction *>( level.gametype.initFunc ) );
	if( error < 0 ) {
		return false;
	}

	error = ctx->Execute();
	if( G_ExecutionErrorReport( error ) ) {
		return false;
	}

	return true;
}
Exemple #20
0
void GClip_LinkEntity( edict_t *ent )
{
	areanode_t *node;
	int leafs[MAX_TOTAL_ENT_LEAFS];
	int clusters[MAX_TOTAL_ENT_LEAFS];
	int num_leafs;
	int i, j, k;
	int area;
	int topnode;

	if( ent->r.area.prev )
		GClip_UnlinkEntity( ent ); // unlink from old position

	if( ent == game.edicts )
		return; // don't add the world

	if( !ent->r.inuse )
		return;

	// set the size
	VectorSubtract( ent->r.maxs, ent->r.mins, ent->r.size );

	if( ent->r.solid == SOLID_NOT || ( ent->r.svflags & SVF_PROJECTILE ) )
	{
		ent->s.solid = 0;
	}
	else if( ISBRUSHMODEL( ent->s.modelindex ) )
	{
		// the only predicted SOLID_TRIGGER entity is ET_PUSH_TRIGGER
		if( ent->r.solid != SOLID_TRIGGER || ent->s.type == ET_PUSH_TRIGGER )
			ent->s.solid = SOLID_BMODEL;
		else
			ent->s.solid = 0;
	}
	else // encode the size into the entity_state for client prediction
	{
		if( ent->r.solid == SOLID_TRIGGER )
		{
			ent->s.solid = 0;
		}
		else
		{
			// assume that x/y are equal and symetric
			i = ent->r.maxs[0]/8;
			clamp( i, 1, 31 );

			// z is not symetric
			j = ( -ent->r.mins[2] )/8;
			clamp( j, 1, 31 );

			// and z maxs can be negative...
			k = ( ent->r.maxs[2]+32 )/8;
			clamp( k, 1, 63 );

			ent->s.solid = ( k<<10 ) | ( j<<5 ) | i;
		}
	}

	// set the abs box
	if( ISBRUSHMODEL( ent->s.modelindex ) &&
		( ent->s.angles[0] || ent->s.angles[1] || ent->s.angles[2] ) )
	{ 
		// expand for rotation
		float radius;

		radius = RadiusFromBounds( ent->r.mins, ent->r.maxs );

		for( i = 0; i < 3; i++ )
		{
			ent->r.absmin[i] = ent->s.origin[i] - radius;
			ent->r.absmax[i] = ent->s.origin[i] + radius;
		}
	}
	else // axis aligned
	{ 
		VectorAdd( ent->s.origin, ent->r.mins, ent->r.absmin );
		VectorAdd( ent->s.origin, ent->r.maxs, ent->r.absmax );
	}

	// because movement is clipped an epsilon away from an actual edge,
	// we must fully check even when bounding boxes don't quite touch
	ent->r.absmin[0] -= 1;
	ent->r.absmin[1] -= 1;
	ent->r.absmin[2] -= 1;
	ent->r.absmax[0] += 1;
	ent->r.absmax[1] += 1;
	ent->r.absmax[2] += 1;

	// link to PVS leafs
	ent->r.num_clusters = 0;
	ent->r.areanum = ent->r.areanum2 = -1;

	// get all leafs, including solids
	num_leafs = trap_CM_BoxLeafnums( ent->r.absmin, ent->r.absmax,
		leafs, MAX_TOTAL_ENT_LEAFS, &topnode );

	// set areas
	for( i = 0; i < num_leafs; i++ )
	{
		clusters[i] = trap_CM_LeafCluster( leafs[i] );
		area = trap_CM_LeafArea( leafs[i] );
		if( area > -1 )
		{
			// doors may legally straggle two areas,
			// but nothing should ever need more than that
			if( ent->r.areanum > -1 && ent->r.areanum != area )
			{
				if( ent->r.areanum2 > -1 && ent->r.areanum2 != area )
				{
					if( developer->integer )
						G_Printf( "Object %s touching 3 areas at %f %f %f\n",
						( ent->classname ? ent->classname : "" ),
						ent->r.absmin[0], ent->r.absmin[1], ent->r.absmin[2] );
				}
				ent->r.areanum2 = area;
			}
			else
				ent->r.areanum = area;
		}
	}

	if( num_leafs >= MAX_TOTAL_ENT_LEAFS )
	{ // assume we missed some leafs, and mark by headnode
		ent->r.num_clusters = -1;
		ent->r.headnode = topnode;
	}
	else
	{
		ent->r.num_clusters = 0;
		for( i = 0; i < num_leafs; i++ )
		{
			if( clusters[i] == -1 )
				continue; // not a visible leaf
			for( j = 0; j < i; j++ )
				if( clusters[j] == clusters[i] )
					break;
			if( j == i )
			{
				if( ent->r.num_clusters == MAX_ENT_CLUSTERS )
				{
					// assume we missed some leafs, and mark by headnode
					ent->r.num_clusters = -1;
					ent->r.headnode = topnode;
					break;
				}

				ent->r.clusternums[ent->r.num_clusters++] = clusters[i];
			}
		}
	}

	// if first time, make sure old_origin is valid
	if( !ent->r.linkcount && !( ent->r.svflags & SVF_TRANSMITORIGIN2 ) )
	{
		VectorCopy( ent->s.origin, ent->s.old_origin );
		ent->olds = ent->s;
	}
	ent->r.linkcount++;
	ent->linked = qtrue;

	if( ent->r.solid == SOLID_NOT )
		return;

	// find the first node that the ent's box crosses
	node = sv_areanodes;
	while( 1 )
	{
		if( node->axis == -1 )
			break;
		if( ent->r.absmin[node->axis] > node->dist )
			node = node->children[0];
		else if( ent->r.absmax[node->axis] < node->dist )
			node = node->children[1];
		else
			break; // crosses the node
	}

	// link it in
	if( ent->r.solid == SOLID_TRIGGER )
		GClip_InsertLinkBefore( &ent->r.area, &node->trigger_edicts, NUM_FOR_EDICT( ent ) );
	else
		GClip_InsertLinkBefore( &ent->r.area, &node->solid_edicts, NUM_FOR_EDICT( ent ) );
}
Exemple #21
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 );
}
Exemple #22
0
/*
* GClip_AreaEdicts
* fills in a table of edict ids with edicts that have bounding boxes
* that intersect the given area.  It is possible for a non-axial bmodel
* to be returned that doesn't actually intersect the area on an exact
* test.
* returns the number of pointers filled in
* ??? does this always return the world?
*/
static int GClip_AreaEdicts( vec3_t mins, vec3_t maxs, int *list, int maxcount, int areatype, int timeDelta )
{
	link_t *l, *start;
	c4clipedict_t *clipEnt;
	int stackdepth = 0, count = 0;
	areanode_t *localstack[AREA_NODES], *node = sv_areanodes;

	while( 1 )
	{
		// touch linked edicts
		if( areatype == AREA_SOLID )
			start = &node->solid_edicts;
		else
			start = &node->trigger_edicts;

		for( l = start->next; l != start; l = l->next )
		{
			clipEnt = GClip_GetClipEdictForDeltaTime( l->entNum, timeDelta );

			if( clipEnt->r.solid == SOLID_NOT )
				continue; // deactivated

			if( !BoundsIntersect( clipEnt->r.absmin, clipEnt->r.absmax, mins, maxs ) )
				continue; // not touching

			if( count == maxcount )
			{
				G_Printf( "G_AreaEdicts: MAXCOUNT\n" );
				return count;
			}
			list[count++] = l->entNum;
		}

		if( node->axis == -1 )
			goto checkstack; // terminal node

		// recurse down both sides
		if( maxs[node->axis] > node->dist )
		{
			if( mins[node->axis] < node->dist )
			{
				localstack[stackdepth++] = node->children[0];
				node = node->children[1];
				continue;
			}
			node = node->children[0];
			continue;
		}
		if( mins[node->axis] < node->dist )
		{
			node = node->children[1];
			continue;
		}

checkstack:
		if( !stackdepth )
			return count;
		node = localstack[--stackdepth];
	}

	return count;
}
Exemple #23
0
void Svcmd_GameMem_f( void ) {
	G_Printf( "Game memory status: %i out of %i bytes allocated\n", allocPoint, POOLSIZE );
}
Exemple #24
0
qboolean G_Damage(gentity_t * targ, gentity_t * inflictor, gentity_t * attacker,
				  const vec3_t dir, const vec3_t point, int damage, int dflags, int mod)
{
	gclient_t      *client;
	int             take;
	int             save;
	int             asave;
	int             knockback;
	int             max;

#ifdef MISSIONPACK
	vec3_t          bouncedir, impactpoint;
#endif

	if(!inflictor)
	{
		inflictor = &g_entities[ENTITYNUM_WORLD];
	}

	if(!attacker)
	{
		attacker = &g_entities[ENTITYNUM_WORLD];
	}

#ifdef G_LUA
	// Lua API callbacks
	if(targ->luaHurt && !targ->client)
	{
		G_LuaHook_EntityHurt(targ->luaHurt, targ->s.number, inflictor->s.number, attacker->s.number);
	}
#endif

	if(!targ->takedamage)
	{
		return qfalse;
	}

	// the intermission has allready been qualified for, so don't
	// allow any extra scoring
	if(level.intermissionQueued)
	{
		return qfalse;
	}
#ifdef MISSIONPACK
	if(targ->client && mod != MOD_JUICED)
	{
		if(targ->client->invulnerabilityTime > level.time)
		{
			if(dir && point)
			{
				G_InvulnerabilityEffect(targ, dir, point, impactpoint, bouncedir);
			}
			return qfalse;
		}
	}
#endif

	// shootable doors / buttons don't actually have any health
	if(targ->s.eType == ET_MOVER)
	{
		if(targ->use && targ->moverState == MOVER_POS1)
		{
			targ->use(targ, inflictor, attacker);
		}
		return qfalse;
	}

	if(g_gametype.integer == GT_OBELISK && CheckObeliskAttack(targ, attacker))
	{
		return qfalse;
	}

	// reduce damage by the attacker's handicap value
	// unless they are rocket jumping
	if(attacker->client && attacker != targ)
	{
		max = attacker->client->ps.stats[STAT_MAX_HEALTH];
#ifdef MISSIONPACK
		if(bg_itemlist[attacker->client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD)
		{
			max /= 2;
		}
#endif
		damage = damage * max / 100;
	}

	client = targ->client;

	if(client)
	{
		if(client->noclip)
		{
			return qfalse;
		}
	}

	if(!dir)
	{
		dflags |= DAMAGE_NO_KNOCKBACK;
	}
	else
	{
		VectorNormalize((float *)dir);
	}

	knockback = damage;
	if(knockback > 200)
	{
		knockback = 200;
	}
	if(targ->flags & FL_NO_KNOCKBACK)
	{
		knockback = 0;
	}
	if(dflags & DAMAGE_NO_KNOCKBACK)
	{
		knockback = 0;
	}

	// figure momentum add, even if the damage won't be taken
	if(knockback && targ->client)
	{
		vec3_t          kvel;
		float           mass;

		mass = 200;

		VectorScale(dir, g_knockback.value * (float)knockback / mass, kvel);
		VectorAdd(targ->client->ps.velocity, kvel, targ->client->ps.velocity);

		// set the timer so that the other client can't cancel
		// out the movement immediately
		if(!targ->client->ps.pm_time)
		{
			int             t;

			t = knockback * 2;
			if(t < 50)
			{
				t = 50;
			}
			if(t > 200)
			{
				t = 200;
			}
			targ->client->ps.pm_time = t;
			targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
		}
	}

	if(attacker->s.weapon == WP_RAILGUN && targ->s.eType == ET_PROJECTILE && targ->s.weapon == WP_RAILGUN)
	{
		// Tr3B: added this special case to shoot railgun spheres
		// railgun spheres can be shot by any raigun user
	}
	// check for completely getting out of the damage
	else if(!(dflags & DAMAGE_NO_PROTECTION))
	{
		// if TF_NO_FRIENDLY_FIRE is set, don't do damage to the target
		// if the attacker was on the same team
#ifdef MISSIONPACK
		if(mod != MOD_JUICED && targ != attacker && !(dflags & DAMAGE_NO_TEAM_PROTECTION) && OnSameTeam(targ, attacker))
		{
#else
		if(targ != attacker && OnSameTeam(targ, attacker))
		{
#endif
			if(!g_friendlyFire.integer)
			{
				return qfalse;
			}
		}
#ifdef MISSIONPACK
		if(mod == MOD_PROXIMITY_MINE)
		{
			if(inflictor && inflictor->parent && OnSameTeam(targ, inflictor->parent))
			{
				return qfalse;
			}
			if(targ == attacker)
			{
				return qfalse;
			}
		}
#endif

		// check for godmode
		if(targ->flags & FL_GODMODE)
		{
			return qfalse;
		}
	}

	// battlesuit protects from all radius damage (but takes knockback)
	// and protects 50% against all damage
	if(client && client->ps.powerups[PW_BATTLESUIT])
	{
		G_AddEvent(targ, EV_POWERUP_BATTLESUIT, 0);
		if((dflags & DAMAGE_RADIUS) || (mod == MOD_FALLING))
		{
			return qfalse;
		}
		damage *= 0.5;
	}

	// add to the attacker's hit counter (if the target isn't a general entity like a prox mine)
	if(attacker->client && targ->client && targ != attacker && targ->health > 0 && targ->s.eType != ET_PROJECTILE && targ->s.eType != ET_PROJECTILE2 && targ->s.eType != ET_GENERAL)
	{
		if(OnSameTeam(targ, attacker))
		{
			attacker->client->ps.persistant[PERS_HITS]--;
		}
		else
		{
			attacker->client->ps.persistant[PERS_HITS]++;
		}

		attacker->client->ps.persistant[PERS_ATTACKEE_ARMOR] = (targ->health << 8) | (targ->client->ps.stats[STAT_ARMOR]);
	}

	// always give half damage if hurting self
	// calculated after knockback, so rocket jumping works
	if(targ == attacker)
	{
		damage *= 0.5;
	}

	if(damage < 1)
	{
		damage = 1;
	}
	take = damage;
	save = 0;

	// save some from armor
	asave = CheckArmor(targ, take, dflags);
	take -= asave;

	if(g_debugDamage.integer)
	{
		G_Printf("%i: client:%i health:%i damage:%i armor:%i\n", level.time, targ->s.number, targ->health, take, asave);
	}

	// add to the damage inflicted on a player this frame
	// the total will be turned into screen blends and view angle kicks
	// at the end of the frame
	if(client)
	{
		if(attacker)
		{
			client->ps.persistant[PERS_ATTACKER] = attacker->s.number;
		}
		else
		{
			client->ps.persistant[PERS_ATTACKER] = ENTITYNUM_WORLD;
		}

		client->damage_armor += asave;
		client->damage_blood += take;
		client->damage_knockback += knockback;

		if(dir)
		{
			VectorCopy(dir, client->damage_from);
			client->damage_fromWorld = qfalse;
		}
		else
		{
			VectorCopy(targ->r.currentOrigin, client->damage_from);
			client->damage_fromWorld = qtrue;
		}
	}

	// See if it's the player hurting the emeny flag carrier
	if(g_gametype.integer == GT_CTF || g_gametype.integer == GT_1FCTF)
	{
		Team_CheckHurtCarrier(targ, attacker);
	}

	if(targ->client)
	{
		// set the last client who damaged the target
		targ->client->lasthurt_client = attacker->s.number;
		targ->client->lasthurt_mod = mod;
	}

	// do the damage
	if(take)
	{
		targ->health = targ->health - take;
		if(targ->client)
		{
			targ->client->ps.stats[STAT_HEALTH] = targ->health;
		}

		if(targ->health <= 0)
		{
			if(client)
				targ->flags |= FL_NO_KNOCKBACK;

			if(targ->health < -999)
				targ->health = -999;

			targ->enemy = attacker;


#ifdef G_LUA
			// Lua API callbacks
			if(targ->luaDie && !targ->client)
			{
				G_LuaHook_EntityDie(targ->luaDie, targ->s.number, inflictor->s.number, attacker->s.number, take, mod);
			}
#endif

			targ->die(targ, inflictor, attacker, take, mod);

			return qfalse;
		}
		else if(targ->pain)
		{
			targ->pain(targ, attacker, take);
		}
	}

	return qfalse;
}


/*
============
CanDamage

Returns qtrue if the inflictor can directly damage the target.  Used for
explosions and melee attacks.
============
*/
qboolean CanDamage(gentity_t * targ, vec3_t origin)
{
	vec3_t          dest;
	trace_t         tr;
	vec3_t          midpoint;

	// use the midpoint of the bounds instead of the origin, because
	// bmodels may have their origin is 0,0,0
	VectorAdd(targ->r.absmin, targ->r.absmax, midpoint);
	VectorScale(midpoint, 0.5, midpoint);

	VectorCopy(midpoint, dest);
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
	if(tr.fraction == 1.0 || tr.entityNum == targ->s.number)
		return qtrue;

	// this should probably check in the plane of projection,
	// rather than in world coordinate, and also include Z
	VectorCopy(midpoint, dest);
	dest[0] += 15.0;
	dest[1] += 15.0;
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
	if(tr.fraction == 1.0)
		return qtrue;

	VectorCopy(midpoint, dest);
	dest[0] += 15.0;
	dest[1] -= 15.0;
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
	if(tr.fraction == 1.0)
		return qtrue;

	VectorCopy(midpoint, dest);
	dest[0] -= 15.0;
	dest[1] += 15.0;
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
	if(tr.fraction == 1.0)
		return qtrue;

	VectorCopy(midpoint, dest);
	dest[0] -= 15.0;
	dest[1] -= 15.0;
	trap_Trace(&tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID);
	if(tr.fraction == 1.0)
		return qtrue;


	return qfalse;
}
Exemple #25
0
/*
================
FinishSpawningItem

Traces down to find where an item should rest, instead of letting them
free fall from their spawn points
================
*/
void FinishSpawningItem( gentity_t *ent ) {
	trace_t tr;
	vec3_t dest;
	vec3_t maxs;

	if ( ent->spawnflags & 1 ) { // suspended
		VectorSet( ent->r.mins, -ITEM_RADIUS, -ITEM_RADIUS, -ITEM_RADIUS );
		VectorSet( ent->r.maxs, ITEM_RADIUS, ITEM_RADIUS, ITEM_RADIUS );
		VectorCopy( ent->r.maxs, maxs );
	} else
	{
		// Rafael
		// had to modify this so that items would spawn in shelves
		VectorSet( ent->r.mins, -ITEM_RADIUS, -ITEM_RADIUS, 0 );
		VectorSet( ent->r.maxs, ITEM_RADIUS, ITEM_RADIUS, ITEM_RADIUS );
		VectorCopy( ent->r.maxs, maxs );
		maxs[2] /= 2;
	}

	ent->r.contents = CONTENTS_TRIGGER | CONTENTS_ITEM;
	ent->touch = Touch_Item_Auto;
	ent->s.eType = ET_ITEM;
	ent->s.modelindex = ent->item - bg_itemlist;        // store item number in modelindex

	ent->s.otherEntityNum2 = 0;     // DHM - Nerve :: takes modelindex2's place in signaling a dropped item
//----(SA)	we don't use this (yet, anyway) so I'm taking it so you can specify a model for treasure items and clipboards
//	ent->s.modelindex2 = 0; // zero indicates this isn't a dropped item
	if ( ent->model ) {
		ent->s.modelindex2 = G_ModelIndex( ent->model );
	}


	// if clipboard, add the menu name string to the client's configstrings
	if ( ent->item->giType == IT_CLIPBOARD ) {
		if ( !ent->message ) {
			ent->s.density = G_FindConfigstringIndex( "clip_test", CS_CLIPBOARDS, MAX_CLIPBOARD_CONFIGSTRINGS, qtrue );
		} else {
			ent->s.density = G_FindConfigstringIndex( ent->message, CS_CLIPBOARDS, MAX_CLIPBOARD_CONFIGSTRINGS, qtrue );
		}

		ent->touch = Touch_Item;    // no auto-pickup, only activate
	} else if ( ent->item->giType == IT_HOLDABLE )      {
		if ( ent->item->giTag >= HI_BOOK1 && ent->item->giTag <= HI_BOOK3 ) {
			G_FindConfigstringIndex( va( "hbook%d", ent->item->giTag - HI_BOOK1 ), CS_CLIPBOARDS, MAX_CLIPBOARD_CONFIGSTRINGS, qtrue );
		}
		ent->touch = Touch_Item;    // no auto-pickup, only activate
	}


//----(SA)	added
	if ( ent->item->giType == IT_TREASURE ) {
		ent->touch = Touch_Item;    // no auto-pickup, only activate
	}
//----(SA)	end

	// using an item causes it to respawn
	ent->use = Use_Item;

//----(SA) moved this up so it happens for suspended items too (and made it a function)
	G_SetAngle( ent, ent->s.angles );

	if ( ent->spawnflags & 1 ) {    // suspended
		G_SetOrigin( ent, ent->s.origin );
	} else {

		VectorSet( dest, ent->s.origin[0], ent->s.origin[1], ent->s.origin[2] - 4096 );
		trap_Trace( &tr, ent->s.origin, ent->r.mins, maxs, dest, ent->s.number, MASK_SOLID );

		if ( tr.startsolid ) {
			vec3_t temp;

			VectorCopy( ent->s.origin, temp );
			temp[2] -= ITEM_RADIUS;

			VectorSet( dest, ent->s.origin[0], ent->s.origin[1], ent->s.origin[2] - 4096 );
			trap_Trace( &tr, temp, ent->r.mins, maxs, dest, ent->s.number, MASK_SOLID );
		}

#if 0
		// drop to floor
		VectorSet( dest, ent->s.origin[0], ent->s.origin[1], ent->s.origin[2] - 4096 );
		trap_Trace( &tr, ent->s.origin, ent->r.mins, maxs, dest, ent->s.number, MASK_SOLID );
#endif
		if ( tr.startsolid ) {
			G_Printf( "FinishSpawningItem: %s startsolid at %s\n", ent->classname, vtos( ent->s.origin ) );
			G_FreeEntity( ent );
			return;
		}

		// allow to ride movers
		ent->s.groundEntityNum = tr.entityNum;

		G_SetOrigin( ent, tr.endpos );
	}

	if ( ent->spawnflags & 2 ) {      // spin
		ent->s.eFlags |= EF_SPINNING;
	}


	// team slaves and targeted items aren't present at start
	if ( ( ent->flags & FL_TEAMSLAVE ) || ent->targetname ) {
		ent->flags |= FL_NODRAW;
		//ent->s.eFlags |= EF_NODRAW;
		ent->r.contents = 0;
		return;
	}

	// health/ammo can potentially be multi-stage (multiple use)
	if ( ent->item->giType == IT_HEALTH || ent->item->giType == IT_AMMO || ent->item->giType == IT_POWERUP ) {
		int i;

		// having alternate models defined in bg_misc.c for a health or ammo item specify it as "multi-stage"
		// TTimo left-hand operand of comma expression has no effect
		// initial line: for(i=0;i<4,ent->item->world_model[i];i++) {}
		for ( i = 0; i < 4 && ent->item->world_model[i] ; i++ ) {}

		ent->s.density = i - 1;   // store number of stages in 'density' for client (most will have '1')
	}

	// powerups don't spawn in for a while
	if ( ent->item->giType == IT_POWERUP && g_gametype.integer != GT_SINGLE_PLAYER ) {
		float respawn;

		respawn = 45 + crandom() * 15;
		ent->flags |= FL_NODRAW;
		//ent->s.eFlags |= EF_NODRAW;
		ent->r.contents = 0;
		ent->nextthink = level.time + respawn * 1000;
		ent->think = RespawnItem;
		return;
	}

	trap_LinkEntity( ent );
}
Exemple #26
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;
	}
}
Exemple #27
0
STATIC_INLINE void PrintEntityOverviewLine( gentity_t *entity )
{
	G_Printf( "%3i: %15s/" S_COLOR_CYAN "%-24s" S_COLOR_WHITE "%s%s\n",
			entity->s.number, Com_EntityTypeName( entity->s.eType ), entity->classname,
			entity->names[0] ? entity->names[0] : "", entity->names[1] ? " …" : "");
}
Exemple #28
0
/*
=================
ConsoleCommand

=================
*/
qboolean    ConsoleCommand( void ) {
	char cmd[MAX_TOKEN_CHARS];

	trap_Argv( 0, cmd, sizeof( cmd ) );

#ifdef SAVEGAME_SUPPORT
	if ( Q_stricmp( cmd, "savegame" ) == 0 ) {

		if ( g_gametype.integer != GT_SINGLE_PLAYER ) {
			return qtrue;
		}

		// don't allow a manual savegame command while we are waiting for the game to start/exit
		if ( g_reloading.integer ) {
			return qtrue;
		}
		if ( saveGamePending ) {
			return qtrue;
		}

		trap_Argv( 1, cmd, sizeof( cmd ) );
		if ( strlen( cmd ) > 0 ) {
			// strip the extension if provided
			if ( strrchr( cmd, '.' ) ) {
				cmd[strrchr( cmd,'.' ) - cmd] = '\0';
			}
			if ( !Q_stricmp( cmd, "current" ) ) {     // beginning of map
				Com_Printf( "sorry, '%s' is a reserved savegame name.  please use another name.\n", cmd );
				return qtrue;
			}

			if ( G_SaveGame( cmd ) ) {
				trap_SendServerCommand( -1, "cp \"Game Saved\n\"" );  // deletedgame
			} else {
				G_Printf( "Unable to save game.\n" );
			}

		} else {    // need a name
			G_Printf( "syntax: savegame <name>\n" );
		}

		return qtrue;
	}
#endif // SAVEGAME_SUPPORT

	if ( Q_stricmp( cmd, "entitylist" ) == 0 ) {
		Svcmd_EntityList_f();
		return qtrue;
	}

	if ( Q_stricmp( cmd, "forceteam" ) == 0 ) {
		Svcmd_ForceTeam_f();
		return qtrue;
	}

	if ( Q_stricmp( cmd, "game_memory" ) == 0 ) {
		Svcmd_GameMem_f();
		return qtrue;
	}

	/*if (Q_stricmp (cmd, "addbot") == 0) {
		Svcmd_AddBot_f();
		return qtrue;
	}
	if (Q_stricmp (cmd, "removebot") == 0) {
		Svcmd_AddBot_f();
		return qtrue;
	}*/
	if ( Q_stricmp( cmd, "addip" ) == 0 ) {
		Svcmd_AddIP_f();
		return qtrue;
	}

	if ( Q_stricmp( cmd, "removeip" ) == 0 ) {
		Svcmd_RemoveIP_f();
		return qtrue;
	}

	if ( Q_stricmp( cmd, "listip" ) == 0 ) {
		trap_SendConsoleCommand( EXEC_INSERT, "g_banIPs\n" );
		return qtrue;
	}

	if ( Q_stricmp( cmd, "listmaxlivesip" ) == 0 ) {
		PrintMaxLivesGUID();
		return qtrue;
	}

	// NERVE - SMF
	if ( Q_stricmp( cmd, "start_match" ) == 0 ) {
		Svcmd_StartMatch_f();
		return qtrue;
	}

	if ( Q_stricmp( cmd, "reset_match" ) == 0 ) {
		Svcmd_ResetMatch_f( qtrue, qtrue );
		return qtrue;
	}

	if ( Q_stricmp( cmd, "swap_teams" ) == 0 ) {
		Svcmd_SwapTeams_f();
		return qtrue;
	}

	if ( Q_stricmp( cmd, "shuffle_teams" ) == 0 ) {
		Svcmd_ShuffleTeams_f();
		return qtrue;
	}

	// -NERVE - SMF

	if ( Q_stricmp( cmd, "makeReferee" ) == 0 ) {
		G_MakeReferee();
		return qtrue;
	}

	if ( Q_stricmp( cmd, "removeReferee" ) == 0 ) {
		G_RemoveReferee();
		return qtrue;
	}

	/*if (Q_stricmp (cmd, "mute") == 0) {
		G_MuteClient();
		return qtrue;
	}

	if (Q_stricmp (cmd, "unmute") == 0) {
		G_UnMuteClient();
		return qtrue;
	}*/

	if ( Q_stricmp( cmd, "ban" ) == 0 ) {
		G_PlayerBan();
		return qtrue;
	}

	if ( Q_stricmp( cmd, "campaign" ) == 0 ) {
		Svcmd_Campaign_f();
		return qtrue;
	}

	if ( Q_stricmp( cmd, "listcampaigns" ) == 0 ) {
		Svcmd_ListCampaigns_f();
		return qtrue;
	}

	if ( Q_stricmp( cmd, "spawnbot" ) == 0 ) {
		Svcmd_SpawnBot();
		return qtrue;
	}


// START - Mad Doc - TDF
	if ( Q_stricmp( cmd, "revive" ) == 0 ) {
		trap_Argv( 1, cmd, sizeof( cmd ) );
		Svcmd_RevivePlayer( cmd );
		return qtrue;
	}
// END - Mad Doc - TDF

	// fretn - moved from engine
	if ( !Q_stricmp( cmd, "kick" ) ) {
		Svcmd_Kick_f();
		return qtrue;
	}

	if ( !Q_stricmp( cmd, "clientkick" ) ) {
		Svcmd_KickNum_f();
		return qtrue;
	}
	// -fretn

	if ( g_dedicated.integer ) {
		if ( !Q_stricmp( cmd, "say" ) ) {
			trap_SendServerCommand( -1, va( "cpm \"server: %s\n\"", ConcatArgs( 1 ) ) );
			return qtrue;
		}

		// OSP - console also gets ref commands
		if ( !level.fLocalHost && Q_stricmp( cmd, "ref" ) == 0 ) {
			if ( !G_refCommandCheck( NULL, cmd ) ) {
				G_refHelp_cmd( NULL );
			}
			return( qtrue );
		}

		// everything else will also be printed as a say command
//		trap_SendServerCommand( -1, va("cpm \"server: %s\n\"", ConcatArgs(0) ) );

		// prints to the console instead now
		return qfalse;
	}

	return qfalse;
}
Exemple #29
0
static c4clipedict_t *GClip_GetClipEdictForDeltaTime( int entNum, int deltaTime )
{
	static int index = 0;
	static c4clipedict_t clipEnts[8];
	static c4clipedict_t *clipent;
	static c4clipedict_t clipentNewer; // for interpolation
	c4frame_t *cframe = NULL;
	unsigned int backTime, cframenum, bf, i;
	edict_t	*ent = game.edicts + entNum;

	// pick one of the 8 slots to prevent overwritings
	clipent = &clipEnts[index];
	index = ( index + 1 )&7;

	if( !entNum || deltaTime >= 0 || !g_antilag->integer )
	{                                                    // current time entity
		clipent->r = ent->r;
		clipent->s = ent->s;
		return clipent;
	}

	if( !ent->r.inuse || ent->r.solid == SOLID_NOT 
		|| ( ent->r.solid == SOLID_TRIGGER && !(entNum >= 1 && entNum <= gs.maxclients) ) )
	{
		clipent->r = ent->r;
		clipent->s = ent->s;
		return clipent;
	}

	// clamp delta time inside the backed up limits
	backTime = abs( deltaTime );
	if( g_antilag_maxtimedelta->integer )
	{
		if( g_antilag_maxtimedelta->integer < 0 )
			trap_Cvar_SetValue( "g_antilag_maxtimedelta", abs( g_antilag_maxtimedelta->integer ) );
		if( backTime > (unsigned int)g_antilag_maxtimedelta->integer )
			backTime = (unsigned int)g_antilag_maxtimedelta->integer;
	}

	// find the first snap with timestamp < than realtime - backtime
	cframenum = sv_collisionFrameNum;
	for( bf = 1; bf < CFRAME_UPDATE_BACKUP && bf < sv_collisionFrameNum; bf++ ) // never overpass limits
	{
		cframe = &sv_collisionframes[( cframenum-bf ) & CFRAME_UPDATE_MASK];

		// if solid has changed, we can't keep moving backwards
		if( ent->r.solid != cframe->clipEdicts[entNum].r.solid 
			|| ent->r.inuse != cframe->clipEdicts[entNum].r.inuse )
		{
			bf--;
			if( bf == 0 )
			{
				// we can't step back from first
				cframe = NULL;
			}
			else
			{
				cframe = &sv_collisionframes[( cframenum-bf ) & CFRAME_UPDATE_MASK];
			}
			break;
		}

		if( game.serverTime >= cframe->timestamp + backTime )
			break;
	}

	if( !cframe )
	{
		// current time entity
		clipent->r = ent->r;
		clipent->s = ent->s;
		return clipent;
	}

	// setup with older for the data that is not interpolated
	*clipent = cframe->clipEdicts[entNum];

	// if we found an older than desired backtime frame, interpolate to find a more precise position.
	if( game.serverTime > cframe->timestamp+backTime )
	{
		float lerpFrac;

		if( bf == 1 )
		{
			// interpolate from 1st backed up to current
			lerpFrac = (float)( ( game.serverTime - backTime ) - cframe->timestamp ) 
				/ (float)( game.serverTime - cframe->timestamp );
			clipentNewer.r = ent->r;
			clipentNewer.s = ent->s;
		}
		else
		{
			// interpolate between 2 backed up
			c4frame_t *cframeNewer = &sv_collisionframes[( cframenum-( bf-1 ) ) & CFRAME_UPDATE_MASK];
			lerpFrac = (float)( ( game.serverTime - backTime ) - cframe->timestamp ) 
				/ (float)( cframeNewer->timestamp - cframe->timestamp );
			clipentNewer = cframeNewer->clipEdicts[entNum];
		}

#if 0
		G_Printf( "backTime:%i cframeBackTime:%i backFrames:%i lerfrac:%f\n",
			backTime, game.serverTime - cframe->timestamp, backframes, lerpFrac );
#endif

		// interpolate
		VectorLerp( clipent->s.origin, lerpFrac, clipentNewer.s.origin, clipent->s.origin );
		VectorLerp( clipent->r.mins, lerpFrac, clipentNewer.r.mins, clipent->r.mins );
		VectorLerp( clipent->r.maxs, lerpFrac, clipentNewer.r.maxs, clipent->r.maxs );
		for( i = 0; i < 3; i++ )
			clipent->s.angles[i] = LerpAngle( clipent->s.angles[i], clipentNewer.s.angles[i], lerpFrac );
	}

#if 0
	G_Printf( "backTime:%i cframeBackTime:%i backFrames:%i\n", backTime,
		game.serverTime - cframe->timestamp, backframes );
#endif

	// back time entity
	return clipent;
}
Exemple #30
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] );}
			}
		}
	}
}