/* ============== 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; } }
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; } }
/* ============== 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); } }
/* ============== 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); } }
/* ============== 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; } }
/* ============== 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; } }
/** * @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; }