// game init void ssm_init() { int rval; ssm_info bogus, *s; char weapon_name[NAME_LENGTH]; if ((rval = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "ssm.tbl", rval)); return; } read_file_text("ssm.tbl", CF_TYPE_TABLES); reset_parse(); // parse the table Ssm_info_count = 0; while (!optional_string("#end")) { // another ssm definition if (optional_string("$SSM:")) { // pointer to info struct if (Ssm_info_count >= MAX_SSM_TYPES) { s = &bogus; } else { s = &Ssm_info[Ssm_info_count]; } // name stuff_string(s->name, F_NAME, NAME_LENGTH); // stuff data required_string("+Weapon:"); stuff_string(weapon_name, F_NAME, NAME_LENGTH); required_string("+Count:"); stuff_int(&s->count); required_string("+WarpRadius:"); stuff_float(&s->warp_radius); required_string("+WarpTime:"); stuff_float(&s->warp_time); required_string("+Radius:"); stuff_float(&s->radius); required_string("+Offset:"); stuff_float(&s->offset); // see if we have a valid weapon s->weapon_info_index = -1; s->weapon_info_index = weapon_name_lookup(weapon_name); if (s->weapon_info_index >= 0) { // valid Ssm_info_count++; } } } }
EffectTiming EffectTiming::parseTiming() { EffectTiming timing; if (optional_string("+Duration:")) { if (optional_string("Onetime")) { timing.m_duration = Duration::Onetime; } else if (optional_string("Always")) { timing.m_duration = Duration::Always; } else { timing.m_duration = Duration::Range; timing.m_durationRange = util::parseUniformRange<float>(false); } } if (optional_string("+Delay:")) { if (timing.m_duration == Duration::Onetime) { error_display(0, "+Delay is not valid for one-time effects!"); } else { timing.m_delayRange = util::parseUniformRange<float>(false); } } return timing; }
// initialization stuff for cutscenes void cutscene_init() { atexit(cutscene_close); char buf[MULTITEXT_LENGTH]; int rval; cutscene_info cutinfo; if ((rval = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "cutscenes.tbl", rval)); return; } read_file_text("cutscenes.tbl", CF_TYPE_TABLES); reset_parse(); // parse in all the cutscenes Cutscenes.clear(); skip_to_string("#Cutscenes"); ignore_white_space(); bool isFirstCutscene = true; while ( required_string_either("#End", "$Filename:") ) { required_string("$Filename:"); stuff_string( cutinfo.filename, F_PATHNAME, MAX_FILENAME_LEN ); required_string("$Name:"); stuff_string( cutinfo.name, F_NAME, NAME_LENGTH ); required_string("$Description:"); stuff_string(buf, F_MULTITEXT, sizeof(buf)); drop_white_space(buf); compact_multitext_string(buf); cutinfo.description = vm_strdup(buf); if (optional_string("$cd:")) stuff_int( &cutinfo.cd ); else cutinfo.cd = 0; cutinfo.viewable = false; if (isFirstCutscene) { isFirstCutscene = false; // The original code assumes the first movie is the intro, so always viewable cutinfo.viewable = true; } if (optional_string("$Always Viewable:")) { stuff_boolean(&cutinfo.viewable); } Cutscenes.push_back(cutinfo); } required_string("#End"); }
// initialize neb2 stuff at game startup void neb2_init() { char name[MAX_FILENAME_LEN]; try { // read in the nebula.tbl read_file_text("nebula.tbl", CF_TYPE_TABLES); reset_parse(); // background bitmaps Neb2_bitmap_count = 0; while (!optional_string("#end")) { // nebula required_string("+Nebula:"); stuff_string(name, F_NAME, MAX_FILENAME_LEN); if (Neb2_bitmap_count < MAX_NEB2_BITMAPS) { strcpy_s(Neb2_bitmap_filenames[Neb2_bitmap_count++], name); } else { WarningEx(LOCATION, "nebula.tbl\nExceeded maximum number of nebulas (%d)!\nSkipping %s.", MAX_NEB2_BITMAPS, name); } } // poofs Neb2_poof_count = 0; while (!optional_string("#end")) { // nebula required_string("+Poof:"); stuff_string(name, F_NAME, MAX_FILENAME_LEN); if (Neb2_poof_count < MAX_NEB2_POOFS) { strcpy_s(Neb2_poof_filenames[Neb2_poof_count++], name); } else { WarningEx(LOCATION, "nebula.tbl\nExceeded maximum number of nebula poofs (%d)!\nSkipping %s.", MAX_NEB2_POOFS, name); } } // should always have 6 neb poofs Assert(Neb2_poof_count == 6); } catch (const parse::ParseException& e) { mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "nebula.tbl", e.what())); return; } }
void palman_load_pixels() { int rval; if ((rval = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "pixels.tbl", rval)); return; } // open pixels.tbl read_file_text("pixels.tbl"); reset_parse(); // parse pixels while(!optional_string("#END")){ // nondarkening pixel if(required_string("+ND")){ stuff_ubyte(&Palman_non_darkening_default[Palman_num_nondarkening_default][0]); stuff_ubyte(&Palman_non_darkening_default[Palman_num_nondarkening_default][1]); stuff_ubyte(&Palman_non_darkening_default[Palman_num_nondarkening_default++][2]); } } // set this to be the active table palman_set_nondarkening(Palman_non_darkening_default, Palman_num_nondarkening_default); }
ParticleEffectIndex parseEffectElement(EffectType forcedType, const SCP_string& name) { if (!optional_string("$New Effect")) { SCP_string newName; stuff_string(newName, F_NAME); auto index = ParticleManager::get()->getEffectByName(newName); if (index < 0) { error_display(0, "Unknown particle effect name '%s' encountered!", newName.c_str()); } if (forcedType != EffectType::Invalid) { // Validate the effect type auto effect = ParticleManager::get()->getEffect(index); if (effect->getType() != forcedType) { error_display(0, "Particle effect '%s' has the wrong effect type! Expected %s but was %s!", getEffectTypeName(forcedType), getEffectTypeName(effect->getType())); } } return index; } if (forcedType == EffectType::Invalid) { forcedType = parseEffectType(); } auto effect = constructEffect(name, forcedType); return ParticleManager::get()->addEffect(effect); }
/** * CommanderDJ - Parse a list of sounds. When using this function for a table entry, * required_string and optional_string aren't needed, as this function deals with * that as its tag parameter, just make sure that the destination sound index(es) can * handle -1 if things don't work out. * * @param destination Vector where sound indexes are to be stored * @param tag Tag * @param object_name Name of object being parsed * @param flags See the parse_sound_flags enum * */ void parse_sound_list(const char* tag, SCP_vector<int>& destination, const char* object_name, parse_sound_flags flags) { if(optional_string(tag)) { int check=0; //if we're using the old format, parse the first entry separately if(!(flags & PARSE_SOUND_SCP_SOUND_LIST)) { stuff_int(&check); } //now read the rest of the entries on the line for(size_t i=0; !check_for_eoln(); i++) { char buf[MAX_FILENAME_LEN]; stuff_string_white(buf, MAX_FILENAME_LEN); //we do this conditionally to avoid adding needless entries when reparsing if(destination.size() <= i) { destination.push_back(-1); } parse_sound_core(tag, &destination.at(i), object_name, buf, flags); } //if we're using the old format, double check the size) if(!(flags & PARSE_SOUND_SCP_SOUND_LIST) && (destination.size() != (unsigned)check)) { mprintf(("%s in '%s' has " SIZE_T_ARG " entries. This does not match entered size of %i.", tag, object_name, destination.size(), check)); } } }
void parse_rank_tbl() { atexit(scoreing_close); char buf[MULTITEXT_LENGTH]; int rval, idx, persona; if ((rval = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "rank.tbl", rval)); return; } read_file_text("rank.tbl", CF_TYPE_TABLES); reset_parse(); // parse in all the rank names idx = 0; skip_to_string("[RANK NAMES]"); ignore_white_space(); while ( required_string_either("#End", "$Name:") ) { Assert ( idx < NUM_RANKS ); required_string("$Name:"); stuff_string( Ranks[idx].name, F_NAME, NAME_LENGTH ); required_string("$Points:"); stuff_int( &Ranks[idx].points ); required_string("$Bitmap:"); stuff_string( Ranks[idx].bitmap, F_NAME, MAX_FILENAME_LEN ); required_string("$Promotion Voice Base:"); stuff_string( Ranks[idx].promotion_voice_base, F_NAME, MAX_FILENAME_LEN ); while (check_for_string("$Promotion Text:")) { required_string("$Promotion Text:"); stuff_string(buf, F_MULTITEXT, sizeof(buf)); drop_white_space(buf); compact_multitext_string(buf); persona = -1; if (optional_string("+Persona:")) { stuff_int(&persona); if (persona < 0) { Warning(LOCATION, "Debriefing text for %s rank is assigned to an invalid persona: %i (must be 0 or greater).\n", Ranks[idx].name, persona); continue; } } Ranks[idx].promotion_text[persona] = vm_strdup(buf); } if (Ranks[idx].promotion_text.find(-1) == Ranks[idx].promotion_text.end()) { Warning(LOCATION, "%s rank is missing default debriefing text.\n", Ranks[idx].name); Ranks[idx].promotion_text[-1] = ""; } idx++; } required_string("#End"); // be sure that all rank points are in order #ifndef NDEBUG for ( idx = 0; idx < NUM_RANKS-1; idx++ ) { if ( Ranks[idx].points >= Ranks[idx+1].points ) Int3(); } #endif }
// game init void ssm_init() { ssm_info bogus, *s; char weapon_name[NAME_LENGTH+1] = ""; read_file_text("ssm.tbl"); reset_parse(); // parse the table Ssm_info_count = 0; while(!optional_string("#end")){ // another ssm definition if(optional_string("$SSM:")){ // pointer to info struct if(Ssm_info_count >= MAX_SSM_TYPES){ s = &bogus; } else { s = &Ssm_info[Ssm_info_count]; } // name stuff_string(s->name, F_NAME, NULL); // stuff data required_string("+Weapon:"); stuff_string(weapon_name, F_NAME, NULL); required_string("+Count:"); stuff_int(&s->count); required_string("+WarpRadius:"); stuff_float(&s->warp_radius); required_string("+WarpTime:"); stuff_float(&s->warp_time); required_string("+Radius:"); stuff_float(&s->radius); required_string("+Offset:"); stuff_float(&s->offset); // see if we have a valid weapon s->weapon_info_index = -1; s->weapon_info_index = weapon_name_lookup(weapon_name); if(s->weapon_info_index >= 0){ // valid Ssm_info_count++; } } } }
//============================================================================== //! //============================================================================== inline string_ref require_string(cref value) { auto const result = optional_string(value); if (!result) { BK_TODO_FAIL(); //throw expected string, got <x> } return *result; }
bool required_string_if_new(const char* token, bool no_create) { if (no_create) { return optional_string(token) == 1; } required_string(token); return true; }
// utility void set_flag(ai_profile_t *profile, const char *name, AI::Profile_Flags flag) { if (optional_string(name)) { bool val; stuff_boolean(&val); profile->flags.set(flag, val); } }
void parse_thrust_glows(species_info *species, bool no_create) { if (!no_create) { required_string("$ThrustGlows:"); generic_anim_init(&species->thruster_info.glow.normal, NULL); generic_anim_init(&species->thruster_info.glow.afterburn, NULL); } else if (!optional_string("$ThrustGlows:")) { return; } if (no_create) { if (optional_string("+Normal:")) stuff_string(species->thruster_info.glow.normal.filename, F_NAME, MAX_FILENAME_LEN); } else { required_string("+Normal:"); stuff_string(species->thruster_info.glow.normal.filename, F_NAME, MAX_FILENAME_LEN); } // if no glow is wanted then clear it if ( !VALID_FNAME(species->thruster_info.glow.normal.filename) ) generic_anim_init(&species->thruster_info.glow.normal, NULL); if (no_create) { if (optional_string("+Afterburn:")) stuff_string(species->thruster_info.glow.afterburn.filename, F_NAME, MAX_FILENAME_LEN); } else { required_string("+Afterburn:"); stuff_string(species->thruster_info.glow.afterburn.filename, F_NAME, MAX_FILENAME_LEN); } // if no glow is wanted then clear it if ( !VALID_FNAME(species->thruster_info.glow.afterburn.filename) ) generic_anim_init(&species->thruster_info.glow.afterburn, NULL); }
/** * Parse a sound. When using this function for a table entry, * required_string and optional_string aren't needed, as this function deals with * that as its tag parameter, just make sure that the destination sound index can * handle -1 if things don't work out. * * @param tag Tag * @param idx_dest Sound index destination * @param object_name Object name being parsed * @param flags See the parse_sound_flags enum * */ void parse_sound(const char* tag, int *idx_dest, const char* object_name, parse_sound_flags flags) { if(optional_string(tag)) { char buf[MAX_FILENAME_LEN]; stuff_string(buf, F_NAME, MAX_FILENAME_LEN); parse_sound_core(tag, idx_dest, object_name, buf, flags); } }
void techroom_intel_init() { int rval, temp; static int inited = 0; if (inited) return; // open localization lcl_ext_open(); if ((rval = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "species.tbl", rval)); lcl_ext_close(); return; } read_file_text("species.tbl", CF_TYPE_TABLES); reset_parse(); Intel_info_size = 0; while (optional_string("$Entry:")) { Assert(Intel_info_size < MAX_INTEL_ENTRIES); if (Intel_info_size >= MAX_INTEL_ENTRIES) { mprintf(("TECHMENU: Too many intel entries!\n")); break; } Intel_info[Intel_info_size].flags = IIF_DEFAULT_VALUE; required_string("$Name:"); stuff_string(Intel_info[Intel_info_size].name, F_NAME, NAME_LENGTH); required_string("$Anim:"); stuff_string(Intel_info[Intel_info_size].anim_filename, F_NAME, NAME_LENGTH); required_string("$AlwaysInTechRoom:"); stuff_int(&temp); if (temp) { // set default to align with what we read - Goober5000 Intel_info[Intel_info_size].flags |= IIF_IN_TECH_DATABASE; Intel_info[Intel_info_size].flags |= IIF_DEFAULT_IN_TECH_DATABASE; } required_string("$Description:"); stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, TECH_INTEL_DESC_LEN); Intel_info_size++; } inited = 1; // close localization lcl_ext_close(); }
void techroom_intel_init() { int temp; static int inited = 0; if (inited) return; try { read_file_text("species.tbl", CF_TYPE_TABLES); reset_parse(); Intel_info_size = 0; while (optional_string("$Entry:")) { Assert(Intel_info_size < MAX_INTEL_ENTRIES); if (Intel_info_size >= MAX_INTEL_ENTRIES) { mprintf(("TECHMENU: Too many intel entries!\n")); break; } Intel_info[Intel_info_size].flags = IIF_DEFAULT_VALUE; required_string("$Name:"); stuff_string(Intel_info[Intel_info_size].name, F_NAME, NAME_LENGTH); required_string("$Anim:"); stuff_string(Intel_info[Intel_info_size].anim_filename, F_NAME, NAME_LENGTH); required_string("$AlwaysInTechRoom:"); stuff_int(&temp); if (temp) { // set default to align with what we read - Goober5000 Intel_info[Intel_info_size].flags |= IIF_IN_TECH_DATABASE; Intel_info[Intel_info_size].flags |= IIF_DEFAULT_IN_TECH_DATABASE; } required_string("$Description:"); stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, TECH_INTEL_DESC_LEN); Intel_info_size++; } inited = 1; } catch (const parse::ParseException& e) { mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "species.tbl", e.what())); return; } }
// parses the string.tbl to see which languages are supported. Doesn't read in any strings. void parse_stringstbl_quick(const char *filename) { lang_info language; int lang_idx; int i; read_file_text(filename, CF_TYPE_TABLES); reset_parse(); if (optional_string("#Supported Languages")) { while (required_string_either("#End","$Language:")) { required_string("$Language:"); stuff_string(language.lang_name, F_RAW, LCL_LANG_NAME_LEN + 1); required_string("+Extension:"); stuff_string(language.lang_ext, F_RAW, LCL_LANG_NAME_LEN + 1); required_string("+Special Character Index:"); stuff_ubyte(&language.special_char_indexes[0]); for (i = 1; i < LCL_MAX_FONTS; ++i) { // default to "none"/0 except for font03 which defaults to 176 // NOTE: fonts.tbl may override these values if (i == font::FONT3) { language.special_char_indexes[i] = 176; } else { language.special_char_indexes[i] = 0; } } lang_idx = -1; // see if we already have this language for (i = 0; i < (int)Lcl_languages.size(); i++) { if (!strcmp(Lcl_languages[i].lang_name, language.lang_name)) { strcpy_s(Lcl_languages[i].lang_ext, language.lang_ext); Lcl_languages[i].special_char_indexes[0] = language.special_char_indexes[0]; lang_idx = i; break; } } // if we have a new language, add it. if (lang_idx == -1) { Lcl_languages.push_back(language); } } } }
void gamesnd_parse_entry(game_snd *gs, bool no_create, SCP_vector<game_snd> *lookupVector) { SCP_string name; stuff_string(name, F_NAME, "\t \n"); if (!no_create) { if (lookupVector != NULL) { if (gamesnd_lookup_name(name.c_str(), *lookupVector) >= 0) { Warning(LOCATION, "Duplicate sound name \"%s\" found!", name.c_str()); } } gs->name = name; } else { int vectorIndex = gamesnd_lookup_name(name.c_str(), *lookupVector); if (vectorIndex < 0) { Warning(LOCATION, "No existing sound entry with name \"%s\" found!", name.c_str()); no_create = false; gs->name = name; } else { gs = &lookupVector->at(vectorIndex); } } if (optional_string("+Filename:")) { parse_gamesnd_new(gs, no_create); } else { parse_gamesnd_old(gs); } }
void palman_load_pixels() { // open pixels.tbl read_file_text("pixels.tbl"); reset_parse(); // parse pixels while(!optional_string("#END")){ // nondarkening pixel if(required_string("+ND")){ stuff_byte(&Palman_non_darkening_default[Palman_num_nondarkening_default][0]); stuff_byte(&Palman_non_darkening_default[Palman_num_nondarkening_default][1]); stuff_byte(&Palman_non_darkening_default[Palman_num_nondarkening_default++][2]); } } // set this to be the active table palman_set_nondarkening(Palman_non_darkening_default, Palman_num_nondarkening_default); }
// utility void set_flag(ai_profile_t *profile, char *name, int flag, int type) { if (optional_string(name)) { bool val; stuff_boolean(&val); if (type == AIP_FLAG) { if (val) profile->flags |= flag; else profile->flags &= ~flag; } else { if (val) profile->flags2 |= flag; else profile->flags2 &= ~flag; } } }
/** * Parse a sound effect entry by requiring the given tag at the beginning. * * @param gs The game_snd instance to fill in * @param tag The tag that's required before an entry * @param lookupVector If non-NULL used to look up @c +nocreate entries * * @return @c true when a new entry has been parsed and should be added to the list of known * entries. @c false otherwise, for example in case of @c +nocreate */ bool gamesnd_parse_line(game_snd *gs, const char *tag, SCP_vector<game_snd> *lookupVector = NULL) { Assertion(gs != NULL, "Invalid game_snd pointer passed to gamesnd_parse_line!"); required_string(tag); bool no_create = false; if (lookupVector != NULL) { if(optional_string("+nocreate")) { no_create = true; } } gamesnd_parse_entry(gs, no_create, lookupVector); return !no_create; }
void hud_shield_game_init() { char name[MAX_FILENAME_LEN+1] = ""; // read in hud.tbl read_file_text("hud.tbl"); reset_parse(); Hud_shield_filename_count = 0; required_string("#Shield Icons Begin"); while(!optional_string("#End")){ required_string("$Shield:"); stuff_string(name, F_NAME, NULL); // maybe store Assert(Hud_shield_filename_count < MAX_SHIELD_ICONS); if(Hud_shield_filename_count < MAX_SHIELD_ICONS){ strcpy(Hud_shield_filenames[Hud_shield_filename_count++], name); } } }
//Takes a tag, a sound index destination, and the object name being parsed //tag and object_name are mostly so that we can debug stuff //This also means you shouldn't use optional_string or required_string, //just make sure the destination sound index can handle -1 if things //don't work out. void parse_sound(char* tag, int* idx_dest, char* object_name) { char buf[MAX_FILENAME_LEN]; int idx; if (optional_string(tag)) { stuff_string(buf, F_NAME, MAX_FILENAME_LEN); idx = gamesnd_get_by_name(buf); if (idx != -1) (*idx_dest) = idx; else (*idx_dest) = atoi(buf); //Ensure sound is in range if ((*idx_dest) < -1 || (*idx_dest) >= Num_game_sounds) { Warning(LOCATION, "%s sound index out of range on '%s'. Must be between 0 and %d. Forcing to -1 (Nonexistant sound).\n", tag, object_name, Num_game_sounds); } } }
// parses help.tbl and populates help_overlaylist[] void parse_helptbl() { int overlay_id, currcount; char buf[HELP_MAX_STRING_LENGTH + 1]; int i, rval; // open localization lcl_ext_open(); if ((rval = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", HELP_OVERLAY_FILENAME, rval)); lcl_ext_close(); return; } read_file_text(HELP_OVERLAY_FILENAME, CF_TYPE_TABLES); // for each overlay... for (overlay_id = 0; overlay_id < MAX_HELP_OVERLAYS; overlay_id++) { reset_parse(); skip_to_string(help_overlay_section_names[overlay_id]); // 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; // read in all elements for this overlay while (!(check_for_string("$end"))) { if (optional_string("+pline")) { currcount = help_overlaylist[overlay_id].plinecount; int a, b; // temp vars to read in int before cast to float; if (currcount < HELP_MAX_ITEM) { // read number of pline vertices stuff_int(&help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount); // note that it is read into GR_640 // help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtxcount = help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount; // set equal to 1024 version vertex count to prevent bugs Assert(help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount <= HELP_MAX_PLINE_VERTICES); // get 640x480 vertex coordinates for (i = 0; i < help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount; i++) { stuff_int(&a); stuff_int(&b); help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[i].xyz.x = (float)a; help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[i].xyz.y = (float)b; help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[i].xyz.z = 0.0f; help_overlaylist[overlay_id].plinelist[GR_640][currcount].pvtx[i] = &help_overlaylist[ overlay_id].plinelist[GR_640][currcount].vtx[i]; } // get 1024x768 vertex coordinates for (i = 0; i < help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount; i++) { stuff_int(&a); stuff_int(&b); help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtx[i].xyz.x = (float)a; help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtx[i].xyz.y = (float)b; help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtx[i].xyz.z = 0.0f; help_overlaylist[overlay_id].plinelist[GR_1024][currcount].pvtx[i] = &help_overlaylist[ overlay_id].plinelist[GR_1024][currcount].vtx[i]; } } //mprintf(("Found pline - start location (%f,%f), end location (%f,%f)\n", help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[0].xyz.x, help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[0].xyz.y, help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[2].xyz.x, help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[2].xyz.y)); help_overlaylist[overlay_id].plinecount++; } else if (optional_string("+text")) { currcount = help_overlaylist[overlay_id].textcount; if (currcount < HELP_MAX_ITEM) { // get 640x480 coordinates stuff_int(&(help_overlaylist[overlay_id].textlist[GR_640][currcount].x_coord)); stuff_int(&(help_overlaylist[overlay_id].textlist[GR_640][currcount].y_coord)); // get 1024x768 coordinates stuff_int(&(help_overlaylist[overlay_id].textlist[GR_1024][currcount].x_coord)); stuff_int(&(help_overlaylist[overlay_id].textlist[GR_1024][currcount].y_coord)); // get string (always use the GR_640 one) stuff_string(buf, F_MESSAGE, sizeof(buf)); help_overlaylist[overlay_id].textlist[GR_640][currcount].string = vm_strdup(buf); //mprintf(("Found text %d on overlay %d - location (%d,%d) @ 640x480 :: location (%d,%d) @ 1024x768\n", currcount, overlay_id, help_overlaylist[overlay_id].textlist[GR_640][currcount].x_coord, help_overlaylist[overlay_id].textlist[GR_640][currcount].y_coord, help_overlaylist[overlay_id].textlist[GR_1024][currcount].x_coord, help_overlaylist[overlay_id].textlist[GR_1024][currcount].x_coord)); help_overlaylist[overlay_id].textcount++; } } else if (optional_string("+right_bracket")) { currcount = help_overlaylist[overlay_id].rbracketcount; if (currcount < HELP_MAX_ITEM) { // get 640x480 coordinates stuff_int(&(help_overlaylist[overlay_id].rbracketlist[GR_640][currcount].x_coord)); stuff_int(&(help_overlaylist[overlay_id].rbracketlist[GR_640][currcount].y_coord)); // get 1024x768 coordinates stuff_int(&(help_overlaylist[overlay_id].rbracketlist[GR_1024][currcount].x_coord)); stuff_int(&(help_overlaylist[overlay_id].rbracketlist[GR_1024][currcount].y_coord)); //mprintf(("Found rbracket %d on overlay %d - location (%d,%d) @ 640x480 :: location (%d,%d) @ 1024x768\n", currcount, overlay_id, help_overlaylist[overlay_id].rbracketlist[GR_640][currcount].x_coord, help_overlaylist[overlay_id].rbracketlist[GR_640][currcount].y_coord, help_overlaylist[overlay_id].rbracketlist[GR_1024][currcount].x_coord, help_overlaylist[overlay_id].rbracketlist[GR_1024][currcount].y_coord)); help_overlaylist[overlay_id].rbracketcount++; } } else if (optional_string("+left_bracket")) { currcount = help_overlaylist[overlay_id].lbracketcount; if (currcount < HELP_MAX_ITEM) { // get 640x480 coordinates stuff_int(&(help_overlaylist[overlay_id].lbracketlist[GR_640][currcount].x_coord)); stuff_int(&(help_overlaylist[overlay_id].lbracketlist[GR_640][currcount].y_coord)); // get 1024x768 coordinates stuff_int(&(help_overlaylist[overlay_id].lbracketlist[GR_1024][currcount].x_coord)); stuff_int(&(help_overlaylist[overlay_id].lbracketlist[GR_1024][currcount].y_coord)); //mprintf(("Found lbracket %d on overlay %d - location (%d,%d) @ 640x480 :: location (%d,%d) @ 1024x768\n", currcount, overlay_id, help_overlaylist[overlay_id].lbracketlist[GR_640][currcount].x_coord, help_overlaylist[overlay_id].lbracketlist[GR_640][currcount].y_coord, help_overlaylist[overlay_id].lbracketlist[GR_1024][currcount].x_coord, help_overlaylist[overlay_id].lbracketlist[GR_1024][currcount].y_coord)); help_overlaylist[overlay_id].lbracketcount++; } } else { // help.tbl is corrupt Assert(0); } // end if } // end while } // end for // close localization lcl_ext_close(); }
/** * @brief Parses controlconfigdefault.tbl, and overrides the default control configuration for each valid entry in the .tbl */ void control_config_common_load_overrides() { LoadEnumsIntoMaps(); try { if (cf_exists_full("controlconfigdefaults.tbl", CF_TYPE_TABLES)) { read_file_text("controlconfigdefaults.tbl", CF_TYPE_TABLES); } else { read_file_text_from_default(defaults_get_file("controlconfigdefaults.tbl")); } reset_parse(); // start parsing // TODO: Split this out into more helps. Too many tabs! while(optional_string("#ControlConfigOverride")) { config_item *cfg_preset = new config_item[CCFG_MAX + 1]; std::copy(Control_config, Control_config + CCFG_MAX + 1, cfg_preset); Control_config_presets.push_back(cfg_preset); SCP_string preset_name; if (optional_string("$Name:")) { stuff_string_line(preset_name); } else { preset_name = "<unnamed preset>"; } Control_config_preset_names.push_back(preset_name); while (required_string_either("#End","$Bind Name:")) { const int iBufferLength = 64; char szTempBuffer[iBufferLength]; required_string("$Bind Name:"); stuff_string(szTempBuffer, F_NAME, iBufferLength); const size_t cCntrlAryLength = sizeof(Control_config) / sizeof(Control_config[0]); for (size_t i = 0; i < cCntrlAryLength; ++i) { config_item& r_ccConfig = cfg_preset[i]; if (!strcmp(szTempBuffer, r_ccConfig.text)) { /** * short key_default; * short joy_default; * char tab; * bool hasXSTR; * char type; */ int iTemp; if (optional_string("$Key Default:")) { if (optional_string("NONE")) { r_ccConfig.key_default = (short)-1; } else { stuff_string(szTempBuffer, F_NAME, iBufferLength); r_ccConfig.key_default = (short)mKeyNameToVal[szTempBuffer]; } } if (optional_string("$Joy Default:")) { stuff_int(&iTemp); r_ccConfig.joy_default = (short)iTemp; } if (optional_string("$Key Mod Shift:")) { stuff_int(&iTemp); r_ccConfig.key_default |= (iTemp == 1) ? KEY_SHIFTED : 0; } if (optional_string("$Key Mod Alt:")) { stuff_int(&iTemp); r_ccConfig.key_default |= (iTemp == 1) ? KEY_ALTED : 0; } if (optional_string("$Key Mod Ctrl:")) { stuff_int(&iTemp); r_ccConfig.key_default |= (iTemp == 1) ? KEY_CTRLED : 0; } if (optional_string("$Category:")) { stuff_string(szTempBuffer, F_NAME, iBufferLength); r_ccConfig.tab = (char)mCCTabNameToVal[szTempBuffer]; } if (optional_string("$Has XStr:")) { stuff_int(&iTemp); r_ccConfig.hasXSTR = (iTemp == 1); } if (optional_string("$Type:")) { stuff_string(szTempBuffer, F_NAME, iBufferLength); r_ccConfig.type = (char)mCCTypeNameToVal[szTempBuffer]; } if (optional_string("+Disable")) { r_ccConfig.disabled = true; } if (optional_string("$Disable:")) { stuff_boolean(&r_ccConfig.disabled); } // Nerf the buffer now. szTempBuffer[0] = '\0'; } else if ((i + 1) == cCntrlAryLength) { error_display(1, "Bind Name not found: %s\n", szTempBuffer); advance_to_eoln(NULL); ignore_white_space(); return; } } } required_string("#End"); } } catch (const parse::ParseException& e) { mprintf(("TABLES: Unable to parse 'controlconfigdefaults.tbl'! Error message = %s.\n", e.what())); return; } // Overwrite the control config with the first preset that was found if (!Control_config_presets.empty()) { std::copy(Control_config_presets[0], Control_config_presets[0] + CCFG_MAX + 1, Control_config); } }
void credits_parse_table(const char* filename) { try { read_file_text(filename, CF_TYPE_TABLES); reset_parse(); // any metadata? if (optional_string("$Music:")) { stuff_string(Credits_music_name, F_NAME, NAME_LENGTH); } if (optional_string("$Number of Images:")) { int temp; stuff_int(&temp); if (temp > 0) Credits_num_images = temp; } if (optional_string("$Start Image Index:")) { stuff_int(&Credits_artwork_index); // bounds check if (Credits_artwork_index < 0) { Credits_artwork_index = 0; } else if (Credits_artwork_index >= Credits_num_images) { Credits_artwork_index = Credits_num_images - 1; } } if (optional_string("$Text scroll rate:")) { stuff_float(&Credits_scroll_rate); if (Credits_scroll_rate < 0.01f) Credits_scroll_rate = 0.01f; } if (optional_string("$Artworks display time:")) { stuff_float(&Credits_artwork_display_time); if (Credits_artwork_display_time < 0.01f) Credits_artwork_display_time = 0.01f; } if (optional_string("$Artworks fade time:")) { stuff_float(&Credits_artwork_fade_time); if (Credits_artwork_fade_time < 0.01f) Credits_artwork_fade_time = 0.01f; } if (optional_string("$SCP Credits position:")) { char mode[NAME_LENGTH]; stuff_string(mode, F_NAME, NAME_LENGTH); if (!stricmp(mode, "Start")) SCP_credits_position = START; else if (!stricmp(mode, "End")) SCP_credits_position = END; else Warning(LOCATION, "Unknown credits position mode \"%s\".", mode); } ignore_white_space(); SCP_string credits_text; SCP_string line; SCP_vector<int> charNum; SCP_vector<const char*> lines; int numLines = -1; bool first_run = true; while (!check_for_string_raw("#end")) { // Read in a line of text stuff_string_line(line); // This is a bit odd but it means if a total conversion uses different credits the // Volition credit won't happen // Also don't append the default credits anymore when there was already a parsed table if (first_run && !Credits_parsed && !line.compare(mod_check)) { credits_text.append(unmodified_credits); } first_run = false; if (line.empty()) { // If the line is empty then just append a newline, don't bother with splitting it first credits_text.append("\n"); } else { // split_str doesn't take care of this. charNum.clear(); // Split the string into multiple lines if it's too long numLines = split_str(line.c_str(), Credits_text_coords[gr_screen.res][2], charNum, lines, -1); // Make sure that we have valid data Assertion(lines.size() == (size_t)numLines, "split_str reported %d lines but vector contains " SIZE_T_ARG " entries!", numLines, lines.size()); Assertion(lines.size() <= charNum.size(), "Something has gone wrong while splitting strings. Got " SIZE_T_ARG " lines but only " SIZE_T_ARG " chacter lengths.", lines.size(), charNum.size()); // Now add all splitted lines to the credit text and append a newline to the end for (int i = 0; i < numLines; i++) { credits_text.append(SCP_string(lines[i], charNum[i])); credits_text.append("\n"); } } } Credit_text_parts.push_back(credits_text); Credits_parsed = true; } catch (const parse::ParseException& e) { mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what())); return; } }
// 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_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_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"); } }
void parse_medal_tbl() { int i; try { read_file_text("medals.tbl", CF_TYPE_TABLES); reset_parse(); required_string("#Medals"); // special background information if (optional_string("+Background Bitmap:")) { stuff_string(Medals_background_filename, F_NAME, NAME_LENGTH); } else { strcpy_s(Medals_background_filename, Default_medals_background_filename); } // special mask information if (optional_string("+Mask Bitmap:")) { stuff_string(Medals_mask_filename, F_NAME, NAME_LENGTH); } else { strcpy_s(Medals_mask_filename, Default_medals_mask_filename); } // configurable hotspot for the exit button if (optional_string("+Exit Button Hotspot Index:")) { stuff_int(&Exit_button_hotspot_override); } // special positioning for player callsign if (optional_string("+Callsign Position 640:")) { stuff_int(&Medals_callsign_coords[GR_640].x); stuff_int(&Medals_callsign_coords[GR_640].y); } else { Medals_callsign_coords[GR_640].x = Default_medals_callsign_coords[GR_640][0]; Medals_callsign_coords[GR_640].y = Default_medals_callsign_coords[GR_640][1]; } if (optional_string("+Callsign Position 1024:")) { stuff_int(&Medals_callsign_coords[GR_1024].x); stuff_int(&Medals_callsign_coords[GR_1024].y); } else { Medals_callsign_coords[GR_1024].x = Default_medals_callsign_coords[GR_1024][0]; Medals_callsign_coords[GR_1024].y = Default_medals_callsign_coords[GR_1024][1]; } // special positioning for medal label if (optional_string("+Label Position 640:")) { stuff_int(&Medals_label_coords[GR_640].x); stuff_int(&Medals_label_coords[GR_640].y); stuff_int(&Medals_label_coords[GR_640].w); } else { Medals_label_coords[GR_640].x = Default_medals_label_coords[GR_640][0]; Medals_label_coords[GR_640].y = Default_medals_label_coords[GR_640][1]; Medals_label_coords[GR_640].w = Default_medals_label_coords[GR_640][2]; } if (optional_string("+Label Position 1024:")) { stuff_int(&Medals_label_coords[GR_1024].x); stuff_int(&Medals_label_coords[GR_1024].y); stuff_int(&Medals_label_coords[GR_1024].w); } else { Medals_label_coords[GR_1024].x = Default_medals_label_coords[GR_1024][0]; Medals_label_coords[GR_1024].y = Default_medals_label_coords[GR_1024][1]; Medals_label_coords[GR_1024].w = Default_medals_label_coords[GR_1024][2]; } // parse in all the medal names Num_medals = 0; while (required_string_either("#End", "$Name:")) { medal_stuff temp_medal; medal_display_info temp_display; required_string("$Name:"); stuff_string(temp_medal.name, F_NAME, NAME_LENGTH); // is this rank? if so, save it if (!stricmp(temp_medal.name, "Rank")) Rank_medal_index = Num_medals; required_string("$Bitmap:"); stuff_string(temp_medal.bitmap, F_NAME, MAX_FILENAME_LEN); if (optional_string("+Position 640:")) { stuff_int(&temp_display.coords[GR_640].x); stuff_int(&temp_display.coords[GR_640].y); } else if (Num_medals < NUM_MEDALS_FS2) { temp_display.coords[GR_640].x = Default_medal_coords[GR_640][Num_medals][0]; temp_display.coords[GR_640].y = Default_medal_coords[GR_640][Num_medals][1]; } else { Warning(LOCATION, "No default GR_640 position for medal '%s'!", temp_medal.name); temp_display.coords[GR_640].x = 0; temp_display.coords[GR_640].y = 0; } if (optional_string("+Position 1024:")) { stuff_int(&temp_display.coords[GR_1024].x); stuff_int(&temp_display.coords[GR_1024].y); } else if (Num_medals < NUM_MEDALS_FS2) { temp_display.coords[GR_1024].x = Default_medal_coords[GR_1024][Num_medals][0]; temp_display.coords[GR_1024].y = Default_medal_coords[GR_1024][Num_medals][1]; } else { Warning(LOCATION, "No default GR_1024 position for medal '%s'!", temp_medal.name); temp_display.coords[GR_1024].x = 0; temp_display.coords[GR_1024].y = 0; } if (optional_string("+Debriefing Bitmap:")) { stuff_string(temp_medal.debrief_bitmap, F_NAME, MAX_FILENAME_LEN); } else if (Num_medals < NUM_MEDALS_FS2) { strcpy_s(temp_medal.debrief_bitmap, Default_debriefing_bitmaps[Num_medals]); } else { Warning(LOCATION, "No default debriefing bitmap for medal '%s'!", temp_medal.name); strcpy_s(temp_medal.debrief_bitmap, ""); } required_string("$Num mods:"); stuff_int(&temp_medal.num_versions); // this is dumb temp_medal.version_starts_at_1 = (Num_medals == Rank_medal_index); if (optional_string("+Version starts at 1:")) { stuff_boolean(&temp_medal.version_starts_at_1); } if (optional_string("+Available From Start:")) { stuff_boolean(&temp_medal.available_from_start); } // some medals are based on kill counts. When string +Num Kills: is present, we know that // this medal is a badge and should be treated specially if (optional_string("+Num Kills:")) { char buf[MULTITEXT_LENGTH]; int persona; stuff_int(&temp_medal.kills_needed); if (optional_string("$Wavefile 1:")) stuff_string(temp_medal.voice_base, F_NAME, MAX_FILENAME_LEN); if (optional_string("$Wavefile 2:")) stuff_string(temp_medal.voice_base, F_NAME, MAX_FILENAME_LEN); if (optional_string("$Wavefile Base:")) stuff_string(temp_medal.voice_base, F_NAME, MAX_FILENAME_LEN); while (check_for_string("$Promotion Text:")) { required_string("$Promotion Text:"); stuff_string(buf, F_MULTITEXT, sizeof(buf)); persona = -1; if (optional_string("+Persona:")) { stuff_int(&persona); if (persona < 0) { Warning(LOCATION, "Debriefing text for %s is assigned to an invalid persona: %i (must be 0 or greater).\n", temp_medal.name, persona); continue; } } temp_medal.promotion_text[persona] = SCP_string(buf); } if (temp_medal.promotion_text.find(-1) == temp_medal.promotion_text.end()) { Warning(LOCATION, "%s medal is missing default debriefing text.\n", temp_medal.name); temp_medal.promotion_text[-1] = ""; } } Medals.push_back(temp_medal); Medal_display_info.push_back(temp_display); Num_medals++; } required_string("#End"); // be sure that we know where the rank is if (Rank_medal_index < 0) { Warning(LOCATION, "Could not find the 'Rank' medal!"); Rank_medal_index = 0; } // be sure that the badges kill numbers show up in order //WMC - I don't think this is needed anymore due to my changes to post-mission functions //but I'm keeping it here to be sure. int prev_badge_kills = 0; for (i = 0; i < Num_medals; i++) { if (Medals[i].kills_needed < prev_badge_kills && Medals[i].kills_needed != 0) Error(LOCATION, "Badges must appear sorted by lowest kill # first in medals.tbl\nFind Allender for most information."); if (Medals[i].kills_needed > 0) prev_badge_kills = Medals[i].kills_needed; } } catch (const parse::ParseException& e) { mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "medals.tbl", e.what())); return; } }