// parses help.tbl and populates help_overlaylist[] void parse_helptbl(const char *filename) { int overlay_id, currcount, vtxcount; char name[HELP_MAX_NAME_LENGTH]; char buf[HELP_MAX_STRING_LENGTH + 1]; int i, j, rval; SCP_vector<help_pline> pline_temp; help_pline pline_temp2; SCP_vector<help_text> text_temp; help_text text_temp2; SCP_vector<help_right_bracket> rbracket_temp; help_right_bracket rbracket_temp2; SCP_vector<help_left_bracket> lbracket_temp; help_left_bracket lbracket_temp2; vec3d vec3d_temp; if ((rval = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", filename, rval)); return; } read_file_text(filename, CF_TYPE_TABLES); reset_parse(); // for each overlay... while (optional_string("$")) { stuff_string(name, F_NAME, HELP_MAX_NAME_LENGTH); overlay_id = help_overlay_get_index(name); if (overlay_id < 0) { if (num_help_overlays >= MAX_HELP_OVERLAYS) { Warning(LOCATION, "Could not load help overlay after '%s' as maximum number of help overlays was reached (Max is %d)", help_overlaylist[overlay_id - 1].name, MAX_HELP_OVERLAYS); if (!skip_to_string("$end")) { Error(LOCATION, "Couldn't find $end. Help.tbl or -hlp.tbm is invalid.\n"); } continue; } else { overlay_id = num_help_overlays; strcpy_s(help_overlaylist[overlay_id].name, name); num_help_overlays++; } } // clear out counters in the overlay struct help_overlaylist[overlay_id].plinecount = 0; help_overlaylist[overlay_id].textcount = 0; help_overlaylist[overlay_id].rbracketcount = 0; help_overlaylist[overlay_id].lbracketcount = 0; help_overlaylist[overlay_id].fontlist.clear(); help_overlaylist[overlay_id].plinelist.clear(); help_overlaylist[overlay_id].textlist.clear(); help_overlaylist[overlay_id].rbracketlist.clear(); help_overlaylist[overlay_id].lbracketlist.clear(); if (optional_string("+resolutions")) { stuff_int(&help_overlaylist[overlay_id].num_resolutions); } else { help_overlaylist[overlay_id].num_resolutions = 2; } if (help_overlaylist[overlay_id].num_resolutions < 1) { Error(LOCATION, "+resolutions in %s is %d. (Must be 1 or greater)", filename, help_overlaylist[overlay_id].num_resolutions); } if (optional_string("+font")) { int font; for (i=0; i<help_overlaylist[overlay_id].num_resolutions; i++) { stuff_int(&font); help_overlaylist[overlay_id].fontlist.push_back(font); } } else { for (i=0; i<help_overlaylist[overlay_id].num_resolutions; i++) { help_overlaylist[overlay_id].fontlist.push_back(FONT1); } } for (i=0; i<help_overlaylist[overlay_id].num_resolutions; i++) { help_overlaylist[overlay_id].plinelist.push_back(pline_temp); help_overlaylist[overlay_id].textlist.push_back(text_temp); help_overlaylist[overlay_id].rbracketlist.push_back(rbracket_temp); help_overlaylist[overlay_id].lbracketlist.push_back(lbracket_temp); } int type; // read in all elements for this overlay while ((type = required_string_one_of(5, "+pline", "+text", "+right_bracket", "+left_bracket", "$end")) != 4) { // Doing it this way means an error lists "$end" at the end, which seems appropriate. -MageKing17 switch (type) { case 0: // +pline required_string("+pline"); currcount = help_overlaylist[overlay_id].plinecount; int a, b; // temp vars to read in int before cast to float; // read number of pline vertices stuff_int(&vtxcount); // get vertex coordinates for each resolution for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) { help_overlaylist[overlay_id].plinelist.at(i).push_back(pline_temp2); for (j = 0; j < vtxcount; j++) { help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtx.push_back(vec3d_temp); help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtxcount = vtxcount; stuff_int(&a); stuff_int(&b); help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtx.at(j).xyz.x = (float)a; help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtx.at(j).xyz.y = (float)b; help_overlaylist[overlay_id].plinelist.at(i).at(currcount).vtx.at(j).xyz.z = 0.0f; } } help_overlaylist[overlay_id].plinecount++; break; case 1: // +text required_string("+text"); currcount = help_overlaylist[overlay_id].textcount; // get coordinates for each resolution for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) { help_overlaylist[overlay_id].textlist.at(i).push_back(text_temp2); stuff_int(&(help_overlaylist[overlay_id].textlist.at(i).at(currcount).x_coord)); stuff_int(&(help_overlaylist[overlay_id].textlist.at(i).at(currcount).y_coord)); } // get string (always use the first resolution) stuff_string(buf, F_MESSAGE, sizeof(buf)); help_overlaylist[overlay_id].textlist.at(0).at(currcount).string = vm_strdup(buf); help_overlaylist[overlay_id].textcount++; break; case 2: // +right_bracket required_string("+right_bracket"); currcount = help_overlaylist[overlay_id].rbracketcount; // get coordinates for each resolution for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) { help_overlaylist[overlay_id].rbracketlist.at(i).push_back(rbracket_temp2); stuff_int(&(help_overlaylist[overlay_id].rbracketlist.at(i).at(currcount).x_coord)); stuff_int(&(help_overlaylist[overlay_id].rbracketlist.at(i).at(currcount).y_coord)); } help_overlaylist[overlay_id].rbracketcount++; break; case 3: // +left_bracket required_string("+left_bracket"); currcount = help_overlaylist[overlay_id].lbracketcount; // get coordinates for each resolution for (i = 0; i < help_overlaylist[overlay_id].num_resolutions; i++) { help_overlaylist[overlay_id].lbracketlist.at(i).push_back(lbracket_temp2); stuff_int(&(help_overlaylist[overlay_id].lbracketlist.at(i).at(currcount).x_coord)); stuff_int(&(help_overlaylist[overlay_id].lbracketlist.at(i).at(currcount).y_coord)); } help_overlaylist[overlay_id].lbracketcount++; break; case -1: // -noparseerrors is set break; case 4: // $end default: Assertion(false, "This should never happen.\n"); break; } } // end while required_string("$end"); } // end while }
void parse_ssm(const char *filename) { char weapon_name[NAME_LENGTH]; try { read_file_text(filename, CF_TYPE_TABLES); reset_parse(); // parse the table while(required_string_either("#end", "$SSM:")) { required_string("$SSM:"); ssm_info s; int string_index; // name stuff_string(s.name, F_NAME, NAME_LENGTH); if (*s.name == 0) { sprintf(s.name, "SSM " SIZE_T_ARG, Ssm_info.size()); mprintf(("Found an SSM entry without a name. Assigning \"%s\".\n", s.name)); } // stuff data required_string("+Weapon:"); stuff_string(weapon_name, F_NAME, NAME_LENGTH); string_index = optional_string_either("+Count:", "+Min Count:"); if (string_index == 0) { stuff_int(&s.count); s.max_count = -1; } else if (string_index == 1) { stuff_int(&s.count); required_string("+Max Count:"); stuff_int(&s.max_count); } else { s.count = 1; s.max_count = -1; } required_string("+WarpRadius:"); stuff_float(&s.warp_radius); if (optional_string("+WarpTime:")) { stuff_float(&s.warp_time); // According to fireballs.cpp, "Warp lifetime must be at least 4 seconds!" if ( (s.warp_time) < 4.0f) { // So let's warn them before they try to use it, shall we? Warning(LOCATION, "Expected a '+WarpTime:' value equal or greater than 4.0, found '%f' in weapon '%s'.\n Setting to 4.0, please check and set to a number 4.0 or greater!\n", s.warp_time, weapon_name); // And then make the Assert obsolete -- Zacam s.warp_time = 4.0f; } } else { s.warp_time = 4.0f; } string_index = required_string_either("+Radius:", "+Min Radius:"); if (string_index == 0) { required_string("+Radius:"); stuff_float(&s.radius); s.max_radius = -1.0f; } else { required_string("+Min Radius:"); stuff_float(&s.radius); required_string("+Max Radius:"); stuff_float(&s.max_radius); } string_index = optional_string_either("+Offset:", "+Min Offset:"); if (string_index == 0) { stuff_float(&s.offset); s.max_offset = -1.0f; } else if (string_index == 1) { stuff_float(&s.offset); required_string("+Max Offset:"); stuff_float(&s.max_offset); } else { s.offset = 0.0f; s.max_offset = -1.0f; } if (optional_string("+Shape:")) { switch(required_string_one_of(3, "Point", "Circle", "Sphere")) { case 0: required_string("Point"); s.shape = SSM_SHAPE_POINT; break; case 1: required_string("Circle"); case -1: // If we're ignoring parse errors and can't identify the shape, go with a circle. s.shape = SSM_SHAPE_CIRCLE; break; case 2: required_string("Sphere"); s.shape = SSM_SHAPE_SPHERE; break; default: Assertion(false, "Impossible return value from required_string_one_of(); get a coder!\n"); } } else { s.shape = SSM_SHAPE_CIRCLE; } if (optional_string("+HUD Message:")) stuff_boolean(&s.send_message); else s.send_message = true; if (optional_string("+Custom Message:")) { stuff_string(s.message, F_NAME, NAME_LENGTH); s.use_custom_message = true; } s.sound_index = -1; parse_sound("+Alarm Sound:", &s.sound_index, s.name); // see if we have a valid weapon s.weapon_info_index = weapon_info_lookup(weapon_name); if(s.weapon_info_index >= 0) { // valid int existing = ssm_info_lookup(s.name); if (existing >= 0) { // Redefined the existing entry instead of adding a duplicate. Ssm_info[existing] = s; } else { Ssm_info.push_back(s); } } } } catch (const parse::ParseException& e) { mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what())); return; } }
void parse_everything_else(const char *filename) { Assertion(filename != NULL, "parse_everything_else() called on NULL; get a coder!\n"); read_file_text(filename, CF_TYPE_TABLES); int err_code; if ((err_code = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %d.\n", filename, err_code)); return; } reset_parse(); int rgba[4] = {0,0,0,0}; // reusable temp vars int i, j; SCP_string temp; if (optional_string("#Start Colors")) { // Skip this section; we already parsed it in every file. skip_to_string("#End", NULL); } //Team coloring if (optional_string("#Team Colors")) { while (required_string_either("#End", "$Team Name:")) { required_string("$Team Name:"); // required to move the parse pointer forward team_color temp_color; char temp2[NAME_LENGTH]; stuff_string(temp2, F_NAME, NAME_LENGTH); temp = temp2; if (!stricmp(temp2, "none")) { Warning(LOCATION, "Team color in '%s' defined with a name of '%s'; this won't be usable due to 'None' being used for a lack of a team color by the engine.\n", filename, temp2); } if (required_string("$Team Stripe Color:")) { int rgb[3]; stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); for (i = 0; i < 3; i++) { CLAMP(rgb[i], 0, 255); } temp_color.stripe.r = rgb[0] / 255.0f; temp_color.stripe.g = rgb[1] / 255.0f; temp_color.stripe.b = rgb[2] / 255.0f; } if (required_string("$Team Base Color:")) { int rgb[3]; stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); for (i = 0; i < 3; i++) { CLAMP(rgb[i], 0, 255); } temp_color.base.r = rgb[0] / 255.0f; temp_color.base.g = rgb[1] / 255.0f; temp_color.base.b = rgb[2] / 255.0f; } if (Team_Colors.find(temp) == Team_Colors.end()) { // Only push to the vector if the team isn't already defined. Team_Names.push_back(temp); } Team_Colors[temp] = temp_color; } required_string("#End"); } // Previously-hardcoded interface colors if (optional_string("#Interface Colors")) { char *color_names[INTERFACE_COLORS] = { "$Text Normal:", "$Text Subselected:", "$Text Selected:", "$Text Error:", "$Text Error Highlighted:", "$Text Active:", "$Text Active Highlighted:", "$Text Heading:", "$More Indicator:", "$Bright More Indicator:", "$Bright:", "$Normal:", }; // now for each color, check if its corresponding string is there for (i = 0; i < INTERFACE_COLORS; i++) { if (optional_string(color_names[i])) { // if so, get its rgba values and initialise it using them mprintf(("'%s' has been redefined.\n", color_names[i])); if ( check_for_string("(") ) { // If we have a list of integers, use them. stuff_int_list(rgba, 4, RAW_INTEGER_TYPE); for (j = 0; j < 4; j++) { if (rgba[j] < 0) { Warning(LOCATION, "RGBA value for '%s' in %s too low (%d), capping to 0.\n", color_names[i], filename, rgba[j]); rgba[j] = 0; } else if (rgba[j] > 255) { Warning(LOCATION, "RGBA value for '%s' in %s too high (%d), capping to 255.\n", color_names[i], filename, rgba[j]); rgba[j] = 255; } } gr_init_alphacolor(interface_colors[i], rgba[0], rgba[1], rgba[2], rgba[3]); //} else if (check_for_string("#")) { // stuff_hex_list(rgba, 4); // gr_init_alphacolor(interface_colors[i], rgba[0], rgba[1], rgba[2], rgba[3]); } else { // We have a string; it should be the name of a color to use. stuff_string(temp, F_NAME); for (j = 0; j < TOTAL_COLORS; j++) { if ( !temp.compare(COLOR_NAMES[j]) ) { break; } } if ( j == TOTAL_COLORS ) { Warning(LOCATION, "Unknown color '%s' in %s, for definition of '%s'; using default ('%s').\n", temp.c_str(), filename, color_names[i], COLOR_NAMES[interface_defaults[i]]); } else { Assertion(j >= 0 && j < TOTAL_COLORS, "Attempting to copy nonexistant color (%d out of 0-%d)!\n", j, TOTAL_COLORS-1); memcpy(interface_colors[i], COLOR_LIST[j], sizeof(color)); } } } } required_string("#End"); } // Text color tags; for briefings, command briefings, debriefings, and the fiction viewer if (optional_string("#Color Tags")) { while (required_string_either("$Tag:", "#End") < 1) { required_string("$Tag:"); color temp_color; char tag; stuff_string(temp, F_RAW); if (temp[0] == '$') { if (temp[1] == '\0') { Error(LOCATION, "%s - found a '$Tag:' entry with a solitary '$'.\n", filename); } tag = temp[1]; if (temp[2] != '\0') { Warning(LOCATION, "%s - tag '$%c' has extra text in its definition.\n", filename, tag); } } else if (temp[0] == '\0') { Error(LOCATION, "%s - found a '$Tag:' entry with no tag.\n", filename); } else { tag = temp[0]; if (temp[1] != '\0') { Warning(LOCATION, "%s - tag '$%c' has extra text in its definition.\n", filename, tag); } } if (Tagged_Colors.find(tag) == Tagged_Colors.end()) { // Only push the tag to our list of tags if it's actually new, not just a redefinition. Color_Tags.push_back(tag); } switch(required_string_one_of(4, "+Color:", "+Friendly", "+Hostile", "+Neutral")) { case 0: // +Color required_string("+Color:"); rgba[0] = rgba[1] = rgba[2] = 0; rgba[3] = 255; // Odds are pretty high you want it to have full alpha... if ( check_for_string("(") ) { stuff_int_list(rgba, 4, RAW_INTEGER_TYPE); for (j = 0; j < 4; j++) { if (rgba[j] < 0) { Warning(LOCATION, "RGBA value for '$%c' in %s too low (%d), capping to 0.\n", tag, filename, rgba[j]); rgba[j] = 0; } else if (rgba[j] > 255) { Warning(LOCATION, "RGBA value for '$%c' in %s too high (%d), capping to 255.\n", tag, filename, rgba[j]); rgba[j] = 255; } } gr_init_alphacolor(&temp_color, rgba[0], rgba[1], rgba[2], rgba[3]); Custom_Colors[tag] = temp_color; Tagged_Colors[tag] = &Custom_Colors[tag]; //} else if ( check_for_string ("#") ) { // stuff_hex_list(rgba, 4); // gr_init_alphacolor(&temp_color, rgba[0], rgba[1], rgba[2], rgba[3]); // Custom_Colors[tag] = temp_color; // Tagged_Colors[tag] = &Custom_Colors[tag]; } else { // We have a string; it should be the name of a color to use. stuff_string(temp, F_NAME); for (j = 0; j < TOTAL_COLORS; j++) { if ( !temp.compare(COLOR_NAMES[j]) ) { break; } } if ( j == TOTAL_COLORS ) { Error(LOCATION, "Unknown color '%s' in %s, for definition of tag '$%c'.\n", temp.c_str(), filename, tag); } Tagged_Colors[tag] = COLOR_LIST[j]; } break; case 1: // +Friendly required_string("+Friendly"); Tagged_Colors[tag] = &Brief_color_green; break; case 2: // +Hostile required_string("+Hostile"); Tagged_Colors[tag] = &Brief_color_red; break; case 3: // +Neutral required_string("+Neutral"); Tagged_Colors[tag] = &Brief_color_legacy_neutral; break; case -1: // -noparseerrors is set if (Tagged_Colors.find(tag) == Tagged_Colors.end()) { // It was a new color, but since we haven't actually defined it... Color_Tags.pop_back(); } break; default: Assertion(false, "MageKing17 made a coding error somewhere, and you should laugh at him (and report this error).\n"); break; } } required_string("#End"); } Assertion(Color_Tags.size() == Tagged_Colors.size(), "Color_Tags and Tagged_Colors size mismatch; get a coder!\n"); if (optional_string("#Default Text Colors")) { char* color_names[MAX_DEFAULT_TEXT_COLORS] = { "$Fiction Viewer:", "$Command Briefing:", "$Briefing:", "$Redalert Briefing:", "$Debriefing:", "$Recommendation:", "$Loop Briefing:", }; char *color_value[MAX_DEFAULT_TEXT_COLORS] = { &default_fiction_viewer_color, &default_command_briefing_color, &default_briefing_color, &default_redalert_briefing_color, &default_debriefing_color, &default_recommendation_color, &default_loop_briefing_color, }; for (i = 0; i < MAX_DEFAULT_TEXT_COLORS; i++) { if ( optional_string(color_names[i]) ) { stuff_string(temp, F_RAW); if (temp[0] == '$') { if (temp[1] == '\0') { Error(LOCATION, "%s - default text color '%s' entry with a solitary '$'.\n", filename, color_names[i]); } *color_value[i] = temp[1]; if (temp[2] != '\0') { Warning(LOCATION, "%s - default text color '%s' has extra text after the tag '$%c'.\n", filename, color_names[i], *color_value[i]); } } else if (temp[0] == '\0') { Error(LOCATION, "%s - default text color '%s' entry with no tag.\n", filename, color_names[i]); } else { *color_value[i] = temp[0]; if (temp[1] != '\0') { Warning(LOCATION, "%s - default text color '%s' has extra text after the tag '$%c'.\n", filename, color_names[i], *color_value[i]); } } if (Tagged_Colors.find(*color_value[i]) == Tagged_Colors.end()) { // Just mprintf() this information instead of complaining with a Warning(); the tag might be defined in a later-loading TBM, and if it isn't, nothing too terrible will happen. mprintf(("%s - default text color '%s' set to non-existant tag '$%c'.\n", filename, color_names[i], *color_value[i])); } } } required_string("#End"); } }
static bool opengl_post_init_table() { bool warned = false; try { if (cf_exists_full("post_processing.tbl", CF_TYPE_TABLES)) read_file_text("post_processing.tbl", CF_TYPE_TABLES); else read_file_text_from_default(defaults_get_file("post_processing.tbl")); reset_parse(); if (optional_string("#Effects")) { while (!required_string_one_of(3, "$Name:", "#Ship Effects", "#End")) { char tbuf[NAME_LENGTH + 1] = { 0 }; post_effect_t eff; required_string("$Name:"); stuff_string(tbuf, F_NAME, NAME_LENGTH); eff.name = tbuf; required_string("$Uniform:"); stuff_string(tbuf, F_NAME, NAME_LENGTH); eff.uniform_name = tbuf; required_string("$Define:"); stuff_string(tbuf, F_NAME, NAME_LENGTH); eff.define_name = tbuf; required_string("$AlwaysOn:"); stuff_boolean(&eff.always_on); required_string("$Default:"); stuff_float(&eff.default_intensity); eff.intensity = eff.default_intensity; required_string("$Div:"); stuff_float(&eff.div); required_string("$Add:"); stuff_float(&eff.add); // Post_effects index is used for flag checks, so we can't have more than 32 if (Post_effects.size() < 32) { Post_effects.push_back(eff); } else if (!warned) { mprintf(("WARNING: post_processing.tbl can only have a max of 32 effects! Ignoring extra...\n")); warned = true; } } } //Built-in per-ship effects ship_effect se1; strcpy_s(se1.name, "FS1 Ship select"); se1.shader_effect = 0; se1.disables_rendering = false; se1.invert_timer = false; Ship_effects.push_back(se1); if (optional_string("#Ship Effects")) { while (!required_string_one_of(3, "$Name:", "#Light Shafts", "#End")) { ship_effect se; char tbuf[NAME_LENGTH] = { 0 }; required_string("$Name:"); stuff_string(tbuf, F_NAME, NAME_LENGTH); strcpy_s(se.name, tbuf); required_string("$Shader Effect:"); stuff_int(&se.shader_effect); required_string("$Disables Rendering:"); stuff_boolean(&se.disables_rendering); required_string("$Invert timer:"); stuff_boolean(&se.invert_timer); Ship_effects.push_back(se); } } if (optional_string("#Light Shafts")) { required_string("$AlwaysOn:"); stuff_boolean(&ls_on); required_string("$Density:"); stuff_float(&ls_density); required_string("$Falloff:"); stuff_float(&ls_falloff); required_string("$Weight:"); stuff_float(&ls_weight); required_string("$Intensity:"); stuff_float(&ls_intensity); required_string("$Sample Number:"); stuff_int(&ls_samplenum); ls_cpintensity = ls_weight; for (int i = 1; i < ls_samplenum; i++) ls_cpintensity += ls_weight * pow(ls_falloff, i); ls_cpintensity *= ls_intensity; } required_string("#End"); return true; } catch (const parse::ParseException& e) { mprintf(("Unable to parse 'post_processing.tbl'! Error message = %s.\n", e.what())); return false; } }