static AIValueFunc_t *newValueFunc( pc_token_list **list )
{
	AIValueFunc_t *ret = nullptr;
	AIValueFunc_t v;
	pc_token_list *current = *list;
	pc_token_list *parenBegin = nullptr;
	struct AIConditionMap_s *f;

	memset( &v, 0, sizeof( v ) );

	f = (struct AIConditionMap_s*) bsearch( current->token.string, conditionFuncs, ARRAY_LEN( conditionFuncs ), sizeof( *conditionFuncs ), cmdcmp );

	if ( !f )
	{
		Log::Warn( "Unknown function: %s on line %d", current->token.string, current->token.line );
		*list = current->next;
		return nullptr;
	}

	v.expType = EX_FUNC;
	v.retType = f->retType;
	v.func =    f->func;
	v.nparams = f->nparams;

	parenBegin = current->next;

	// if the function has no parameters, allow it to be used without parenthesis
	if ( v.nparams == 0 && parenBegin->token.string[ 0 ] != '(' )
	{
		ret = ( AIValueFunc_t * ) BG_Alloc( sizeof( *ret ) );
		memcpy( ret, &v, sizeof( *ret ) );

		*list = current->next;
		return ret;
	}

	v.params = parseFunctionParameters( list, &v.nparams, f->nparams, f->nparams );

	if ( !v.params && f->nparams > 0 )
	{
		return nullptr;
	}

	// create the value op
	ret = ( AIValueFunc_t * ) BG_Alloc( sizeof( *ret ) );

	// copy the members
	memcpy( ret, &v, sizeof( *ret ) );

	return ret;
}
Example #2
0
/*
==============
G_CopyString
==============
*/
char *G_CopyString( const char *str )
{
	size_t size = strlen( str ) + 1;
	char *cp = (char*) BG_Alloc( size );
	memcpy( cp, str, size );
	return cp;
}
Example #3
0
void G_namelog_connect( gclient_t *client )
{
  namelog_t *n, *p = NULL;
  int       i;

  for( n = level.namelogs; n; p = n, n = n->next )
  {
    if( n->slot != -1 )
      continue;
    if( !Q_stricmp( client->pers.guid, n->guid ) )
      break;
  }
  if( !n )
  {
    n = BG_Alloc( sizeof( namelog_t ) );
    strcpy( n->guid, client->pers.guid );
    if( p )
      p->next = n;
    else
      level.namelogs = n;
  }
  client->pers.namelog = n;
  n->slot = client - level.clients;
  n->banned = qfalse;

  G_namelog_update_name( client );

  for( i = 0; i < MAX_NAMELOG_ADDRS && n->ip[ i ].str[ 0 ]; i++ )
    if( !strcmp( n->ip[ i ].str, client->pers.ip.str ) )
      return;
  if( i == MAX_NAMELOG_ADDRS )
    i--;
  memcpy( &n->ip[ i ], &client->pers.ip, sizeof( n->ip[ i ] ) );
}
Example #4
0
/*
=============
G_NewString

Builds a copy of the string, translating \n to real linefeeds
so message texts can be multi-line
=============
*/
char *G_NewString( const char *string )
{
	char *newb, *new_p;
	int  i, l;

	l = strlen( string ) + 1;

	newb = BG_Alloc( l );

	new_p = newb;

	// turn \n into a real linefeed
	for ( i = 0; i < l; i++ )
	{
		if ( string[ i ] == '\\' && i < l - 1 )
		{
			i++;

			if ( string[ i ] == 'n' )
			{
				*new_p++ = '\n';
			}
			else
			{
				*new_p++ = '\\';
			}
		}
		else
		{
			*new_p++ = string[ i ];
		}
	}

	return newb;
}
Example #5
0
/*
=============
G_NewTarget
=============
*/
gentityCallDefinition_t G_NewCallDefinition( char *eventKey, const char *string )
{
	char *stringPointer;
	int  i, stringLength;
	gentityCallDefinition_t newCallDefinition = { NULL, ON_DEFAULT, NULL, NULL, ECA_NOP };

	stringLength = strlen( string ) + 1;
	if(stringLength == 1)
		return newCallDefinition;

	stringPointer = BG_Alloc( stringLength );
	newCallDefinition.name = stringPointer;

	for ( i = 0; i < stringLength; i++ )
	{
		if ( string[ i ] == ':' && !newCallDefinition.action )
		{
			*stringPointer++ = '\0';
			newCallDefinition.action = stringPointer;
			continue;
		}
		*stringPointer++ = string[ i ];
	}
	newCallDefinition.actionType = G_GetCallActionTypeFor( newCallDefinition.action );

	newCallDefinition.event = eventKey;
	newCallDefinition.eventType = G_GetCallEventTypeFor( newCallDefinition.event );
	return newCallDefinition;
}
pc_token_list *CreateTokenList( int handle )
{
	pc_token_t token;
	char filename[ MAX_QPATH ];
	pc_token_list *current = nullptr;
	pc_token_list *root = nullptr;

	while ( trap_Parse_ReadToken( handle, &token ) )
	{
		pc_token_list *list = ( pc_token_list * ) BG_Alloc( sizeof( pc_token_list ) );
		
		if ( current )
		{
			list->prev = current;
			current->next = list;
		}
		else
		{
			list->prev = list;
			root = list;
		}
		
		current = list;
		current->next = nullptr;

		current->token.floatvalue = token.floatvalue;
		current->token.intvalue = token.intvalue;
		current->token.subtype = token.subtype;
		current->token.type = token.type;
		current->token.string = BG_strdup( token.string );
		trap_Parse_SourceFileAndLine( handle, filename, &current->token.line );
	}

	return root;
}
Example #7
0
void *B_Alloc(int size)
{
#ifdef BOT_ZMALLOC
	void *ptr = NULL;
	int i = 0;

#ifdef BOTMEMTRACK
	int free = 0;
	int used = 0;

	while (i < MAX_BALLOC)
	{
		if (!BAllocList[i])
		{
			free++;
		}
		else
		{
			used++;
		}

		i++;
	}

	trap->Print("Allocations used: %i\nFree allocation slots: %i\n", used, free);

	i = 0;
#endif

	ptr = trap->BotGetMemoryGame(size);

	while (i < MAX_BALLOC)
	{
		if (!BAllocList[i])
		{
			BAllocList[i] = ptr;
			break;
		}
		i++;
	}

	if (i == MAX_BALLOC)
	{
		//If this happens we'll have to rely on this chunk being freed manually with B_Free, which it hopefully will be
#ifdef DEBUG
		trap->Print("WARNING: MAXIMUM B_ALLOC ALLOCATIONS EXCEEDED\n");
#endif
	}

	return ptr;
#else

	return BG_Alloc(size);

#endif
}
Example #8
0
/*
===============
G_ParseInfos
===============
*/
int G_ParseInfos( char *buf, int max, char *infos[] ) {
	char	*token;
	int		count;
	char	key[MAX_TOKEN_CHARS];
	char	info[MAX_INFO_STRING];

	count = 0;

	while ( 1 ) {
		token = COM_Parse( &buf );
		if ( !token[0] ) {
			break;
		}
		if ( strcmp( token, "{" ) ) {
			Com_Printf( "Missing { in info file\n" );
			break;
		}

		if ( count == max ) {
			Com_Printf( "Max infos exceeded\n" );
			break;
		}

		info[0] = '\0';
		while ( 1 ) {
			token = COM_ParseExt( &buf, qtrue );
			if ( !token[0] ) {
				Com_Printf( "Unexpected end of info file\n" );
				break;
			}
			if ( !strcmp( token, "}" ) ) {
				break;
			}
			Q_strncpyz( key, token, sizeof( key ) );

			token = COM_ParseExt( &buf, qfalse );
			if ( !token[0] ) {
				strcpy( token, "<NULL>" );
			}
			Info_SetValueForKey( info, key, token );
		}
                if(!BG_CanAlloc(strlen(info) + strlen("\\num\\") + strlen(va("%d", MAX_ARENAS)) + 1))
                    break; //Not enough memory. Don't even try
		//NOTE: extra space for arena number
		//KK-OAX Changed to Tremulous's BG_Alloc
		infos[count] = BG_Alloc(strlen(info) + strlen("\\num\\") + strlen(va("%d", MAX_ARENAS)) + 1);
		if (infos[count]) {
			strcpy(infos[count], info);
			count++;
		}
	}
	return count;
}
static AIOp_t *newOp( pc_token_list *list )
{
	pc_token_list *current = list;
	AIOp_t *ret = nullptr;

	AIOpType_t op = opTypeFromToken( &current->token );

	if ( isBinaryOp( op ) )
	{
		AIBinaryOp_t *b = ( AIBinaryOp_t * ) BG_Alloc( sizeof( *b ) );
		b->opType = op;
		ret = ( AIOp_t * ) b;
	}
	else if ( isUnaryOp( op ) )
	{
		AIUnaryOp_t *u = ( AIUnaryOp_t * ) BG_Alloc( sizeof( *u ) );
		u->opType = op;
		ret = ( AIOp_t * ) u;
	}

	return ret;
}
Example #10
0
static AIValue_t *newValueLiteral( pc_token_list **list )
{
	AIValue_t *ret;
	pc_token_list *current = *list;
	pc_token_stripped_t *token = &current->token;

	ret = ( AIValue_t * ) BG_Alloc( sizeof( *ret ) );

	*ret = AIBoxToken( token );

	*list = current->next;
	return ret;
}
Example #11
0
void AddTreeToList( AITreeList_t *list, AIBehaviorTree_t *tree )
{
	if ( list->maxTrees == list->numTrees )
	{
		AIBehaviorTree_t **trees = ( AIBehaviorTree_t ** ) BG_Alloc( sizeof( AIBehaviorTree_t * ) * list->maxTrees );
		list->maxTrees *= 2;
		memcpy( trees, list->trees, sizeof( AIBehaviorTree_t * ) * list->numTrees );
		BG_Free( list->trees );
		list->trees = trees;
	}

	list->trees[ list->numTrees ] = tree;
	list->numTrees++;
}
Example #12
0
// Create/Allocate a new Animal Vehicle (initializing it as well).
//this is a BG function too in MP so don't un-bg-compatibilify it -rww
void G_CreateWalkerNPC( Vehicle_t **pVeh, const char *strAnimalType ) {
	// Allocate the Vehicle.
#ifdef PROJECT_GAME
	//these will remain on entities on the client once allocated because the pointer is
	//never stomped. on the server, however, when an ent is freed, the entity struct is
	//memset to 0, so this memory would be lost..
	G_AllocateVehicleObject( pVeh );
#else
	if ( !*pVeh ) { //only allocate a new one if we really have to
		(*pVeh) = (Vehicle_t *)BG_Alloc( sizeof(Vehicle_t) );
	}
#endif
	memset( *pVeh, 0, sizeof(Vehicle_t) );
	(*pVeh)->m_pVehicleInfo = &g_vehicleInfo[BG_VehicleGetIndex( strAnimalType )];
}
Example #13
0
void G_namelog_connect( gclient_t *client )
{
  namelog_t *n, *p = NULL;
  int       i;
  char      *newname;

  for( n = level.namelogs; n; p = n, n = n->next )
  {
    if( n->slot != -1 )
      continue;
    if( !Q_stricmp( client->pers.guid, n->guid ) )
      break;
  }
  if( !n )
  {
    n = BG_Alloc( sizeof( namelog_t ) );
    strcpy( n->guid, client->pers.guid );
    n->guidless = client->pers.guidless;
    if( p )
    {
      p->next = n;
      n->id = p->id + 1;
    }
    else
    {
      level.namelogs = n;
      n->id = MAX_CLIENTS;
    }
  }
  client->pers.namelog = n;
  n->slot = client - level.clients;
  n->banned = qfalse;

  newname = n->name[ n->nameOffset ];
  // If they're muted, copy in their last known name - this will stop people
  // reconnecting to get around the name change protection.
  if( n->muted && G_admin_name_check( &g_entities[ n->slot ],
      newname, NULL, 0 ) )
    Q_strncpyz( client->pers.netname, newname, MAX_NAME_LENGTH );

  for( i = 0; i < MAX_NAMELOG_ADDRS && n->ip[ i ].str[ 0 ]; i++ )
    if( !strcmp( n->ip[ i ].str, client->pers.ip.str ) )
      return;
  if( i == MAX_NAMELOG_ADDRS )
    i--;
  memcpy( &n->ip[ i ], &client->pers.ip, sizeof( n->ip[ i ] ) );
}
Example #14
0
int G_BotAddNames( team_t team, int arg, int last )
{
	int  i = botNames[team].count;
	int  added = 0;
	char name[MAX_NAME_LENGTH];

	while ( arg < last && i < MAX_CLIENTS )
	{
		int j, t;

		trap_Argv( arg++, name, sizeof( name ) );

		// name already in the list? (quick check, including colours & invalid)
		for ( t = 1; t < NUM_TEAMS; ++t )
		{
			for ( j = 0; j < botNames[t].count; ++j )
			{
				if ( !Q_stricmp( botNames[t].name[j].name, name ) )
				{
					goto next;
				}
			}
		}

		botNames[team].name[i].name = ( char * )BG_Alloc( strlen( name ) + 1 );
		strcpy( botNames[team].name[i].name, name );

		botNames[team].count = ++i;
		++added;

		next:
		;
	}

	return added;
}
Example #15
0
/**
 * Add one bot into a team
 * @param name [string] bot's name
 * @param team [team_t] alien or human
 */
