/* RGS 11/12/93: Made format string parser re-entrant: * Needed for lazy evaluation of named formatters */ CONST_FORMAT_PTR ParseFormatString(const char *FormString) { CONST_FORMAT_PTR Formatter; BOOLEAN error = FALSE; Format_Parse_Type parser; initFormatParser(&parser); parser.ParseString = FormString; LexString(&parser, FormString); parser.TokenListHead = parser.TokenList; Formatter = Parse(&parser, FALSE, &error); if (error) Formatter = new_f_formatter(BadFormatFMT, NULL); FreeTokenList(parser.TokenListHead); clearFormatParser(&parser); return Formatter; }
/* ====================== 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( ¤t ); if ( node ) { tree->root = node; } else { RemoveTreeFromList( list, tree ); tree = nullptr; } FreeTokenList( tokenlist ); return tree; }