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"); } }
void parse_species_tbl(const char *filename) { int i, rval; char species_name[NAME_LENGTH]; if ((rval = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", (filename) ? filename : NOX("<default species_defs.tbl>"), rval)); return; } if (filename == NULL) read_file_text_from_array(defaults_get_file("species_defs.tbl")); else read_file_text(filename, CF_TYPE_TABLES); reset_parse(); // start parsing required_string("#SPECIES DEFS"); // no longer required: counted automatically if (optional_string("$NumSpecies:")) { int temp; stuff_int(&temp); } // begin reading data while (required_string_either("#END","$Species_Name:")) { bool no_create = false; species_info *species, new_species; species = &new_species; // Start Species - Get its name required_string("$Species_Name:"); stuff_string(species_name, F_NAME, NAME_LENGTH); if (optional_string("+nocreate")) { no_create = true; for (i = 0; i < (int)Species_info.size(); i++) { if (!stricmp(Species_info[i].species_name, species_name)) { species = &Species_info[i]; break; } } } else { strcpy_s(species->species_name, species_name); } // Goober5000 - IFF if (optional_string("$Default IFF:")) { bool iff_found = false; char temp_name[NAME_LENGTH]; stuff_string(temp_name, F_NAME, NAME_LENGTH); // search for it in iffs for (int iLoop = 0; iLoop < Num_iffs; iLoop++) { if (!stricmp(Iff_info[iLoop].iff_name, temp_name)) { species->default_iff = iLoop; iff_found = true; } } if (!iff_found) { species->default_iff = 0; Warning(LOCATION, "Species %s default IFF %s not found in iff_defs.tbl! Defaulting to %s.\n", species->species_name, temp_name, Iff_info[species->default_iff].iff_name); } } else if (!no_create) { // we have no idea which it could be, so default to 0 species->default_iff = 0; // let them know Warning(LOCATION, "$Default IFF not specified for species %s in species_defs.tbl! Defaulting to %s.\n", species->species_name, Iff_info[species->default_iff].iff_name); } // Goober5000 - FRED color if (optional_string("$FRED Color:") || optional_string("$FRED Colour:")) { stuff_int_list(species->fred_color.a1d, 3, RAW_INTEGER_TYPE); } else if (!no_create) { // set defaults to Volition's originals if (!stricmp(species->species_name, "Terran")) { species->fred_color.rgb.r = 0; species->fred_color.rgb.g = 0; species->fred_color.rgb.b = 192; } else if (!stricmp(species->species_name, "Vasudan")) { species->fred_color.rgb.r = 0; species->fred_color.rgb.g = 128; species->fred_color.rgb.b = 0; } else if (!stricmp(species->species_name, "Shivan")) { species->fred_color.rgb.r = 192; species->fred_color.rgb.g = 0; species->fred_color.rgb.b = 0; } else if (!stricmp(species->species_name, "Ancients") || !stricmp(species->species_name, "Ancient")) { species->fred_color.rgb.r = 192; species->fred_color.rgb.g = 0; species->fred_color.rgb.b = 192; } else { species->fred_color.rgb.r = 0; species->fred_color.rgb.g = 0; species->fred_color.rgb.b = 0; } // let them know Warning(LOCATION, "$FRED Color not specified for species %s in species_defs.tbl! Defaulting to (%d, %d, %d).\n", species->species_name, species->fred_color.rgb.r, species->fred_color.rgb.g, species->fred_color.rgb.b); } // stuff optional_string("$MiscAnims:"); // Get its Debris Texture if ((!no_create && required_string("+Debris_Texture:")) || optional_string("+Debris_Texture:")) { generic_bitmap_init(&species->debris_texture, NULL); stuff_string(species->debris_texture.filename, F_NAME, MAX_FILENAME_LEN); } // Shield Hit Animation if (optional_string("+Shield_Hit_ani:")) // Shouldn't be required -- LPine { generic_anim_init(&species->shield_anim, NULL); stuff_string(species->shield_anim.filename, F_NAME, MAX_FILENAME_LEN); } else if (!no_create) { species->shield_anim.filename[0] = '\0'; species->shield_anim.first_frame = -1; // Landmine to trip up anyone who does end up using this } // Thruster Anims parse_thrust_anims(species, no_create); // Thruster Glow Anims parse_thrust_glows(species, no_create); // Goober5000 - AWACS multiplier if (optional_string("$AwacsMultiplier:")) { stuff_float(&species->awacs_multiplier); } else if (!no_create) { // set defaults to Volition's originals if (!stricmp(species->species_name, "Vasudan")) species->awacs_multiplier = 1.25f; else if (!stricmp(species->species_name, "Shivan")) species->awacs_multiplier = 1.50f; else species->awacs_multiplier = 1.0f; // let them know Warning(LOCATION, "$AwacsMultiplier not specified for species %s in species_defs.tbl! Defaulting to %.2d.\n", species->species_name, species->awacs_multiplier); } // Goober5000 - countermeasure type // (we won't be able to resolve it until after we've parsed the weapons table) if (optional_string("$Countermeasure type:")) stuff_string(species->cmeasure_name, F_NAME, NAME_LENGTH); // don't add new entry if this is just a modified one if ( !no_create ) Species_info.push_back( new_species ); } required_string("#END"); // add tbl/tbm to multiplayer validation list extern void fs2netd_add_table_validation(const char *tblname); fs2netd_add_table_validation(filename); }
void parse_colors(const char *filename) { Assertion(filename != NULL, "parse_colors() 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(); // we search for the colors based on their order of definition above // if the color isn't found, we just use default values if (optional_string("#Start Colors")) { // vars for holding rgba values int rgba[4] = {0,0,0,0}; int i, j; char* color_names[TOTAL_COLORS] = { "$Blue:", "$Bright Blue:", "$Green:", "$Bright Green:", "$Black:", "$Grey:", "$Silver:", "$White:", "$Bright White:", "$Violet Gray:", "$Violet:", "$Dim Red:", "$Red:", "$Bright Red:", "$Pink:", "$Light Pink:", "$Yellow:", "$Bright Yellow:", "$UI Light Green:", "$UI Green:", "$UI Light Pink:", "$UI Pink:" }; // now for each color, check if it's corresponding string is there for (i = 0; i < TOTAL_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("(")) { 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; } } //} else { // stuff_hex_list(rgba, 4); //} gr_init_alphacolor(COLOR_LIST[i], rgba[0], rgba[1], rgba[2], rgba[3]); } } required_string("#End"); } }
/** * Parse the table */ void iff_init() { char traitor_name[NAME_LENGTH]; char attack_names[MAX_IFFS][MAX_IFFS][NAME_LENGTH]; struct { char iff_name[NAME_LENGTH]; int color_index; } observed_color_table[MAX_IFFS][MAX_IFFS]; int num_attack_names[MAX_IFFS]; int num_observed_colors[MAX_IFFS]; int i, j, k; int string_idx; try { // Goober5000 - if table doesn't exist, use the default table if (cf_exists_full("iff_defs.tbl", CF_TYPE_TABLES)) read_file_text("iff_defs.tbl", CF_TYPE_TABLES); else read_file_text_from_array(defaults_get_file("iff_defs.tbl")); reset_parse(); // parse the table -------------------------------------------------------- required_string("#IFFs"); // get the traitor required_string("$Traitor IFF:"); stuff_string(traitor_name, F_NAME, NAME_LENGTH); int rgb[3]; // check if alternate colours are wanted to be used for these // Marks various stuff... like asteroids if ((optional_string("$Selection Color:")) || (optional_string("$Selection Colour:"))) { stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); iff_init_color(rgb[0], rgb[1], rgb[2]); } else iff_init_color(0xff, 0xff, 0xff); // Marks the ship currently saying something if ((optional_string("$Message Color:")) || (optional_string("$Message Colour:"))) { stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); iff_init_color(rgb[0], rgb[1], rgb[2]); } else iff_init_color(0x7f, 0x7f, 0x7f); // Marks the tagged ships if ((optional_string("$Tagged Color:")) || (optional_string("$Tagged Colour:"))) { stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); iff_init_color(rgb[0], rgb[1], rgb[2]); } else iff_init_color(0xff, 0xff, 0x00); // init radar blips colour table int a_bright, a_dim; bool alternate_blip_color = false; for (i = 0; i < 5; i++) { for (j = 0; j < 2; j++) { for (k = 0; k < 3; k++) { radar_iff_color[i][j][k] = -1; } } } // if the bright/dim scaling is wanted to be changed if (optional_string("$Dimmed IFF brightness:")) { int dim_iff_brightness; stuff_int(&dim_iff_brightness); Assert(dim_iff_brightness >= 0 && dim_iff_brightness <= HUD_COLOR_ALPHA_MAX); *iff_color_brightness = dim_iff_brightness; } else *iff_color_brightness = 4; // alternate = use same method as with ship blips // retail = use 1/2 intensities if (optional_string("$Use Alternate Blip Coloring:") || optional_string("$Use Alternate Blip Colouring:")) { stuff_boolean(&alternate_blip_color); } // Parse blip colours, their order is hardcoded. if ((optional_string("$Missile Blip Color:")) || (optional_string("$Missile Blip Colour:"))) { stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); for (i = 0; i < 3; i++) { Assert(rgb[i] >= 0 && rgb[i] <= 255); radar_iff_color[0][1][i] = rgb[i]; radar_iff_color[0][0][i] = rgb[i] / 2; } } if ((optional_string("$Navbuoy Blip Color:")) || (optional_string("$Navbuoy Blip Colour:"))) { stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); for (i = 0; i < 3; i++) { Assert(rgb[i] >= 0 && rgb[i] <= 255); radar_iff_color[1][1][i] = rgb[i]; radar_iff_color[1][0][i] = rgb[i] / 2; } } if ((optional_string("$Warping Blip Color:")) || (optional_string("$Warping Blip Colour:"))) { stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); for (i = 0; i < 3; i++) { Assert(rgb[i] >= 0 && rgb[i] <= 255); radar_iff_color[2][1][i] = rgb[i]; radar_iff_color[2][0][i] = rgb[i] / 2; } } if ((optional_string("$Node Blip Color:")) || (optional_string("$Node Blip Colour:"))) { stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); for (i = 0; i < 3; i++) { Assert(rgb[i] >= 0 && rgb[i] <= 255); radar_iff_color[3][1][i] = rgb[i]; radar_iff_color[3][0][i] = rgb[i] / 2; } } if ((optional_string("$Tagged Blip Color:")) || (optional_string("$Tagged Blip Colour:"))) { stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); for (i = 0; i < 3; i++) { Assert(rgb[i] >= 0 && rgb[i] <= 255); radar_iff_color[4][1][i] = rgb[i]; radar_iff_color[4][0][i] = rgb[i] / 2; } } if (alternate_blip_color == true) { a_bright = iff_get_alpha_value(true); a_dim = iff_get_alpha_value(false); for (i = 0; i < 5; i++) { if (radar_iff_color[i][0][0] >= 0) { for (j = 0; j < 3; j++) { radar_iff_color[i][0][j] = radar_iff_color[i][1][j]; } radar_iff_color[i][1][3] = a_bright; radar_iff_color[i][0][3] = a_dim; } } } else { for (i = 0; i < 5; i++) { if (radar_iff_color[i][0][0] >= 0) { radar_iff_color[i][0][3] = 255; radar_iff_color[i][1][3] = 255; } } } if (optional_string("$Radar Target ID Flags:")) { parse_string_flag_list((int*)&radar_target_id_flags, rti_flags, Num_rti_flags); if (optional_string("+reset")) radar_target_id_flags = 0; } // begin reading data Num_iffs = 0; while (required_string_either("#End", "$IFF Name:")) { iff_info *iff; int cur_iff; // make sure we're under the limit if (Num_iffs >= MAX_IFFS) { Warning(LOCATION, "Too many iffs in iffs_defs.tbl! Max is %d.\n", MAX_IFFS); skip_to_start_of_string("#End", NULL); break; } // add new IFF iff = &Iff_info[Num_iffs]; cur_iff = Num_iffs; Num_iffs++; // get required IFF info ---------------------------------------------- // get the iff name required_string("$IFF Name:"); stuff_string(iff->iff_name, F_NAME, NAME_LENGTH); // get the iff color if (check_for_string("$Colour:")) required_string("$Colour:"); else required_string("$Color:"); stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); iff->color_index = iff_init_color(rgb[0], rgb[1], rgb[2]); // get relationships between IFFs ------------------------------------- // get the list of iffs attacked if (optional_string("$Attacks:")) num_attack_names[cur_iff] = stuff_string_list(attack_names[cur_iff], MAX_IFFS); else num_attack_names[cur_iff] = 0; // get the list of observed colors num_observed_colors[cur_iff] = 0; while (optional_string("+Sees")) { // get iff observed stuff_string_until(observed_color_table[cur_iff][num_observed_colors[cur_iff]].iff_name, "As:", NAME_LENGTH); required_string("As:"); // get color observed stuff_int_list(rgb, 3, RAW_INTEGER_TYPE); observed_color_table[cur_iff][num_observed_colors[cur_iff]].color_index = iff_init_color(rgb[0], rgb[1], rgb[2]); // increment num_observed_colors[cur_iff]++; } // get flags ---------------------------------------------------------- // get iff flags iff->flags = 0; if (optional_string("$Flags:")) { char flag_strings[MAX_IFF_FLAGS][NAME_LENGTH]; int num_strings = stuff_string_list(flag_strings, MAX_IFF_FLAGS); for (string_idx = 0; string_idx < num_strings; string_idx++) { if (!stricmp(NOX("support allowed"), flag_strings[string_idx])) iff->flags |= IFFF_SUPPORT_ALLOWED; else if (!stricmp(NOX("exempt from all teams at war"), flag_strings[string_idx])) iff->flags |= IFFF_EXEMPT_FROM_ALL_TEAMS_AT_WAR; else if (!stricmp(NOX("orders hidden"), flag_strings[string_idx])) iff->flags |= IFFF_ORDERS_HIDDEN; else if (!stricmp(NOX("orders shown"), flag_strings[string_idx])) iff->flags |= IFFF_ORDERS_SHOWN; else if (!stricmp(NOX("wing name hidden"), flag_strings[string_idx])) iff->flags |= IFFF_WING_NAME_HIDDEN; else Warning(LOCATION, "Bogus string in iff flags: %s\n", flag_strings[string_idx]); } } // get default ship flags iff->default_parse_flags = 0; if (optional_string("$Default Ship Flags:")) { i = 0; j = 0; char flag_strings[MAX_PARSE_OBJECT_FLAGS][NAME_LENGTH]; int num_strings = stuff_string_list(flag_strings, MAX_PARSE_OBJECT_FLAGS); for (i = 0; i < num_strings; i++) { for (j = 0; j < MAX_PARSE_OBJECT_FLAGS; j++) { if (!stricmp(flag_strings[i], Parse_object_flags[j])) { iff->default_parse_flags |= (1 << j); break; } } } if (j == MAX_PARSE_OBJECT_FLAGS) Warning(LOCATION, "Bogus string in iff default ship flags: %s\n", flag_strings[i]); } // again iff->default_parse_flags2 = 0; if (optional_string("$Default Ship Flags2:")) { i = 0; j = 0; char flag_strings[MAX_PARSE_OBJECT_FLAGS_2][NAME_LENGTH]; int num_strings = stuff_string_list(flag_strings, MAX_PARSE_OBJECT_FLAGS_2); for (i = 0; i < num_strings; i++) { for (j = 0; j < MAX_PARSE_OBJECT_FLAGS_2; j++) { if (!stricmp(flag_strings[i], Parse_object_flags_2[j])) { iff->default_parse_flags2 |= (1 << j); break; } } } if (j == MAX_PARSE_OBJECT_FLAGS_2) Warning(LOCATION, "Bogus string in iff default ship flags2: %s\n", flag_strings[i]); } // this is cleared between each level but let's just set it here for thoroughness iff->ai_rearm_timestamp = timestamp(-1); } required_string("#End"); // now resolve the relationships ------------------------------------------ // first get the traitor Iff_traitor = iff_lookup(traitor_name); if (Iff_traitor < 0) { Iff_traitor = 0; Warning(LOCATION, "Traitor IFF %s not found in iff_defs.tbl! Defaulting to %s.\n", traitor_name, Iff_info[Iff_traitor].iff_name); } // next get the attackees and colors for (int cur_iff = 0; cur_iff < Num_iffs; cur_iff++) { iff_info *iff = &Iff_info[cur_iff]; // clear the iffs to be attacked iff->attackee_bitmask = 0; iff->attackee_bitmask_all_teams_at_war = 0; // clear the observed colors for (j = 0; j < MAX_IFFS; j++) iff->observed_color_index[j] = -1; // resolve the list names for (int list_index = 0; list_index < MAX_IFFS; list_index++) { // are we within the number of attackees listed? if (list_index < num_attack_names[cur_iff]) { // find out who int target_iff = iff_lookup(attack_names[cur_iff][list_index]); // valid? if (target_iff >= 0) iff->attackee_bitmask |= iff_get_mask(target_iff); else Warning(LOCATION, "Attack target IFF %s not found for IFF %s in iff_defs.tbl!\n", attack_names[cur_iff][list_index], iff->iff_name); } // are we within the number of colors listed? if (list_index < num_observed_colors[cur_iff]) { // find out who int target_iff = iff_lookup(observed_color_table[cur_iff][list_index].iff_name); // valid? if (target_iff >= 0) iff->observed_color_index[target_iff] = observed_color_table[cur_iff][list_index].color_index; else Warning(LOCATION, "Observed color IFF %s not found for IFF %s in iff_defs.tbl!\n", observed_color_table[cur_iff][list_index].iff_name, iff->iff_name); } } // resolve the all teams at war relationships if (iff->flags & IFFF_EXEMPT_FROM_ALL_TEAMS_AT_WAR) { // exempt, so use standard attacks iff->attackee_bitmask_all_teams_at_war = iff->attackee_bitmask; } else { // nonexempt, so build bitmask of all other nonexempt teams for (int other_iff = 0; other_iff < Num_iffs; other_iff++) { // skip myself (unless I attack myself normally) if ((other_iff == cur_iff) && !iff_x_attacks_y(cur_iff, cur_iff)) continue; // skip anyone exempt if (Iff_info[other_iff].flags & IFFF_EXEMPT_FROM_ALL_TEAMS_AT_WAR) continue; // add everyone else iff->attackee_bitmask_all_teams_at_war |= iff_get_mask(other_iff); } } } // add tbl/tbm to multiplayer validation list extern void fs2netd_add_table_validation(const char *tblname); fs2netd_add_table_validation("iff_defs.tbl"); } catch (const parse::ParseException& e) { mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "iff_defs.tbl", e.what())); return; } }