Exemple #1
0
/*
==============
G_Script_ScriptParse

  Parses the script for the given entity
==============
*/
void G_Script_ScriptParse(gentity_t *ent) {
	char                    *pScript;
	qboolean                wantName;
	qboolean                inScript;
	int                     eventNum;
	g_script_event_t        events[G_MAX_SCRIPT_STACK_ITEMS];
	int                     numEventItems;
	g_script_event_t        *curEvent;
	char                    params[MAX_INFO_STRING];
	g_script_stack_action_t *action;
	int                     i;
	int                     bracketLevel;
	qboolean                buildScript;

	if (!ent->scriptName) {
		return;
	}
	if (!level.scriptEntity) {
		return;
	}

	buildScript = trap_Cvar_VariableIntegerValue("com_buildScript");

	pScript  = level.scriptEntity;
	wantName = qtrue;
	inScript = qfalse;
	COM_BeginParseSession("G_Script_ScriptParse");
	bracketLevel  = 0;
	numEventItems = 0;

	memset(events, 0, sizeof (events));

	for (;;) {
		char *token;

		token = COM_Parse(&pScript);

		if (!token[0]) {
			if (!wantName) {
				G_Error("G_Script_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine());
			}
			break;
		}

		// end of script
		if (token[0] == '}') {
			if (inScript) {
				break;
			}
			if (wantName) {
				G_Error("G_Script_ScriptParse(), Error (line %d): '}' found, but not expected.\n", COM_GetCurrentParseLine());
			}
			wantName = qtrue;
		} else if (token[0] == '{') {
			if (wantName) {
				G_Error("G_Script_ScriptParse(), Error (line %d): '{' found, NAME expected.\n", COM_GetCurrentParseLine());
			}
		} else if (wantName) {
			if (!Q_stricmp(token, "bot")) {
				// a bot, skip this whole entry
				SkipRestOfLine(&pScript);
				// skip this section
				SkipBracedSection(&pScript);
				//
				continue;
			}
			if (!Q_stricmp(token, "entity")) {
				// this is an entity, so go back to look for a name
				continue;
			}
			if (!Q_stricmp(ent->scriptName, token)) {
				inScript      = qtrue;
				numEventItems = 0;
			}
			wantName = qfalse;
		} else if (inScript) {
			Q_strlwr(token);
			eventNum = G_Script_EventForString(token);
			if (eventNum < 0) {
				G_Error("G_Script_ScriptParse(), Error (line %d): unknown event: %s.\n", COM_GetCurrentParseLine(), token);
			}

			if (numEventItems >= G_MAX_SCRIPT_STACK_ITEMS) {
				G_Error("G_Script_ScriptParse(), Error (line %d): G_MAX_SCRIPT_STACK_ITEMS reached (%d)\n", COM_GetCurrentParseLine(), G_MAX_SCRIPT_STACK_ITEMS);
			}

			curEvent           = &events[numEventItems];
			curEvent->eventNum = eventNum;
			memset(params, 0, sizeof (params));

			// parse any event params before the start of this event's actions
			while ((token = COM_Parse(&pScript)) != NULL && (token[0] != '{')) {
				if (!token[0]) {
					G_Error("G_Script_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine());
				}

				if (strlen(params)) {      // add a space between each param
					Q_strcat(params, sizeof (params), " ");
				}
				Q_strcat(params, sizeof (params), token);
			}

			if (strlen(params)) {        // copy the params into the event
				curEvent->params = G_Alloc(strlen(params) + 1);
				Q_strncpyz(curEvent->params, params, strlen(params) + 1);
			}

			// parse the actions for this event
			while ((token = COM_Parse(&pScript)) != NULL && (token[0] != '}')) {
				if (!token[0]) {
					G_Error("G_Script_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine());
				}

				action = G_Script_ActionForString(token);
				if (!action) {
					G_Error("G_Script_ScriptParse(), Error (line %d): unknown action: %s.\n", COM_GetCurrentParseLine(), token);
				}

				curEvent->stack.items[curEvent->stack.numItems].action = action;

				memset(params, 0, sizeof (params));

				// Ikkyo - Parse for {}'s if this is a set command
				// Nico, added "create" & "delete" condition
				if (!Q_stricmp(action->actionString, "set") ||
				    !Q_stricmp(action->actionString, "create") ||
				    !Q_stricmp(action->actionString, "delete")) {
					token = COM_Parse(&pScript);
					if (token[0] != '{') {
						COM_ParseError("'{' expected, found: %s.\n", token);
					}

					while ((token = COM_Parse(&pScript)) != NULL && (token[0] != '}')) {
						if (strlen(params)) {     // add a space between each param
							Q_strcat(params, sizeof (params), " ");
						}

						if (strrchr(token, ' ')) {    // need to wrap this param in quotes since it has more than one word
							Q_strcat(params, sizeof (params), "\"");
						}

						Q_strcat(params, sizeof (params), token);

						if (strrchr(token, ' ')) {    // need to wrap this param in quotes since it has mor
							Q_strcat(params, sizeof (params), "\"");
						}
					}
				} else
				// hackly precaching of custom characters
				if (!Q_stricmp(token, "spawnbot")) {
					// this is fairly indepth, so I'll move it to a separate function for readability
					G_Script_ParseSpawnbot(&pScript, params, MAX_INFO_STRING);
				} else {
					token = COM_ParseExt(&pScript, qfalse);
					for (i = 0; token[0]; ++i) {
						if (strlen(params)) {     // add a space between each param
							Q_strcat(params, sizeof (params), " ");
						}

						if (i == 0) {
							// Special case: playsound's need to be cached on startup to prevent in-game pauses
							if (!Q_stricmp(action->actionString, "playsound")) {
								G_SoundIndex(token);
							} else if (!Q_stricmp(action->actionString, "changemodel")) {
								G_ModelIndex(token);
							} else if (buildScript &&
							           (!Q_stricmp(action->actionString, "mu_start") ||
							            !Q_stricmp(action->actionString, "mu_play") ||
							            !Q_stricmp(action->actionString, "mu_queue") ||
							            !Q_stricmp(action->actionString, "startcam")) &&
							           strlen(token)) {
								trap_SendServerCommand(-1, va("addToBuild %s\n", token));
							}
						}

						if ((i == 0 || i == 1) && !Q_stricmp(action->actionString, "remapshader")) {
							G_ShaderIndex(token);
						}

						if (strrchr(token, ' ')) {    // need to wrap this param in quotes since it has more than one word
							Q_strcat(params, sizeof (params), "\"");
						}

						Q_strcat(params, sizeof (params), token);

						if (strrchr(token, ' ')) {    // need to wrap this param in quotes since it has more than one word
							Q_strcat(params, sizeof (params), "\"");
						}

						token = COM_ParseExt(&pScript, qfalse);
					}
				}

				if (strlen(params)) {     // copy the params into the event
					curEvent->stack.items[curEvent->stack.numItems].params = G_Alloc(strlen(params) + 1);
					Q_strncpyz(curEvent->stack.items[curEvent->stack.numItems].params, params, strlen(params) + 1);
				}

				curEvent->stack.numItems++;

				if (curEvent->stack.numItems >= G_MAX_SCRIPT_STACK_ITEMS) {
					G_Error("G_Script_ScriptParse(): script exceeded G_MAX_SCRIPT_STACK_ITEMS (%d), line %d\n", G_MAX_SCRIPT_STACK_ITEMS, COM_GetCurrentParseLine());
				}
			}

			numEventItems++;
		} else {   // skip this character completely
			// TTimo gcc: suggest parentheses around assignment used as truth value
			while ((token = COM_Parse(&pScript)) != NULL) {
				if (!token[0]) {
					G_Error("G_Script_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine());
				} else if (token[0] == '{') {
					bracketLevel++;
				} else if (token[0] == '}' && !--bracketLevel) {
					break;
				}
			}
		}
	}

	// alloc and copy the events into the gentity_t for this cast
	if (numEventItems > 0) {
		ent->scriptEvents = G_Alloc(sizeof (g_script_event_t) * numEventItems);
		memcpy(ent->scriptEvents, events, sizeof (g_script_event_t) * numEventItems);
		ent->numScriptEvents = numEventItems;
	}
}
Exemple #2
0
void G_xpsave_readconfig() 
{
	g_xpsave_t *x = g_xpsaves[0];
	g_mapstat_t *m = g_mapstats[0];
	int xc = 0;
	int mc = 0;
	fileHandle_t f;
	int i, j;
	int len;
	char *cnf, *cnf2;
	char *t;
	qboolean xpsave_open;
	qboolean mapstat_open;
	qboolean serverstat_open;
	qboolean found_serverstat = qfalse;
	float skill;
	char buffer[MAX_STRING_CHARS];

	if(!(g_XPSave.integer & XPSF_ENABLE))
		return;	
	if(!g_XPSaveFile.string[0])
		return;
	len = trap_FS_FOpenFile(g_XPSaveFile.string, &f, FS_READ) ; 
	if(len < 0) {
		G_Printf("readconfig: could not open xpsave file %s\n",
			g_XPSaveFile.string);
		return;
	}
	cnf = malloc(len+1);
	cnf2 = cnf;
	trap_FS_Read(cnf, len, f);
	*(cnf + len) = '\0';
	trap_FS_FCloseFile(f);

	G_xpsave_cleanup();
	
	t = COM_Parse(&cnf);
	xpsave_open = qfalse;
	mapstat_open = qfalse;
	serverstat_open = qfalse;
	while(*t) {
		if(!Q_stricmp(t, "[xpsave]") ||
			!Q_stricmp(t, "[mapstat]") ||
			!Q_stricmp(t, "[serverstat]")
			) {

			if(xpsave_open)
				g_xpsaves[xc++] = x;
			if(mapstat_open)
				g_mapstats[mc++] = m;
			xpsave_open = qfalse;
			mapstat_open = qfalse;
			serverstat_open = qfalse;
		}

		if(xpsave_open) {
			if(!Q_stricmp(t, "guid")) {
				G_shrubbot_readconfig_string(&cnf, 
					x->guid, sizeof(x->guid)); 
			}
			else if(!Q_stricmp(t, "name")) {
				G_shrubbot_readconfig_string(&cnf, 
					x->name, sizeof(x->name)); 
			}
			else if(!Q_stricmp(t, "time")) {
				G_shrubbot_readconfig_int(&cnf, &x->time);
			}
			else if(!Q_stricmpn(t, "skill[", 6)) {
				for(i=0; i<SK_NUM_SKILLS; i++) {
					if(Q_stricmp(t, va("skill[%i]", i)))
						continue;		
					G_shrubbot_readconfig_float(&cnf,
						&skill);
					x->skill[i] = skill;
					break;
				}
			}
			else if(!Q_stricmp(t, "kill_rating")) {
				G_shrubbot_readconfig_float(&cnf, &x->kill_rating);
			}
			else if(!Q_stricmp(t, "kill_variance")) {
				G_shrubbot_readconfig_float(&cnf, &x->kill_variance);
			}
			else if(!Q_stricmp(t, "rating")) {
				G_shrubbot_readconfig_float(&cnf,
					&x->rating);
			}
			else if(!Q_stricmp(t, "rating_variance")) {
				G_shrubbot_readconfig_float(&cnf,
					&x->rating_variance);
			}
			else if(!Q_stricmp(t, "mutetime")) {
				G_shrubbot_readconfig_int(&cnf, &x->mutetime);
			}
			else if(!Q_stricmpn(t, "pr_skill[", 9)) {
				for(i=0; i<SK_NUM_SKILLS; i++) {
					if(Q_stricmp(t, va("pr_skill[%i]", i)))
						continue;		
					G_shrubbot_readconfig_string(&cnf,
						buffer, sizeof(buffer));
					sscanf(buffer,
						"%i %f %i %f %i %f %i %f %i %f",
						&x->pr_skill_updates[i][0],
						&x->pr_skill[i][0],
						&x->pr_skill_updates[i][1],
						&x->pr_skill[i][1],
						&x->pr_skill_updates[i][2],
						&x->pr_skill[i][2],
						&x->pr_skill_updates[i][3],
						&x->pr_skill[i][3],
						&x->pr_skill_updates[i][4],
						&x->pr_skill[i][4]);
					break;
				}
			}
			else {
				G_Printf("xpsave: [xpsave] parse error near "
					"%s on line %d\n", 
					t, 
					COM_GetCurrentParseLine());
			}
		}
		else if(mapstat_open) {
			if(!Q_stricmp(t, "name")) {
				G_shrubbot_readconfig_string(&cnf, 
					m->name, sizeof(m->name)); 
			}
			else if(!Q_stricmp(t, "rating")) {
				G_shrubbot_readconfig_float(&cnf,
					&m->rating);
			}
			else if(!Q_stricmp(t, "rating_variance")) {
				G_shrubbot_readconfig_float(&cnf,
					&m->rating_variance);
			}
			else if(!Q_stricmp(t, "spree_record")) {
				G_shrubbot_readconfig_int(&cnf,
					&m->spreeRecord);
			}
			else if(!Q_stricmp(t, "spree_name")) {
				G_shrubbot_readconfig_string(&cnf, 
					m->spreeName, sizeof(m->spreeName)); 
			}
			else {
				G_Printf("xpsave: [mapstat] parse error near "
					"%s on line %d\n", 
					t, 
					COM_GetCurrentParseLine());
			}
		}
		else if(serverstat_open) {
			if(!Q_stricmp(t, "rating")) {
				G_shrubbot_readconfig_float(&cnf,
					&g_serverstat.rating);
			}
			else if(!Q_stricmp(t, "rating_variance")) {
				G_shrubbot_readconfig_float(&cnf,
					&g_serverstat.rating_variance);
			}
			else if(!Q_stricmp(t, "distance_rating")) {
				G_shrubbot_readconfig_float(&cnf,
					&g_serverstat.distance_rating);
			}
			else if(!Q_stricmp(t, "distance_variance")) {
				G_shrubbot_readconfig_float(&cnf,
					&g_serverstat.distance_variance);
			}
			else {
				G_Printf("xpsave: [serverstat] parse error near "
					"%s on line %d\n", 
					t, 
					COM_GetCurrentParseLine());
			}
		}

		if(!Q_stricmp(t, "[xpsave]")) {
			if(xc >= MAX_XPSAVES) {
				G_Printf("xpsave: error MAX_XPSAVES exceeded");
				return;
			}
			x = malloc(sizeof(g_xpsave_t));
			x->guid[0] = '\0';
			x->name[0] = '\0';
			x->kill_rating = 0.0f;
			x->kill_variance = SIGMA2_DELTA;
			x->rating = 0.0f;
			x->rating_variance = SIGMA2_THETA;
			for(i=0; i<SK_NUM_SKILLS; i++) {
				x->skill[i] = 0.0f;
				for(j=0; j<NUM_SKILL_LEVELS; j++) {
					x->pr_skill_updates[i][j] = 0;
					x->pr_skill[i][j] = 0.0f;
				}
			}
			x->mutetime = 0;
			x->hits = 0;
			x->team_hits = 0;
			x->time = 0;
			xpsave_open = qtrue;
		}
		if(!Q_stricmp(t, "[mapstat]")) {
			if(mc >= MAX_MAPSTATS) {
				G_Printf("xpsave: error MAX_MAPSTATS exceeded");
				return;
			}
			m = malloc(sizeof(g_mapstat_t));
			m->name[0] = '\0';
			m->rating = 0.0f;
			m->rating_variance = SIGMA2_GAMMA;
			m->spreeRecord = 0;
			m->spreeName[0] = '\0';
			mapstat_open = qtrue;
		}
		if(!Q_stricmp(t, "[serverstat]")) {
			// server prior = 2.6, NOT 0
			g_serverstat.rating = 2.6f;
			g_serverstat.rating_variance = SIGMA2_PSI;
			g_serverstat.distance_rating = 0.0f;
			g_serverstat.distance_variance = SIGMA2_DELTA;
			serverstat_open = qtrue;
			found_serverstat = qtrue;
		}
		t = COM_Parse(&cnf);
	}
	if(xpsave_open)
		g_xpsaves[xc++] = x;
	else if(mapstat_open)
		g_mapstats[mc++] = m;

	free(cnf2);
	if (!found_serverstat) {
		// server prior = 2.6, NOT 0
		g_serverstat.rating = 2.6f;
		g_serverstat.rating_variance = SIGMA2_PSI;
	}
	G_Printf("xpsave: loaded %d mapstats, %d xpsaves\n", mc, xc);
}
void AICast_ScriptParse( cast_state_t *cs ) {
	#define MAX_SCRIPT_EVENTS   64
	gentity_t   *ent;
	char        *pScript;
	char        *token;
	qboolean wantName;
	qboolean inScript;
	int eventNum;
	cast_script_event_t events[MAX_SCRIPT_EVENTS];
	int numEventItems;
	cast_script_event_t *curEvent;
	char params[MAX_QPATH];
	cast_script_stack_action_t  *action;
	int i;
	int bracketLevel;
	qboolean buildScript;       //----(SA)	added

	if ( !level.scriptAI ) {
		return;
	}

	ent = &g_entities[cs->entityNum];
	if ( !ent->aiName ) {
		return;
	}

	buildScript = trap_Cvar_VariableIntegerValue( "com_buildScript" );
	buildScript = qtrue;

	pScript = level.scriptAI;
	wantName = qtrue;
	inScript = qfalse;
	COM_BeginParseSession( "AICast_ScriptParse" );
	bracketLevel = 0;
	numEventItems = 0;

	memset( events, 0, sizeof( events ) );

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

		if ( !token[0] ) {
			if ( !wantName ) {
				G_Error( "AICast_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine() );
			}
			break;
		}

		// end of script
		if ( token[0] == '}' ) {
			if ( inScript ) {
				break;
			}
			if ( wantName ) {
				G_Error( "AICast_ScriptParse(), Error (line %d): '}' found, but not expected.\n", COM_GetCurrentParseLine() );
			}
			wantName = qtrue;
		} else if ( token[0] == '{' )    {
			if ( wantName ) {
				G_Error( "AICast_ScriptParse(), Error (line %d): '{' found, NAME expected.\n", COM_GetCurrentParseLine() );
			}
		} else if ( wantName )   {
			if ( !Q_strcasecmp( ent->aiName, token ) ) {
				inScript = qtrue;
				numEventItems = 0;
			}
			wantName = qfalse;
		} else if ( inScript )   {
			if ( !Q_strcasecmp( token, "attributes" ) ) {
				// read in all the attributes
				AICast_CheckLevelAttributes( cs, ent, &pScript );
				continue;
			}
			eventNum = AICast_EventForString( token );
			if ( eventNum < 0 ) {
				G_Error( "AICast_ScriptParse(), Error (line %d): unknown event: %s.\n", COM_GetCurrentParseLine(), token );
			}
			if ( numEventItems >= MAX_SCRIPT_EVENTS ) {
				G_Error( "AICast_ScriptParse(), Error (line %d): MAX_SCRIPT_EVENTS reached (%d)\n", COM_GetCurrentParseLine(), MAX_SCRIPT_EVENTS );
			}

			// if this is a "friendlysightcorpse" event, then disable corpse vis sharing
			if ( !Q_stricmp( token, "friendlysightcorpse" ) ) {
				cs->aiFlags &= ~AIFL_CORPSESIGHTING;
			}

			curEvent = &events[numEventItems];
			curEvent->eventNum = eventNum;
			memset( params, 0, sizeof( params ) );

			// parse any event params before the start of this event's actions
			while ( ( token = COM_Parse( &pScript ) ) && ( token[0] != '{' ) )
			{
				if ( !token[0] ) {
					G_Error( "AICast_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine() );
				}

				if ( eventNum == 13 ) {   // statechange event, check params
					if ( strlen( token ) > 1 ) {
						if ( BG_IndexForString( token, animStateStr, qtrue ) < 0 ) {
							G_Error( "AICast_ScriptParse(), Error (line %d): unknown state type '%s'.\n", COM_GetCurrentParseLine(), token );
						}
					}
				}

				if ( strlen( params ) ) { // add a space between each param
					Q_strcat( params, sizeof( params ), " " );
				}
				Q_strcat( params, sizeof( params ), token );
			}

			if ( strlen( params ) ) { // copy the params into the event
				curEvent->params = G_Alloc( strlen( params ) + 1 );
				Q_strncpyz( curEvent->params, params, strlen( params ) + 1 );
			}

			// parse the actions for this event
			while ( ( token = COM_Parse( &pScript ) ) && ( token[0] != '}' ) )
			{
				if ( !token[0] ) {
					G_Error( "AICast_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine() );
				}

				action = AICast_ActionForString( cs, token );
				if ( !action ) {
					G_Error( "AICast_ScriptParse(), Error (line %d): unknown action: %s.\n", COM_GetCurrentParseLine(), token );
				}

				curEvent->stack.items[curEvent->stack.numItems].action = action;

				memset( params, 0, sizeof( params ) );
				token = COM_ParseExt( &pScript, qfalse );
				for ( i = 0; token[0]; i++ )
				{
					if ( strlen( params ) ) { // add a space between each param
						Q_strcat( params, sizeof( params ), " " );
					}

					if ( i == 0 ) {
						// Special case: playsound's need to be cached on startup to prevent in-game pauses
						if ( !Q_stricmp( action->actionString, "playsound" ) ) {
							G_SoundIndex( token );
						}

//----(SA)	added a bit more
						if (    buildScript && (
									!Q_stricmp( action->actionString, "mu_start" ) ||
									!Q_stricmp( action->actionString, "mu_play" ) ||
									!Q_stricmp( action->actionString, "mu_queue" ) ||
									!Q_stricmp( action->actionString, "startcam" ) ||
									!Q_stricmp( action->actionString, "startcamblack" ) )
								) {
							if ( strlen( token ) ) { // we know there's a [0], but don't know if it's '0'
								trap_SendServerCommand( cs->entityNum, va( "addToBuild %s\n", token ) );
							}
						}

						if ( !Q_stricmp( action->actionString, "giveweapon" ) ) { // register weapon for client pre-loading
							gitem_t *weap = BG_FindItem2( token );    // (SA) FIXME: rats, need to fix this for weapon names with spaces: 'mauser rifle'
//							if(weap)
							RegisterItem( weap );   // don't be nice, just do it.  if it can't find it, you'll bomb out to the error menu
						}
//----(SA)	end
					}

					if ( strrchr( token,' ' ) ) { // need to wrap this param in quotes since it has more than one word
						Q_strcat( params, sizeof( params ), "\"" );
					}

					Q_strcat( params, sizeof( params ), token );

					if ( strrchr( token,' ' ) ) { // need to wrap this param in quotes since it has more than one word
						Q_strcat( params, sizeof( params ), "\"" );
					}

					token = COM_ParseExt( &pScript, qfalse );
				}

				if ( strlen( params ) ) { // copy the params into the event
					curEvent->stack.items[curEvent->stack.numItems].params = G_Alloc( strlen( params ) + 1 );
					Q_strncpyz( curEvent->stack.items[curEvent->stack.numItems].params, params, strlen( params ) + 1 );
				}

				curEvent->stack.numItems++;

				if ( curEvent->stack.numItems >= AICAST_MAX_SCRIPT_STACK_ITEMS ) {
					G_Error( "AICast_ScriptParse(): script exceeded MAX_SCRIPT_ITEMS (%d), line %d\n", AICAST_MAX_SCRIPT_STACK_ITEMS, COM_GetCurrentParseLine() );
				}
			}

			numEventItems++;
		} else    // skip this character completely
		{
			// TTimo: gcc: suggest () around assignment used as truth value
			while ( ( token = COM_Parse( &pScript ) ) )
			{
				if ( !token[0] ) {
					G_Error( "AICast_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine() );
				} else if ( token[0] == '{' ) {
					bracketLevel++;
				} else if ( token[0] == '}' ) {
					if ( !--bracketLevel ) {
						break;
					}
				}
			}
		}
	}

	// alloc and copy the events into the cast_state_t for this cast
	if ( numEventItems > 0 ) {
		cs->castScriptEvents = G_Alloc( sizeof( cast_script_event_t ) * numEventItems );
		memcpy( cs->castScriptEvents, events, sizeof( cast_script_event_t ) * numEventItems );
		cs->numCastScriptEvents = numEventItems;

		cs->castScriptStatus.castScriptEventIndex = -1;
	}
}
Exemple #4
0
/*
==============
Bot_ScriptParse

  Parses the script for the given character
==============
*/
void Bot_ScriptParse(bot_script_data_t * bsd, char **text)
{
	char           *token;
	qboolean        inScript;
	int             eventNum;
	bot_script_event_t events[BOT_MAX_SCRIPT_EVENTS];
	int             numEventItems;
	bot_script_event_t *curEvent;
	char            params[512];

	//
	bot_script_stack_item_t items[BOT_MAX_SCRIPT_ITEMS];
	int             numItems;

	//
	bot_script_stack_action_t *action;
	int             i;
	int             bracketLevel;
	int             strPoolCount;

	inScript = qfalse;			// not inside the given bot's script

	bracketLevel = 0;
	numEventItems = 0;
	numItems = 0;
	strPoolCount = 0;

	memset(events, 0, sizeof(events));
	memset(items, 0, sizeof(items));

	while(1)
	{
		token = COM_Parse(text);

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

		// end of script
		if(token[0] == '}')
		{
			bracketLevel--;
			if(!bracketLevel)
			{					// we have already parsed the given bot, so get out of here
				break;
			}
			if(bracketLevel < 0)
			{
				G_Error("Bot_ScriptParse(), Error (line %d): '%s' found, name expected\n", 1 + COM_GetCurrentParseLine(), token);
			}
		}
		else if(token[0] == '{')
		{
			bracketLevel++;
			if(bracketLevel > 1)
			{
				G_Error("Bot_ScriptParse(), Error (line %d): '%s' found, event name expected\n", 1 + COM_GetCurrentParseLine(),
						token);
			}
		}
		else if(bracketLevel == 1)
		{
			eventNum = Bot_EventForString(token);
			if(eventNum < 0)
			{
				G_Error("Bot_ScriptParse(), Error (line %d): unknown event: %s.\n", 1 + COM_GetCurrentParseLine(), token);
			}
			if(numEventItems >= BOT_MAX_SCRIPT_EVENTS)
			{
				G_Error("Bot_ScriptParse(), Error (line %d): BOT_MAX_SCRIPT_EVENTS reached (%d)\n", 1 + COM_GetCurrentParseLine(),
						BOT_MAX_SCRIPT_EVENTS);
			}

			curEvent = &events[numEventItems];
			curEvent->eventNum = eventNum;
			curEvent->stack.startIndex = numItems;
			memset(params, 0, sizeof(params));

			curEvent->lineNum = 1 + COM_GetCurrentParseLine();
			curEvent->text = *text - strlen(token);

			// parse any event params before the start of this event's actions
			while((token = COM_Parse(text)) && (token[0] != '{'))
			{
				if(!token[0])
				{
					G_Error("Bot_ScriptParse(), Error (line %d): '}' expected, end of script found.\n",
							1 + COM_GetCurrentParseLine());
				}

				if(strlen(params))
				{				// add a space between each param
					Q_strcat(params, sizeof(params), " ");
				}
				Q_strcat(params, sizeof(params), token);
			}

			if(strlen(params))
			{					// copy the params into the event
				curEvent->params = &bsd->stringPool[strPoolCount];
				Q_strncpyz(curEvent->params, params, BOT_SIZE_STRING_POOL - strPoolCount);
				if((strPoolCount += strlen(params) + 1) >= BOT_SIZE_STRING_POOL)
				{
					G_Error("Bot_ScriptParse(), Error (line %d): string pool size exceeded (MAX = %i)\n",
							1 + COM_GetCurrentParseLine(), BOT_SIZE_STRING_POOL);
				}
			}

			// parse the actions for this event
			while((token = COM_Parse(text)) && (token[0] != '}'))
			{
				if(!token[0])
				{
					G_Error("Bot_ScriptParse(), Error (line %d): '}' expected, end of script found.\n",
							1 + COM_GetCurrentParseLine());
				}

				action = Bot_ActionForString(token);
				if(!action)
				{
					G_Error("Bot_ScriptParse(), Error (line %d): unknown action: %s.\n", 1 + COM_GetCurrentParseLine(), token);
				}

				items[numItems].action = action;
				items[numItems].lineNum = 1 + COM_GetCurrentParseLine();
				items[numItems].text = *text - strlen(token);

				memset(params, 0, sizeof(params));
				token = COM_ParseExt(text, qfalse);
				for(i = 0; token[0]; i++)
				{
					if(strlen(params))
					{			// add a space between each param
						Q_strcat(params, sizeof(params), " ");
					}

					// Special case: playsound's need to be cached on startup to prevent in-game pauses
					if(i == 0)
					{
						if(!Q_stricmp(action->actionString, "playsound"))
						{
							G_SoundIndex(token);
						}
					}

					if(strrchr(token, ' '))
					{			// need to wrap this param in quotes since it has more than one word
						Q_strcat(params, sizeof(params), "\"");
					}

					Q_strcat(params, sizeof(params), token);

					if(strrchr(token, ' '))
					{			// need to wrap this param in quotes since it has more than one word
						Q_strcat(params, sizeof(params), "\"");
					}

					token = COM_ParseExt(text, qfalse);
				}

				if(strlen(params))
				{				// copy the params into the event
					items[numItems].params = &bsd->stringPool[strPoolCount];
					Q_strncpyz(items[numItems].params, params, BOT_SIZE_STRING_POOL - strPoolCount);
					if((strPoolCount += strlen(params) + 1) >= BOT_SIZE_STRING_POOL)
					{
						G_Error("Bot_ScriptParse(), Error (line %d): string pool size exceeded (MAX = %i)\n",
								1 + COM_GetCurrentParseLine(), BOT_SIZE_STRING_POOL);
					}
				}

				curEvent->stack.numItems++;
				numItems++;

				if(numItems >= BOT_MAX_SCRIPT_ITEMS)
				{
					G_Error("Bot_ScriptParse(), Error (line %d): script exceeded BOT_MAX_SCRIPT_ITEMS (%d)\n",
							1 + COM_GetCurrentParseLine(), BOT_MAX_SCRIPT_ITEMS);
				}
			}

			numEventItems++;
		}
		else
		{
			G_Error("Bot_ScriptParse(), Error (line %d): '%s' found, '{' expected\n", 1 + COM_GetCurrentParseLine(), token);
		}
	}

	// alloc and copy the events into the structure for this bot
	if(numEventItems > 0)
	{
		memcpy(bsd->events, events, sizeof(bot_script_event_t) * numEventItems);
		bsd->numEvents = numEventItems;
		memcpy(bsd->items, items, sizeof(bot_script_stack_item_t) * numItems);
	}

}
Exemple #5
0
/*
==============
Bot_ScriptParseAllCharacters
==============
*/
void Bot_ScriptParseAllCharacters()
{
	char           *pScript;
	char           *token;
	bot_script_global_data_t *bsd;
	char            params[MAX_TOKEN_CHARS];

	if(!level.scriptEntity)
	{
		return;
	}

	pScript = level.scriptEntity;
	COM_BeginParseSession("Bot_ScriptParse");
	numScriptCharacters = 0;
	memset(botCharacterScriptData, 0, sizeof(botCharacterScriptData));

	while(1)
	{
		token = COM_Parse(&pScript);
		// we are expecting a name here
		if(!token[0])
		{
			// end of script
			break;
		}
		if(token[0] == '{' || token[0] == '}')
		{
			G_Error("Bot_ScriptParse(), Error (line %d): entry identifier expected, '%s' found.\n", 1 + COM_GetCurrentParseLine(),
					token);
		}
		// is this a bot?
		if(Q_stricmp(token, "BOT") != 0)
		{
			// not a bot, skip this whole entry
			SkipRestOfLine(&pScript);
			// skip this section
			SkipBracedSection(&pScript);
			//
			continue;
		}
		// this is the name
		if(numScriptCharacters == MAX_BOT_SCRIPT_CHARACTERS)
		{
			G_Error
				("Bot_ScriptParse(), Error (line %d): MAX_BOT_SCRIPT_CHARACTERS exceeded (%i), too many bot script characters\n",
				 1 + COM_GetCurrentParseLine(), MAX_BOT_SCRIPT_CHARACTERS);
			break;
		}
		bsd = &botCharacterScriptData[numScriptCharacters++];
		bsd->lineNum = 1 + COM_GetCurrentParseLine();
		// read the name
		token = COM_Parse(&pScript);
		// we are expecting a name here
		if(!token[0])
		{
			G_Error("Bot_ScriptParse(), Error (line %d): name expected, end of line found.\n", 1 + COM_GetCurrentParseLine());
		}
		if(token[0] == '{' || token[0] == '}')
		{
			G_Error("Bot_ScriptParse(), Error (line %d): name expected, '%s' found.\n", 1 + COM_GetCurrentParseLine(), token);
		}
		// allocate the name
		bsd->name = G_Alloc(strlen(token) + 1);
		Q_strncpyz(bsd->name, token, strlen(token) + 1);
		// read the params
		memset(params, 0, sizeof(params));
		while((token = COM_ParseExt(&pScript, qfalse)) && token[0])
		{
			if(strlen(params) + strlen(token) >= sizeof(params))
			{
				G_Error("Bot_ScriptParse(), Error (line %d): parameters exceed maximum size\n", 1 + COM_GetCurrentParseLine());
			}
			if(strlen(params) > 0)
			{
				Q_strcat(params, sizeof(params), " ");
			}
			Q_strcat(params, sizeof(params), token);
		}
		// allocate the params
		bsd->params = G_Alloc(strlen(params) + 1);
		Q_strncpyz(bsd->params, params, strlen(params) + 1);
		// allocate memory for this character script
		bsd->data = G_Alloc(sizeof(bot_script_data_t));
		memset(bsd->data, 0, sizeof(bot_script_data_t));
		// now parse the script data for this character
		Bot_ScriptParse(bsd->data, &pScript);
	}
}
Exemple #6
0
/*
==============
AICast_ScriptParse

  Parses the script for the given character
==============
*/
void AICast_ScriptParse( cast_state_t *cs )
{
	#define MAX_SCRIPT_EVENTS	64
	gentity_t	*ent;
	char		*pScript;
	char		*token;
	qboolean	wantName;
	qboolean	inScript;
	int			eventNum;
	cast_script_event_t	events[MAX_SCRIPT_EVENTS];
	int			numEventItems;
	cast_script_event_t *curEvent;
	char		params[MAX_QPATH];
	cast_script_stack_action_t	*action;
	int			i;
	int			bracketLevel;

	if (!level.scriptAI)
		return;

	ent = &g_entities[cs->entityNum];
	if (!ent->aiName)
		return;

	pScript = level.scriptAI;
	wantName = qtrue;
	inScript = qfalse;
	COM_BeginParseSession("AICast_ScriptParse");
	bracketLevel = 0;
	numEventItems = 0;

	memset( events, 0, sizeof(events) );

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

		if ( !token[0] )
		{
			if ( !wantName )
			{
				G_Error( "AICast_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine() );
			}
			break;
		}

		// end of script
		if ( token[0] == '}' )
		{
			if ( inScript )
			{
				break;
			}
			if ( wantName )
			{
				G_Error( "AICast_ScriptParse(), Error (line %d): '}' found, but not expected.\n", COM_GetCurrentParseLine() );
			}
			wantName = qtrue;
		}
		else if ( token[0] == '{' )
		{
			if ( wantName )
			{
				G_Error( "AICast_ScriptParse(), Error (line %d): '{' found, NAME expected.\n", COM_GetCurrentParseLine() );
			}
		}
		else if ( wantName )
		{
			if ( !Q_strcasecmp( ent->aiName, token ) )
			{
				inScript = qtrue;
				numEventItems = 0;
			}
			wantName = qfalse;
		}
		else if ( inScript )
		{
			if ( !Q_strcasecmp( token, "attributes" ) ) {
				// read in all the attributes
				AICast_CheckLevelAttributes( cs, ent, &pScript );
				continue;
			}
			eventNum = AICast_EventForString( token );
			if (eventNum < 0)
			{
				G_Error( "AICast_ScriptParse(), Error (line %d): unknown event: %s.\n", COM_GetCurrentParseLine(), token );
			}
			if (numEventItems >= MAX_SCRIPT_EVENTS)
			{
				G_Error( "AICast_ScriptParse(), Error (line %d): MAX_SCRIPT_EVENTS reached (%d)\n", COM_GetCurrentParseLine(), MAX_SCRIPT_EVENTS );
			}

			// if this is a "friendlysightcorpse" event, then disable corpse vis sharing
			if (!Q_stricmp(token, "friendlysightcorpse")) {
				cs->aiFlags &= ~AIFL_CORPSESIGHTING;
			}

			curEvent = &events[numEventItems];
			curEvent->eventNum = eventNum;
			memset( params, 0, sizeof(params) );

			// parse any event params before the start of this event's actions
			while ((token = COM_Parse( &pScript )) && (token[0] != '{'))
			{
				if (!token[0])
				{
					G_Error( "AICast_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine() );
				}

				if (eventNum == 13) {	// statechange event, check params
					if (strlen( token ) > 1) {
						if (BG_IndexForString( token, animStateStr, qtrue ) < 0) {
							G_Error( "AICast_ScriptParse(), Error (line %d): unknown state type '%s'.\n", COM_GetCurrentParseLine(), token );
						}
					}
				}

				if (strlen( params ))	// add a space between each param
					Q_strcat( params, sizeof(params), " " );
				Q_strcat( params, sizeof(params), token );
			}

			if (strlen( params ))
			{	// copy the params into the event
				curEvent->params = G_Alloc( strlen( params ) + 1 );
				Q_strncpyz( curEvent->params, params, strlen(params)+1 );
			}

			// parse the actions for this event
			while ((token = COM_Parse( &pScript )) && (token[0] != '}'))
			{
				if (!token[0])
				{
					G_Error( "AICast_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine() );
				}

				action = AICast_ActionForString( token );
				if (!action)
				{
					G_Error( "AICast_ScriptParse(), Error (line %d): unknown action: %s.\n", COM_GetCurrentParseLine(), token );
				}

				curEvent->stack.items[curEvent->stack.numItems].action = action;

				memset( params, 0, sizeof(params) );
				token = COM_ParseExt( &pScript, qfalse );
				for (i=0; token[0]; i++)
				{
					if (strlen( params )) {	// add a space between each param
						Q_strcat( params, sizeof(params), " " );
					}

					// Special case: playsound's need to be cached on startup to prevent in-game pauses
					if ((i==0) && !Q_stricmp(action->actionString, "playsound")) {
						G_SoundIndex(token);
					}

					if (strrchr(token,' '))	// need to wrap this param in quotes since it has more than one word
						Q_strcat( params, sizeof(params), "\"" );

					Q_strcat( params, sizeof(params), token );

					if (strrchr(token,' '))	// need to wrap this param in quotes since it has more than one word
						Q_strcat( params, sizeof(params), "\"" );

					token = COM_ParseExt( &pScript, qfalse );
				}

				if (strlen( params ))
				{	// copy the params into the event
					curEvent->stack.items[curEvent->stack.numItems].params = G_Alloc( strlen( params ) + 1 );
					Q_strncpyz( curEvent->stack.items[curEvent->stack.numItems].params, params, strlen(params)+1 );
				}

				curEvent->stack.numItems++;

				if (curEvent->stack.numItems >= AICAST_MAX_SCRIPT_STACK_ITEMS)
				{
					G_Error( "AICast_ScriptParse(): script exceeded MAX_SCRIPT_ITEMS (%d), line %d\n", AICAST_MAX_SCRIPT_STACK_ITEMS, COM_GetCurrentParseLine() );
				}
			}

			numEventItems++;
		}
		else	// skip this character completely
		{
      // TTimo gcc: suggest parentheses around assignment used as truth value
			while ( ( token = COM_Parse( &pScript ) ) )
			{
				if (!token[0]) {
					G_Error( "AICast_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine() );
				} else if (token[0] == '{')	{
					bracketLevel++;
				} else if (token[0] == '}') {
					if (!--bracketLevel)
						break;
				}
			}
		}
	}

	// alloc and copy the events into the cast_state_t for this cast
	if (numEventItems > 0)
	{
		cs->castScriptEvents = G_Alloc( sizeof(cast_script_event_t) * numEventItems );
		memcpy( cs->castScriptEvents, events, sizeof(cast_script_event_t) * numEventItems );
		cs->numCastScriptEvents = numEventItems;

		cs->castScriptStatus.castScriptEventIndex = -1;
	}
}
Exemple #7
0
/*
==============
G_Script_ScriptParse

  Parses the script for the given entity
==============
*/
void G_Script_ScriptParse( gentity_t *ent ) {
	#define MAX_SCRIPT_EVENTS   64
	char        *pScript;
	char        *token;
	qboolean wantName;
	qboolean inScript;
	int eventNum;
	g_script_event_t events[MAX_SCRIPT_EVENTS];
	int numEventItems;
	g_script_event_t *curEvent;
	// DHM - Nerve :: Some of our multiplayer script commands have longer parameters
	//char		params[MAX_QPATH];
	char params[MAX_INFO_STRING];
	// dhm - end
	g_script_stack_action_t *action;
	int i;
	int bracketLevel;
	qboolean buildScript;       //----(SA)	added

	if ( !ent->scriptName ) {
		return;
	}
	if ( !level.scriptEntity ) {
		return;
	}

	buildScript = trap_Cvar_VariableIntegerValue( "com_buildScript" );
	buildScript = qtrue;

	pScript = level.scriptEntity;
	wantName = qtrue;
	inScript = qfalse;
	COM_BeginParseSession( "G_Script_ScriptParse" );
	bracketLevel = 0;
	numEventItems = 0;

	memset( events, 0, sizeof( events ) );

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

		if ( !token[0] ) {
			if ( !wantName ) {
				G_Error( "G_Script_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine() );
			}
			break;
		}

		// end of script
		if ( token[0] == '}' ) {
			if ( inScript ) {
				break;
			}
			if ( wantName ) {
				G_Error( "G_Script_ScriptParse(), Error (line %d): '}' found, but not expected.\n", COM_GetCurrentParseLine() );
			}
			wantName = qtrue;
		} else if ( token[0] == '{' )    {
			if ( wantName ) {
				G_Error( "G_Script_ScriptParse(), Error (line %d): '{' found, NAME expected.\n", COM_GetCurrentParseLine() );
			}
		} else if ( wantName )   {
			if ( !Q_strcasecmp( ent->scriptName, token ) ) {
				inScript = qtrue;
				numEventItems = 0;
			}
			wantName = qfalse;
		} else if ( inScript )   {
			//if ( !Q_strcasecmp( token, "attributes" ) ) {
			//	// read in all the attributes
			//	G_Script_CheckLevelAttributes( cs, ent, &pScript );
			//	continue;
			//}
			eventNum = G_Script_EventForString( token );
			if ( eventNum < 0 ) {
				G_Error( "G_Script_ScriptParse(), Error (line %d): unknown event: %s.\n", COM_GetCurrentParseLine(), token );
			}
			if ( numEventItems >= MAX_SCRIPT_EVENTS ) {
				G_Error( "G_Script_ScriptParse(), Error (line %d): MAX_SCRIPT_EVENTS reached (%d)\n", COM_GetCurrentParseLine(), MAX_SCRIPT_EVENTS );
			}

			curEvent = &events[numEventItems];
			curEvent->eventNum = eventNum;
			memset( params, 0, sizeof( params ) );

			// parse any event params before the start of this event's actions
			while ( ( token = COM_Parse( &pScript ) ) && ( token[0] != '{' ) )
			{
				if ( !token[0] ) {
					G_Error( "G_Script_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine() );
				}

				if ( strlen( params ) ) { // add a space between each param
					Q_strcat( params, sizeof( params ), " " );
				}
				Q_strcat( params, sizeof( params ), token );
			}

			if ( strlen( params ) ) { // copy the params into the event
				curEvent->params = G_Alloc( strlen( params ) + 1 );
				Q_strncpyz( curEvent->params, params, strlen( params ) + 1 );
			}

			// parse the actions for this event
			while ( ( token = COM_Parse( &pScript ) ) && ( token[0] != '}' ) )
			{
				if ( !token[0] ) {
					G_Error( "G_Script_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine() );
				}

				action = G_Script_ActionForString( token );
				if ( !action ) {
					G_Error( "G_Script_ScriptParse(), Error (line %d): unknown action: %s.\n", COM_GetCurrentParseLine(), token );
				}

				curEvent->stack.items[curEvent->stack.numItems].action = action;

				memset( params, 0, sizeof( params ) );
				token = COM_ParseExt( &pScript, qfalse );
				for ( i = 0; token[0]; i++ )
				{
					if ( strlen( params ) ) { // add a space between each param
						Q_strcat( params, sizeof( params ), " " );
					}

					if ( i == 0 ) {
						// Special case: playsound's need to be cached on startup to prevent in-game pauses
						if ( !Q_stricmp( action->actionString, "playsound" ) ) {
							G_SoundIndex( token );
						}

//----(SA)	added a bit more
						if (    buildScript && (
									!Q_stricmp( action->actionString, "mu_start" ) ||
									!Q_stricmp( action->actionString, "mu_play" ) ||
									!Q_stricmp( action->actionString, "mu_queue" ) ||
									!Q_stricmp( action->actionString, "startcam" ) ||
									!Q_stricmp( action->actionString, "startcamblack" ) )
								) {
							if ( strlen( token ) ) { // we know there's a [0], but don't know if it's '0'
								trap_SendServerCommand( ent->s.number, va( "addToBuild %s\n", token ) );
							}
						}
					}
//----(SA)	end

					if ( strrchr( token,' ' ) ) { // need to wrap this param in quotes since it has more than one word
						Q_strcat( params, sizeof( params ), "\"" );
					}

					Q_strcat( params, sizeof( params ), token );

					if ( strrchr( token,' ' ) ) { // need to wrap this param in quotes since it has more than one word
						Q_strcat( params, sizeof( params ), "\"" );
					}

					token = COM_ParseExt( &pScript, qfalse );
				}

				if ( strlen( params ) ) { // copy the params into the event
					curEvent->stack.items[curEvent->stack.numItems].params = G_Alloc( strlen( params ) + 1 );
					Q_strncpyz( curEvent->stack.items[curEvent->stack.numItems].params, params, strlen( params ) + 1 );
				}

				curEvent->stack.numItems++;

				if ( curEvent->stack.numItems >= G_MAX_SCRIPT_STACK_ITEMS ) {
					G_Error( "G_Script_ScriptParse(): script exceeded MAX_SCRIPT_ITEMS (%d), line %d\n", G_MAX_SCRIPT_STACK_ITEMS, COM_GetCurrentParseLine() );
				}
			}

			numEventItems++;
		} else    // skip this character completely
		{
			// TTimo: gcc: suggest parentheses around assignment used as truth value
			while ( ( token = COM_Parse( &pScript ) ) )
			{
				if ( !token[0] ) {
					G_Error( "G_Script_ScriptParse(), Error (line %d): '}' expected, end of script found.\n", COM_GetCurrentParseLine() );
				} else if ( token[0] == '{' ) {
					bracketLevel++;
				} else if ( token[0] == '}' ) {
					if ( !--bracketLevel ) {
						break;
					}
				}
			}
		}
	}

	// alloc and copy the events into the gentity_t for this cast
	if ( numEventItems > 0 ) {
		ent->scriptEvents = G_Alloc( sizeof( g_script_event_t ) * numEventItems );
		memcpy( ent->scriptEvents, events, sizeof( g_script_event_t ) * numEventItems );
		ent->numScriptEvents = numEventItems;
	}
}
Exemple #8
0
/**
 * @brief Finds and loads all .shader files, combining them into
 * a single large text block that can be scanned for shader names
 */
int ScanAndLoadShaderFilesR1()
{
	char         **shaderFiles;
	char         *buffers[MAX_SHADER_FILES];
	char         *p;
	int          numShaderFiles, i;
	char         *oldp, *token, *textEnd;
	char         **hashMem;
	int          shaderTextHashTableSizes[MAX_SHADERTEXT_HASH], hash;
	unsigned int size;
	char         filename[MAX_QPATH];
	long         sum = 0, summand;

	Com_Memset(buffers, 0, MAX_SHADER_FILES);
	Com_Memset(shaderTextHashTableSizes, 0, MAX_SHADER_FILES);

	// scan for shader files
	shaderFiles = ri.FS_ListFiles("scripts", ".shader", &numShaderFiles);

	if (!shaderFiles || !numShaderFiles)
	{
		Ren_Print("----- ScanAndLoadShaderFilesR1 (no files)-----\n");
		return 0;
	}

	Ren_Print("----- ScanAndLoadShaderFilesR1 (%i files)-----\n", numShaderFiles);

	if (numShaderFiles >= MAX_SHADER_FILES)
	{
		Ren_Drop("MAX_SHADER_FILES limit is reached!");
	}

	// load and parse shader files
	for (i = 0; i < numShaderFiles; i++)
	{
		Com_sprintf(filename, sizeof(filename), "scripts/%s", shaderFiles[i]);
		COM_BeginParseSession(filename);

		Ren_Developer("...loading '%s'\n", filename);
		summand = ri.FS_ReadFile(filename, (void **)&buffers[i]);

		if (!buffers[i])
		{
			Ren_Drop("Couldn't load %s", filename); // in this case shader file is cought/listed but the file can't be read - drop!
		}

		p = buffers[i];
		while (1)
		{
			token = COM_ParseExt(&p, qtrue);

			if (!*token)
			{
				break;
			}

			// Step over the "table"/"guide" and the name
			if (!Q_stricmp(token, "table") || !Q_stricmp(token, "guide"))
			{
				token = COM_ParseExt2(&p, qtrue);

				if (!*token)
				{
					break;
				}
			}

			oldp = p;

			token = COM_ParseExt2(&p, qtrue);
			if (token[0] != '{' && token[1] != '\0')
			{
				Ren_Warning("WARNING: Bad shader file %s has incorrect syntax near token '%s' line %i\n", filename, token, COM_GetCurrentParseLine());
				ri.FS_FreeFile(buffers[i]);
				buffers[i] = NULL;
				break;
			}

			SkipBracedSection(&oldp);
			p = oldp;
		}

		if (buffers[i])
		{
			sum += summand;
		}
	}

	// build single large buffer
	s_shaderTextR1    = (char *)ri.Hunk_Alloc(sum + numShaderFiles * 2, h_low);
	s_shaderTextR1[0] = '\0';
	textEnd           = s_shaderTextR1;

	// free in reverse order, so the temp files are all dumped
	for (i = numShaderFiles - 1; i >= 0 ; i--)
	{
		if (!buffers[i])
		{
			continue;
		}

		strcat(textEnd, buffers[i]);
		strcat(textEnd, "\n");
		textEnd += strlen(textEnd);
		ri.FS_FreeFile(buffers[i]);
	}

	COM_Compress(s_shaderTextR1);

	// free up memory
	ri.FS_FreeFileList(shaderFiles);

	Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes));
	size = 0;

	p = s_shaderTextR1;
	// look for shader names
	while (1)
	{
		token = COM_ParseExt(&p, qtrue);
		if (token[0] == 0)
		{
			break;
		}

		// skip shader tables
		if (!Q_stricmp(token, "table"))
		{
			// skip table name
			(void) COM_ParseExt2(&p, qtrue);

			SkipBracedSection(&p);
		}
		// support shader templates
		else if (!Q_stricmp(token, "guide"))
		{
			// parse shader name
			token = COM_ParseExt2(&p, qtrue);
			//Ren_Print("...guided '%s'\n", token);

			hash = generateHashValue(token, MAX_SHADERTEXT_HASH);
			shaderTextHashTableSizes[hash]++;
			size++;

			// skip guide name
			token = COM_ParseExt2(&p, qtrue);

			// skip parameters
			token = COM_ParseExt2(&p, qtrue);
			if (Q_stricmp(token, "("))
			{
				Ren_Warning("expected ( found '%s'\n", token);
				break;
			}

			while (1)
			{
				token = COM_ParseExt2(&p, qtrue);

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

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

			if (Q_stricmp(token, ")"))
			{
				Ren_Warning("expected ( found '%s'\n", token);
				break;
			}
		}
		else
		{
			hash = generateHashValue(token, MAX_SHADERTEXT_HASH);
			shaderTextHashTableSizes[hash]++;
			size++;
			SkipBracedSection(&p);
		}
	}

	//Ren_Print("Shader hash table size %i\n", size);

	size += MAX_SHADERTEXT_HASH;

	hashMem = (char **)ri.Hunk_Alloc(size * sizeof(char *), h_low);

	for (i = 0; i < MAX_SHADERTEXT_HASH; i++)
	{
		shaderTextHashTableR1[i] = hashMem;
		hashMem                 += shaderTextHashTableSizes[i] + 1;
	}

	Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes));

	p = s_shaderTextR1;

	// look for shader names
	while (1)
	{
		oldp  = p;
		token = COM_ParseExt(&p, qtrue);
		if (token[0] == 0)
		{
			break;
		}

		// parse shader tables
		if (!Q_stricmp(token, "table"))
		{
			int           depth;
			float         values[FUNCTABLE_SIZE];
			int           numValues;
			shaderTable_t *tb;
			qboolean      alreadyCreated;

			Com_Memset(&values, 0, sizeof(values));
			Com_Memset(&table, 0, sizeof(table));

			token = COM_ParseExt2(&p, qtrue);

			Q_strncpyz(table.name, token, sizeof(table.name));

			// check if already created
			alreadyCreated = qfalse;
			hash           = generateHashValue(table.name, MAX_SHADERTABLE_HASH);
			for (tb = shaderTableHashTable[hash]; tb; tb = tb->next)
			{
				if (Q_stricmp(tb->name, table.name) == 0)
				{
					// match found
					alreadyCreated = qtrue;
					break;
				}
			}

			depth     = 0;
			numValues = 0;
			do
			{
				token = COM_ParseExt2(&p, qtrue);

				if (!Q_stricmp(token, "snap"))
				{
					table.snap = qtrue;
				}
				else if (!Q_stricmp(token, "clamp"))
				{
					table.clamp = qtrue;
				}
				else if (token[0] == '{')
				{
					depth++;
				}
				else if (token[0] == '}')
				{
					depth--;
				}
				else if (token[0] == ',')
				{
					continue;
				}
				else
				{
					if (numValues == FUNCTABLE_SIZE)
					{
						Ren_Warning("WARNING: FUNCTABLE_SIZE hit\n");
						break;
					}
					values[numValues++] = atof(token);
				}
			}
			while (depth && p);

			if (!alreadyCreated)
			{
				Ren_Developer("...generating '%s'\n", table.name);
				GeneratePermanentShaderTable(values, numValues);
			}
		}
		// support shader templates
		else if (!Q_stricmp(token, "guide"))
		{
			// parse shader name
			oldp  = p;
			token = COM_ParseExt2(&p, qtrue);

			//Ren_Print("...guided '%s'\n", token);

			hash                                                          = generateHashValue(token, MAX_SHADERTEXT_HASH);
			shaderTextHashTableR1[hash][shaderTextHashTableSizes[hash]++] = oldp;

			// skip guide name
			token = COM_ParseExt2(&p, qtrue);

			// skip parameters
			token = COM_ParseExt2(&p, qtrue);
			if (Q_stricmp(token, "("))
			{
				Ren_Warning("expected ( found '%s'\n", token);
				break;
			}

			while (1)
			{
				token = COM_ParseExt2(&p, qtrue);

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

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

			if (Q_stricmp(token, ")"))
			{
				Ren_Warning("expected ( found '%s'\n", token);
				break;
			}
		}
		else
		{
			hash                                                          = generateHashValue(token, MAX_SHADERTEXT_HASH);
			shaderTextHashTableR1[hash][shaderTextHashTableSizes[hash]++] = oldp;

			SkipBracedSection(&p);
		}
	}

	return numShaderFiles;
}