qboolean G_BotAdd( char *name, team_t team ) {
	int i;
	int clientNum;
	char userinfo[MAX_INFO_STRING];
	int reservedSlots = 0;
	gentity_t *ent;
    namelog_t *namelog;
    char name_s[ MAX_NAME_LENGTH ];
    char name_tmp_s[ MAX_NAME_LENGTH ] = "";
	
	reservedSlots = trap_Cvar_VariableIntegerValue( "sv_privateclients" );

	//If bot name does not contains [BOT], prepend it.
	if(g_bot_tagname.integer == 1) {
		G_DecolorString(name, name_s, MAX_NAME_LENGTH);
		if (! (Com_StringContains(name_s, "[BOT]", 0))) {
			if(team == TEAM_HUMANS) {
				strcat(name_tmp_s, "^4[BOT] ");
			} else if(team == TEAM_ALIENS) {
				strcat(name_tmp_s, "^1[BOT] ");
			}
			strcat(name_tmp_s, name);
			strcpy(name, name_tmp_s);
		}
	}
    // LEPE: check if no player/bot exists with that name	
    G_SanitiseString(name, name_s, sizeof(name_s) );
    for( namelog = level.namelogs; namelog; namelog = namelog->next ) {
        if( namelog->slot >= 0 ) {
            for( i = 0; i < MAX_NAMELOG_NAMES && namelog->name[ i ][ 0 ]; i++ ) {
                G_SanitiseString(namelog->name[ i ], name_tmp_s, sizeof(name_tmp_s) );
                if( i == namelog->nameOffset && namelog->slot > -1 && !strcmp( name_s, name_tmp_s ) ) {
                    trap_Print("Nick already exists\n");
                    return qfalse;
                }
            }
        }
    }
	// find what clientNum to use for bot
	// LEPE: clientNum calculation was modified to prevent player hijacking
        // We will assign slots from maxclients - 1 to maxclients - reservedSlots - 1
	clientNum = -1;
	for( i = level.maxclients - 1; i > level.maxclients - reservedSlots - 1; i-- ) {
		if( !g_entities[i].inuse ) {
			clientNum = i;
			break;
		}
	}
	if(clientNum == -1)
	{
		trap_Print("Error: Bots were not assigned correctly\n"); //LEPE
		return qfalse;
	}
	if(clientNum < level.maxclients - reservedSlots - 1) 
	{
		trap_Print("no more slots for bot\n");
		return qfalse;
	}
	
	ent = &g_entities[ clientNum ];
	ent->inuse = qtrue;
	ent->bot = (bot_t *)BG_Alloc( sizeof(bot_t) );
//	ent->bot->path.crumb = BG_Alloc( sizeof(level.paths) );
	
	ent->r.svFlags |= SVF_BOT;
	// register user information
	userinfo[0] = '\0';
	Info_SetValueForKey( userinfo, "name", name );
	Info_SetValueForKey( userinfo, "rate", "25000" ); //25000
	Info_SetValueForKey( userinfo, "snaps", "40" );
	//so we can connect if server is password protected
	if(g_needpass.integer == 1) {
		  Info_SetValueForKey( userinfo, "password", g_password.string);
	}
	trap_SetUserinfo( clientNum, userinfo );
	
	// have it connect to the game as a normal client
	if(ClientConnect(clientNum, qtrue) != NULL ) {
		G_Printf("Something weird happened. Bot was not added.");
		// won't let us join
		return qfalse;
	}
	ClientBegin( clientNum );
    G_BotDebug(ent, BOT_VERB_IMPORTANT, BOT_DEBUG_GENERAL, "Bot Added\n");
	G_ChangeTeam( ent, team );
	BotInit( ent );
    if(team == TEAM_HUMANS) {
		BotInitHuman( ent );
		level.humanBots++;
    } else if(team == TEAM_ALIENS) {
		BotInitAlien( ent );
		level.alienBots++;
	}
	//TODO: load profile
	return qtrue;
}
Example #16
0
/*
============
BG_VoiceParseCommand
============
*/
static voiceTrack_t *BG_VoiceParseCommand( int handle )
{
	pc_token_t   token;
	qboolean     parsingTrack = qfalse;
	voiceTrack_t *voiceTracks = NULL;
	voiceTrack_t *top = NULL;

	while ( trap_Parse_ReadToken( handle, &token ) )
	{
		if ( !parsingTrack && token.string[ 0 ] == '}' )
		{
			return top;
		}

		if ( parsingTrack )
		{
			if ( token.string[ 0 ] == '{' )
			{
				BG_VoiceParseTrack( handle, voiceTracks );
				parsingTrack = qfalse;
				continue;
			}
			else
			{
				BG_VoiceParseError( handle, va( "BG_VoiceParseCommand(): "
				                                "parse error at \"%s\"", token.string ) );
			}
		}

		if ( top == NULL )
		{
			voiceTracks = BG_Alloc( sizeof( voiceTrack_t ) );
			top = voiceTracks;
		}
		else
		{
			voiceTracks->next = BG_Alloc( sizeof( voiceCmd_t ) );
			voiceTracks = voiceTracks->next;
		}

		if ( !trap_FS_FOpenFile( token.string, NULL, FS_READ ) )
		{
			int  line;
			char filename[ MAX_QPATH ];

			trap_Parse_SourceFileAndLine( handle, filename, &line );
			Com_Printf( S_WARNING "BG_VoiceParseCommand(): "
			            "track \"%s\" referenced on line %d of %s does not exist\n",
			            token.string, line, filename );
		}
		else
		{
#ifdef CGAME
			voiceTracks->track = trap_S_RegisterSound( token.string, qfalse );
			voiceTracks->duration = 0; // FIXME: Was always zero...
#endif
		}

		voiceTracks->team = -1;
		voiceTracks->pClass = -1;
		voiceTracks->weapon = -1;
		voiceTracks->enthusiasm = 0;
		voiceTracks->text = NULL;
		voiceTracks->next = NULL;
		parsingTrack = qtrue;
	}

	return NULL;
}
Example #17
0
/*
============
BG_VoiceParse
============
*/
static voiceCmd_t *BG_VoiceParse( const char *name )
{
	voiceCmd_t *voiceCmds = NULL;
	voiceCmd_t *top = NULL;
	pc_token_t token;
	qboolean   parsingCmd = qfalse;
	int        handle;

	handle = trap_Parse_LoadSource( va( "voice/%s.voice", name ) );

	if ( !handle )
	{
		return NULL;
	}

	while ( trap_Parse_ReadToken( handle, &token ) )
	{
		if ( parsingCmd )
		{
			if ( token.string[ 0 ] == '{' )
			{
				voiceCmds->tracks = BG_VoiceParseCommand( handle );
				parsingCmd = qfalse;
				continue;
			}
			else
			{
				int  line;
				char filename[ MAX_QPATH ];

				trap_Parse_SourceFileAndLine( handle, filename, &line );
				Com_Error( ERR_FATAL, "BG_VoiceParse(): "
				           "parse error on line %d of %s", line, filename );
			}
		}

		if ( strlen( token.string ) >= MAX_VOICE_CMD_LEN )
		{
			int  line;
			char filename[ MAX_QPATH ];

			trap_Parse_SourceFileAndLine( handle, filename, &line );
			Com_Error( ERR_FATAL, "BG_VoiceParse(): "
			           "command \"%s\" exceeds MAX_VOICE_CMD_LEN (%d) on line %d of %s",
			           token.string, MAX_VOICE_CMD_LEN, line, filename );
		}

		if ( top == NULL )
		{
			voiceCmds = BG_Alloc( sizeof( voiceCmd_t ) );
			top = voiceCmds;
		}
		else
		{
			voiceCmds->next = BG_Alloc( sizeof( voiceCmd_t ) );
			voiceCmds = voiceCmds->next;
		}

		Q_strncpyz( voiceCmds->cmd, token.string, sizeof( voiceCmds->cmd ) );
		voiceCmds->next = NULL;
		parsingCmd = qtrue;
	}

	trap_Parse_FreeSource( handle );

	return top;
}
Example #18
0
/*
============
BG_VoiceList
============
*/
static voice_t *BG_VoiceList( void )
{
	char    fileList[ MAX_VOICES * ( MAX_VOICE_NAME_LEN + 6 ) ] = { "" };
	int     numFiles, i, fileLen = 0;
	int     count = 0;
	char    *filePtr;
	voice_t *voices = NULL;
	voice_t *top = NULL;

	numFiles = trap_FS_GetFileList( "voice", ".voice", fileList,
	                                sizeof( fileList ) );

	if ( numFiles < 1 )
	{
		return NULL;
	}

	// special case for default.voice.  this file is REQUIRED and will
	// always be loaded first in the event of overflow of voice definitions
	if ( !trap_FS_FOpenFile( "voice/default.voice", NULL, FS_READ ) )
	{
		Com_Printf( "voice/default.voice missing, voice system disabled.\n" );
		return NULL;
	}

	voices = ( voice_t * ) BG_Alloc( sizeof( voice_t ) );
	Q_strncpyz( voices->name, "default", sizeof( voices->name ) );
	voices->cmds = NULL;
	voices->next = NULL;
	count = 1;

	top = voices;

	filePtr = fileList;

	for ( i = 0; i < numFiles; i++, filePtr += fileLen + 1 )
	{
		fileLen = strlen( filePtr );

		// accounted for above
		if ( !Q_stricmp( filePtr, "default.voice" ) )
		{
			continue;
		}

		if ( fileLen >= MAX_VOICE_NAME_LEN + 6 )
		{
			Com_Printf( S_WARNING "MAX_VOICE_NAME_LEN is %d. "
			            "skipping \"%s\", filename too long\n", MAX_VOICE_NAME_LEN, filePtr );
			continue;
		}

		// trap_FS_GetFileList() buffer has overflowed
		if ( !trap_FS_FOpenFile( va( "voice/%s", filePtr ), NULL, FS_READ ) )
		{
			Com_Printf( S_WARNING "BG_VoiceList(): detected "
			            "an invalid .voice file \"%s\" in directory listing.  You have "
			            "probably named one or more .voice files with outrageously long "
			            "names.\n", filePtr );
			break;
		}

		if ( count >= MAX_VOICES )
		{
			Com_Printf( S_WARNING ".voice file overflow.  "
			            "%d of %d .voice files loaded.  MAX_VOICES is %d\n",
			            count, numFiles, MAX_VOICES );
			break;
		}

		voices->next = ( voice_t * ) BG_Alloc( sizeof( voice_t ) );
		voices = voices->next;

		Q_strncpyz( voices->name, filePtr, sizeof( voices->name ) );
		// strip extension
		voices->name[ fileLen - 6 ] = '\0';
		voices->cmds = NULL;
		voices->next = NULL;
		count++;
	}

	return top;
}
Example #19
0
/*
===============
G_AllocateNode

Allocate memory for a node_t
===============
*/
static node_t *G_AllocateNode( void )
{
	node_t *node = BG_Alloc( sizeof( node_t ) );

	return node;
}
Example #20
0
/*
===============
CG_ParseInfos
===============
*/
int CG_ParseInfos( const char *buf, int max, char *infos[] )
{
	char *token;
	int  count;
	char key[ MAX_TOKEN_CHARS ];
	char info[ MAX_INFO_STRING ];

	count = 0;

	while ( 1 )
	{
		token = COM_Parse( &buf );

		if ( !token[ 0 ] )
		{
			break;
		}

		if ( strcmp( token, "{" ) )
		{
			Com_Printf( "Missing { in info file\n" );
			break;
		}

		if ( count == max )
		{
			Com_Printf( "Max infos exceeded\n" );
			break;
		}

		info[ 0 ] = '\0';

		while ( 1 )
		{
			token = COM_ParseExt( &buf, true );

			if ( !token[ 0 ] )
			{
				Com_Printf( "Unexpected end of info file\n" );
				break;
			}

			if ( !strcmp( token, "}" ) )
			{
				break;
			}

			Q_strncpyz( key, token, sizeof( key ) );

			token = COM_ParseExt( &buf, false );

			if ( !token[ 0 ] )
			{
				strcpy( token, "<NULL>" );
			}

			Info_SetValueForKey( info, key, token, false );
		}

		//NOTE: extra space for arena number
		infos[ count ] = (char*) BG_Alloc( strlen( info ) + strlen( "\\num\\" ) + strlen( va( "%d", MAX_ARENAS ) ) + 1 );

		if ( infos[ count ] )
		{
			strcpy( infos[ count ], info );
			count++;
		}
	}

	return count;
}
Example #21
0
static AIValue_t *parseFunctionParameters( pc_token_list **list, int *nparams, int minparams, int maxparams )
{
	pc_token_list *current = *list;
	pc_token_list *parenBegin = current->next;
	pc_token_list *parenEnd;
	pc_token_list *parse;
	AIValue_t     *params = nullptr;
	int           numParams = 0;

	// functions should always be proceeded by a '(' if they have parameters
	if ( !expectToken( "(", &parenBegin, false ) )
	{
		*list = current;
		return nullptr;
	}

	// find the end parenthesis around the function's args
	parenEnd = findCloseParen( parenBegin, nullptr );

	if ( !parenEnd )
	{
		Log::Warn( "could not find matching ')' for '(' on line %d", parenBegin->token.line );
		*list = parenBegin->next;
		return nullptr;
	}

	// count the number of parameters
	parse = parenBegin->next;

	while ( parse != parenEnd )
	{
		if ( parse->token.type == tokenType_t::TT_NUMBER || parse->token.type == tokenType_t::TT_STRING )
		{
			numParams++;
		}
		else if ( parse->token.string[ 0 ] != ',' )
		{
			Log::Warn( "Invalid token %s in parameter list on line %d", parse->token.string, parse->token.line );
			*list = parenEnd->next; // skip invalid function expression
			return nullptr;
		}
		parse = parse->next;
	}

	// warn if too many or too few parameters
	if ( numParams < minparams )
	{
		Log::Warn( "too few parameters for %s on line %d", current->token.string, current->token.line );
		*list = parenEnd->next;
		return nullptr;
	}

	if ( numParams > maxparams )
	{
		Log::Warn( "too many parameters for %s on line %d", current->token.string, current->token.line );
		*list = parenEnd->next;
		return nullptr;
	}

	*nparams = numParams;

	if ( numParams )
	{
		// add the parameters
		params = ( AIValue_t * ) BG_Alloc( sizeof( *params ) * numParams );

		numParams = 0;
		parse = parenBegin->next;
		while ( parse != parenEnd )
		{
			if ( parse->token.type == tokenType_t::TT_NUMBER || parse->token.type == tokenType_t::TT_STRING )
			{
				params[ numParams ] = AIBoxToken( &parse->token );
				numParams++;
			}
			parse = parse->next;
		}
	}
	*list = parenEnd->next;
	return params;
}
Example #22
0
/*
======================
ReadBehaviorTree

Load a behavior tree of the given name from a file
======================
*/
AIBehaviorTree_t *ReadBehaviorTree( const char *name, AITreeList_t *list )
{
	int i;
	char treefilename[ MAX_QPATH ];
	int handle;
	pc_token_list *tokenlist;
	AIBehaviorTree_t *tree;
	pc_token_list *current;
	AIGenericNode_t *node;

	currentList = list;

	// check if this behavior tree has already been loaded
	for ( i = 0; i < list->numTrees; i++ )
	{
		AIBehaviorTree_t *tree = list->trees[ i ];
		if ( !Q_stricmp( tree->name, name ) )
		{
			return tree;
		}
	}

	// add preprocessor defines for use in the behavior tree
	// add upgrades
	D( UP_LIGHTARMOUR );
	D( UP_MEDIUMARMOUR );
	D( UP_BATTLESUIT );
	D( UP_RADAR );
	D( UP_JETPACK );
	D( UP_GRENADE );
	D( UP_MEDKIT );

	// add weapons
	D( WP_MACHINEGUN );
	D( WP_PAIN_SAW );
	D( WP_SHOTGUN );
	D( WP_LAS_GUN );
	D( WP_MASS_DRIVER );
	D( WP_CHAINGUN );
	D( WP_FLAMER );
	D( WP_PULSE_RIFLE );
	D( WP_LUCIFER_CANNON );
	D( WP_HBUILD );

	// add teams
	D( TEAM_ALIENS );
	D( TEAM_HUMANS );
	D( TEAM_NONE );

	// add AIEntitys
	D( E_NONE );
	D( E_A_SPAWN );
	D( E_A_OVERMIND );
	D( E_A_BARRICADE );
	D( E_A_ACIDTUBE );
	D( E_A_TRAPPER );
	D( E_A_BOOSTER );
	D( E_A_HIVE );
	D( E_A_LEECH );
	D( E_H_SPAWN );
	D( E_H_MGTURRET );
	D( E_H_ROCKETPOD );
	D( E_H_ARMOURY );
	D( E_H_MEDISTAT );
	D( E_H_DRILL );
	D( E_H_REACTOR );
	D( E_H_REPEATER );
	D( E_GOAL );
	D( E_ENEMY );
	D( E_DAMAGEDBUILDING );
	D( E_SELF );

	// add player classes
	D( PCL_NONE );
	D( PCL_ALIEN_BUILDER0 );
	D( PCL_ALIEN_BUILDER0_UPG );
	D( PCL_ALIEN_LEVEL0 );
	D( PCL_ALIEN_LEVEL1 );
	D( PCL_ALIEN_LEVEL2 );
	D( PCL_ALIEN_LEVEL2_UPG );
	D( PCL_ALIEN_LEVEL3 );
	D( PCL_ALIEN_LEVEL3_UPG );
	D( PCL_ALIEN_LEVEL4 );
	D( PCL_HUMAN_NAKED );
	D( PCL_HUMAN_LIGHT );
	D( PCL_HUMAN_MEDIUM );
	D( PCL_HUMAN_BSUIT );
	
	D( MOVE_FORWARD );
	D( MOVE_BACKWARD );
	D( MOVE_RIGHT );
	D( MOVE_LEFT );

	D2( ET_BUILDABLE, Util::ordinal(entityType_t::ET_BUILDABLE) );

	// node return status
	D( STATUS_RUNNING );
	D( STATUS_SUCCESS );
	D( STATUS_FAILURE );

	D( SAY_ALL );
	D( SAY_TEAM );
	D( SAY_AREA );
	D( SAY_AREA_TEAM );
	
	Q_strncpyz( treefilename, va( "bots/%s.bt", name ), sizeof( treefilename ) );

	handle = trap_Parse_LoadSource( treefilename );
	if ( !handle )
	{
		Log::Warn( "Cannot load behavior tree %s: File not found", treefilename );
		return nullptr;
	}

	tokenlist = CreateTokenList( handle );
	trap_Parse_FreeSource( handle );

	tree = ( AIBehaviorTree_t * ) BG_Alloc( sizeof( AIBehaviorTree_t ) );

	Q_strncpyz( tree->name, name, sizeof( tree->name ) );

	tree->run = BotBehaviorNode;
	tree->type = BEHAVIOR_NODE;

	AddTreeToList( list, tree );

	current = tokenlist;

	node = ReadNode( &current );
	if ( node )
	{
		tree->root = node;
	}
	else
	{
		RemoveTreeFromList( list, tree );
		tree = nullptr;
	}

	FreeTokenList( tokenlist );
	return tree;
}
Example #23
0
/*
============
BG_VoiceParseTrack
============
*/
static qboolean BG_VoiceParseTrack( int handle, voiceTrack_t *voiceTrack )
{
	pc_token_t token;
	qboolean   found = qfalse;
	qboolean   foundText = qfalse;
	qboolean   foundToken = qfalse;

	foundToken = trap_Parse_ReadToken( handle, &token );

	while ( foundToken )
	{
		if ( token.string[ 0 ] == '}' )
		{
			if ( foundText )
			{
				return qtrue;
			}
			else
			{
				BG_VoiceParseError( handle, "BG_VoiceParseTrack(): "
				                    "missing text attribute for track" );
			}
		}
		else if ( !Q_stricmp( token.string, "team" ) )
		{
			foundToken = trap_Parse_ReadToken( handle, &token );
			found = qfalse;

			while ( foundToken )
			{
				if ( voiceTrack->team < 0 )
				{
					voiceTrack->team = 0;
				}

				if ( !Q_stricmp( token.string, "humans" ) )
				{
					voiceTrack->team |= 1 << TEAM_HUMANS;
				}
				else if ( !Q_stricmp( token.string, "aliens" ) )
				{
					voiceTrack->team |= 1 << TEAM_ALIENS;
				}
				else
				{
					break;
				}

				found = qtrue;
				foundToken = trap_Parse_ReadToken( handle, &token );
			}

			if ( !found )
			{
				BG_VoiceParseError( handle, "BG_VoiceParseTrack(): missing \"team\" name" );
			}

			continue;
		}
		else if ( !Q_stricmp( token.string, "class" ) )
		{
			qboolean negate = qfalse;

			foundToken = trap_Parse_ReadToken( handle, &token );
			found = qfalse;

			while ( foundToken )
			{
				classModelConfig_t *model;
				int                modelno = -1;

				if ( voiceTrack->pClass < 0 )
				{
					voiceTrack->pClass = 0;
				}

				if ( !Q_stricmp( token.string, "all" ) )
				{
					modelno = PCL_ALL_CLASSES;
				}
				else if ( !Q_stricmp( token.string, "humans" ) )
				{
					modelno = PCL_HUMAN_CLASSES;
				}
				else if ( !Q_stricmp( token.string, "aliens" ) )
				{
					modelno = PCL_ALIEN_CLASSES;
				}
				else if ( !Q_stricmp( token.string, "-" ) ) // this must be outside quotation marks
				{
					negate = qtrue;
					modelno = 0;
				}
				else
				{
					model = BG_ClassModelConfigByName( token.string );

					if ( model != BG_ClassModelConfigByName( NULL ) )
					{
						modelno = 1 << ( model - BG_ClassModelConfig( 0 ) );

						if ( modelno <= 1)
						{
							modelno = -1; // match failure
						}
					}

				}

				if ( modelno > 0 )
				{
					if ( negate )
					{
						negate = qfalse;
						voiceTrack->pClass &= ~modelno;
					}
					else
					{
						voiceTrack->pClass |= modelno;
					}
				}
				else if ( modelno < 0 )
				{
				        break; // possibly the next keyword
				}

				found = qtrue;
				foundToken = trap_Parse_ReadToken( handle, &token );
			}

			if ( !found )
			{
				BG_VoiceParseError( handle, "BG_VoiceParseTrack(): missing \"class\" name" );
			}

			continue;
		}
		else if ( !Q_stricmp( token.string, "text" ) )
		{
			if ( foundText )
			{
				BG_VoiceParseError( handle, "BG_VoiceParseTrack(): "
				                    "duplicate \"text\" definition for track" );
			}

			foundToken = trap_Parse_ReadToken( handle, &token );

			if ( !foundToken )
			{
				BG_VoiceParseError( handle, "BG_VoiceParseTrack(): "
				                    "missing \"text\" value" );
			}

			foundText = qtrue;

			if ( strlen( token.string ) >= MAX_SAY_TEXT )
			{
				BG_VoiceParseError( handle, va( "BG_VoiceParseTrack(): "
				                                "\"text\" value " "\"%s\" exceeds MAX_SAY_TEXT length",
				                                token.string ) );
			}

			voiceTrack->text = ( char * ) BG_Alloc( strlen( token.string ) + 1 );
			Q_strncpyz( voiceTrack->text, token.string, strlen( token.string ) + 1 );
			foundToken = trap_Parse_ReadToken( handle, &token );
			continue;
		}
		else if ( !Q_stricmp( token.string, "enthusiasm" ) )
		{
			foundToken = trap_Parse_ReadToken( handle, &token );

			if ( token.type == TT_NUMBER )
			{
				voiceTrack->enthusiasm = token.intvalue;
			}
			else
			{
				BG_VoiceParseError( handle, "BG_VoiceParseTrack(): "
				                    "missing \"enthusiasm\" value" );
			}

			foundToken = trap_Parse_ReadToken( handle, &token );
			continue;
		}
		else
		{
			BG_VoiceParseError( handle, va( "BG_VoiceParseTrack():"
			                                " unknown token \"%s\"", token.string ) );
		}
	}

	return qfalse;
}
Example #24
0
// functions for keeping a list of behavior trees loaded
void InitTreeList( AITreeList_t *list )
{
	list->trees = ( AIBehaviorTree_t ** ) BG_Alloc( sizeof( AIBehaviorTree_t * ) * 10 );
	list->maxTrees = 10;
	list->numTrees = 0;
}