Esempio n. 1
0
// 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++;
			}
		}
	}
}
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
}
Esempio n. 3
0
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);
		}
	}
}
Esempio n. 4
0
// -------------------------------------------------------------------------------------------------
// gamesnd_parse_soundstbl() will parse the sounds.tbl file, and load the specified sounds.
//
//
void gamesnd_parse_soundstbl()
{
	int		rval;
	int		num_game_sounds = 0;
	int		num_iface_sounds = 0;

	// open localization
	lcl_ext_open();

	gamesnd_init_sounds();

	if ((rval = setjmp(parse_abort)) != 0) {
		Error(LOCATION, "Unable to parse sounds.tbl!  Code = %i.\n", rval);
	}
	else {
		read_file_text("sounds.tbl");
		reset_parse();		
	}

	// Parse the gameplay sounds section
	required_string("#Game Sounds Start");
	while (required_string_either("#Game Sounds End","$Name:")) {
		Assert( num_game_sounds < MAX_GAME_SOUNDS);
		gamesnd_parse_line( &Snds[num_game_sounds], "$Name:" );
		num_game_sounds++;
	}
	required_string("#Game Sounds End");

	// Parse the interface sounds section
	required_string("#Interface Sounds Start");
	while (required_string_either("#Interface Sounds End","$Name:")) {
		Assert( num_iface_sounds < MAX_INTERFACE_SOUNDS);
		gamesnd_parse_line(&Snds_iface[num_iface_sounds], "$Name:");
		num_iface_sounds++;
	}
	required_string("#Interface Sounds End");

	// parse flyby sound section	
	required_string("#Flyby Sounds Start");

	// read 2 terran sounds
	gamesnd_parse_line(&Snds_flyby[SPECIES_TERRAN][0], "$Terran:");
	gamesnd_parse_line(&Snds_flyby[SPECIES_TERRAN][1], "$Terran:");

	// 2 vasudan sounds
	gamesnd_parse_line(&Snds_flyby[SPECIES_VASUDAN][0], "$Vasudan:");
	gamesnd_parse_line(&Snds_flyby[SPECIES_VASUDAN][1], "$Vasudan:");

	gamesnd_parse_line(&Snds_flyby[SPECIES_SHIVAN][0], "$Shivan:");
	gamesnd_parse_line(&Snds_flyby[SPECIES_SHIVAN][1], "$Shivan:");
	
	required_string("#Flyby Sounds End");

	// close localization
	lcl_ext_close();
}
Esempio n. 5
0
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);
}
/**
 * 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;
}
// 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++;
			}
		}
	}
}
Esempio n. 8
0
// -------------------------------------------------------------------------------------------------
// gamesnd_parse_line()
//
// Parse a sound effect line
//
void gamesnd_parse_line(game_snd *gs, char *tag)
{
	int is_3d;

	required_string(tag);
	stuff_int(&gs->sig);
	stuff_string(gs->filename, F_NAME, ",");
	if ( !stricmp(gs->filename,NOX("empty")) ) {
		gs->filename[0] = 0;
		advance_to_eoln(NULL);
		return;
	}
	Mp++;
	stuff_int(&gs->preload);
	stuff_float(&gs->default_volume);
	stuff_int(&is_3d);
	if ( is_3d ) {
		gs->flags |= GAME_SND_USE_DS3D;
		stuff_int(&gs->min);
		stuff_int(&gs->max);
	}
	advance_to_eoln(NULL);
}
/**
 * @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);
	}
}
Esempio n. 10
0
void parse_mod_table(const char *filename)
{
	int rval;
	// SCP_vector<SCP_string> lines;

	// open localization
	lcl_ext_open();

	if ((rval = setjmp(parse_abort)) != 0)
	{
		mprintf(("TABLES: Unable to parse '%s'!  Error code = %i.\n", (filename) ? filename : "<default game_settings.tbl>", rval));
		lcl_ext_close();
		return;
	}

	if (filename == NULL)
		read_file_text_from_array(defaults_get_file("game_settings.tbl"));
	else
		read_file_text(filename, CF_TYPE_TABLES);

	reset_parse();	

	// start parsing
	optional_string("#CAMPAIGN SETTINGS");

	if (optional_string("$Default Campaign File Name:")) {
		char temp[MAX_FILENAME_LEN];
		stuff_string(temp, F_NAME, MAX_FILENAME_LEN);

		// remove extension?
		if (drop_extension(temp)) {
			mprintf(("Game Settings Table: Removed extension on default campaign file name %s\n", temp));
		}

		// check length
		int maxlen = (MAX_FILENAME_LEN - 4);
		int len = strlen(temp);
		if (len > maxlen) {
			Warning(LOCATION, "Token too long: [%s].  Length = %i.  Max is %i.\n", temp, len, maxlen);
			temp[maxlen] = 0;
		}

		strcpy_s(Default_campaign_file_name, temp);
	}

	if (optional_string("#Ignored Campaign File Names")) {
		SCP_string campaign_name; 

		while (optional_string("$Campaign File Name:")) {
			stuff_string(campaign_name, F_NAME); 

			// remove extension?
			if (drop_extension(campaign_name)) {
				mprintf(("Game Settings Table: Removed extension on ignored campaign file name %s\n", campaign_name.c_str()));
			}

			Ignored_campaigns.push_back(campaign_name); 
		}
	}

	optional_string("#HUD SETTINGS");

	// how long should the game wait before displaying a directive?
	if (optional_string("$Directive Wait Time:")) {
		stuff_int(&Directive_wait_time);
	}

	if (optional_string("$Cutscene camera displays HUD:")) {
		stuff_boolean(&Cutscene_camera_displays_hud);
	}
	// compatibility
	if (optional_string("$Cutscene camera disables HUD:")) {
		mprintf(("Game Settings Table: \"$$Cutscene camera disables HUD\" is deprecated in favor of \"$Cutscene camera displays HUD\"\n"));
		bool temp;
		stuff_boolean(&temp);
		Cutscene_camera_displays_hud = !temp;
	}
	
	if (optional_string("$Full color head animations:")) {
		stuff_boolean(&Full_color_head_anis);
	}
	// compatibility
	if (optional_string("$Color head animations with hud colors:")) {
		mprintf(("Game Settings Table: \"$Color head animations with hud colors\" is deprecated in favor of \"$Full color head animations\"\n"));
		bool temp;
		stuff_boolean(&temp);
		Full_color_head_anis = !temp;
	}

	optional_string("#SEXP SETTINGS"); 

	if (optional_string("$Loop SEXPs Then Arguments:")) { 
		stuff_boolean(&True_loop_argument_sexps);
		if (True_loop_argument_sexps) {
			mprintf(("Game Settings Table: Using Reversed Loops For SEXP Arguments\n"));
		} else {
			mprintf(("Game Settings Table: Using Standard Loops For SEXP Arguments\n"));
		}
	}

	if (optional_string("$Use Alternate Chaining Behavior:")) {
		stuff_boolean(&Alternate_chaining_behavior);
		if (Alternate_chaining_behavior) {
			mprintf(("Game Settings Table: Using alternate event chaining behavior\n"));
		} else {
			mprintf(("Game Settings Table: Using standard event chaining behavior\n"));
		}
	}

	optional_string("#GRAPHICS SETTINGS");

	if (optional_string("$Enable External Shaders:")) {
		stuff_boolean(&Enable_external_shaders);
		if (Enable_external_shaders)
			mprintf(("Game Settings Table: External shaders are enabled\n"));
		else
			mprintf(("Game Settings Table: External shaders are DISABLED\n"));
	}

	if (optional_string("$Default Detail Level:")) {
		int detail_level;

		stuff_int(&detail_level);

		mprintf(("Game Settings Table: Setting default detail level to %i of %i-%i\n", detail_level, 0, NUM_DEFAULT_DETAIL_LEVELS-1));

		if (detail_level < 0 || detail_level > NUM_DEFAULT_DETAIL_LEVELS-1) {
			Warning(LOCATION, "Invalid detail level: %i, setting to %i\n", detail_level, Default_detail_level);
		} else {
			Default_detail_level = detail_level;
		}
	}
	
	optional_string("#NETWORK SETTINGS"); 

	if (optional_string("$FS2NetD port:")) {
		stuff_int(&FS2NetD_port);
		if (FS2NetD_port)
			mprintf(("Game Settings Table: FS2NetD connecting to port %i\n", FS2NetD_port));
	}

	optional_string("#OTHER SETTINGS"); 

	if (optional_string("$Fixed Turret Collisions:")) { 
		stuff_boolean(&Fixed_turret_collisions);
	}

	if (optional_string("$Damage Impacted Subsystem First:")) { 
		stuff_boolean(&Damage_impacted_subsystem_first);
	}

	if (optional_string("$Default ship select effect:")) {
		char effect[NAME_LENGTH];
		stuff_string(effect, F_NAME, NAME_LENGTH);
		if (!stricmp(effect, "FS2"))
			Default_ship_select_effect = 2;
		else if (!stricmp(effect, "FS1"))
			Default_ship_select_effect = 1;
		else if (!stricmp(effect, "off"))
			Default_ship_select_effect = 0;
	}

	if (optional_string("$Default weapon select effect:")) {
		char effect[NAME_LENGTH];
		stuff_string(effect, F_NAME, NAME_LENGTH);
		if (!stricmp(effect, "FS2"))
			Default_weapon_select_effect = 2;
		else if (!stricmp(effect, "FS1"))
			Default_weapon_select_effect = 1;
		else if (!stricmp(effect, "off"))
			Default_weapon_select_effect = 0;
	}

	if (optional_string("$Weapons inherit parent collision group:")) {
		stuff_boolean(&Weapons_inherit_parent_collision_group);
		if (Weapons_inherit_parent_collision_group)
			mprintf(("Game Settings Table: Weapons inherit parent collision group\n"));
	}

	if (optional_string("$Flight controls follow eyepoint orientation:")) {
		stuff_boolean(&Flight_controls_follow_eyepoint_orientation);
		if (Flight_controls_follow_eyepoint_orientation)
			mprintf(("Game Settings Table: Flight controls follow eyepoint orientation\n"));
	}

	required_string("#END");

	// close localization
	lcl_ext_close();
}
Esempio n. 11
0
void parse_ai_profiles_tbl(const char *filename)
{
	int i;
	char profile_name[NAME_LENGTH];
	ai_profile_t dummy_profile;
	char *saved_Mp = NULL;
	char buf[NAME_LENGTH];

	try
	{
		if (filename == NULL)
			read_file_text_from_default(defaults_get_file("ai_profiles.tbl"));
		else
			read_file_text(filename, CF_TYPE_TABLES);

		reset_parse();


		// start parsing
		required_string("#AI Profiles");

		// new default?
		if (optional_string("$Default Profile:"))
			stuff_string(Default_profile_name, F_NAME, NAME_LENGTH);

		// begin reading data
		while (required_string_either("#End", "$Profile Name:"))
		{
			ai_profile_t *profile = &dummy_profile;
			ai_profile_t *previous_profile = NULL;
			bool no_create = false;

			// get the name
			required_string("$Profile Name:");
			stuff_string(profile_name, F_NAME, NAME_LENGTH);

			// see if it exists
			for (i = 0; i < Num_ai_profiles; i++)
			{
				if (!stricmp(Ai_profiles[i].profile_name, profile_name))
				{
					previous_profile = &Ai_profiles[i];
					break;
				}
			}

			// modular table stuff
			if (optional_string("+nocreate"))
			{
				no_create = true;

				// use the previous one if possible,
				// otherwise continue to use the dummy one
				if (previous_profile != NULL)
					profile = previous_profile;
			}
			else
			{
				// don't create multiple profiles with the same name
				if (previous_profile != NULL)
				{
					Warning(LOCATION, "An ai profile named '%s' already exists!  The new one will not be created.\n", profile_name);
				}
				else
				{
					// make sure we're under the limit
					if (Num_ai_profiles >= MAX_AI_PROFILES)
					{
						Warning(LOCATION, "Too many profiles in ai_profiles.tbl!  Max is %d.\n", MAX_AI_PROFILES - 1);	// -1 because one is built-in
						skip_to_string("#End", NULL);
						break;
					}

					profile = &Ai_profiles[Num_ai_profiles];
					Num_ai_profiles++;
				}
			}

			// initialize profile if we're not building from a previously parsed one
			if (!no_create)
			{
				// base profile, so zero it out
				if (profile == &Ai_profiles[0])
				{
                    profile->reset();
				}
				// brand new profile, so set it to the base defaults
				else
				{
                    *profile = Ai_profiles[0];
				}
			}

			// set the name
			strcpy_s(profile->profile_name, profile_name);


			// fill in any and all settings; they're all optional and can be in any order
			while (!check_for_string("$Profile Name:") && !check_for_string("#End"))
			{
				if (optional_string("$Player Afterburner Recharge Scale:"))
					parse_float_list(profile->afterburner_recharge_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Max Beam Friendly Fire Damage:"))
					parse_float_list(profile->beam_friendly_damage_cap, NUM_SKILL_LEVELS);

				if (optional_string("$Player Countermeasure Life Scale:"))
					parse_float_list(profile->cmeasure_life_scale, NUM_SKILL_LEVELS);

				if (optional_string("$AI Countermeasure Firing Chance:"))
					parse_float_list(profile->cmeasure_fire_chance, NUM_SKILL_LEVELS);

				if (optional_string("$AI In Range Time:"))
					parse_float_list(profile->in_range_time, NUM_SKILL_LEVELS);

				if (optional_string("$AI Always Links Ammo Weapons:"))
					parse_float_list(profile->link_ammo_levels_always, NUM_SKILL_LEVELS);

				if (optional_string("$AI Maybe Links Ammo Weapons:"))
					parse_float_list(profile->link_ammo_levels_maybe, NUM_SKILL_LEVELS);

				if (optional_string("$Primary Ammo Burst Multiplier:"))
					parse_float_list(profile->primary_ammo_burst_mult, NUM_SKILL_LEVELS);

				if (optional_string("$AI Always Links Energy Weapons:"))
					parse_float_list(profile->link_energy_levels_always, NUM_SKILL_LEVELS);

				if (optional_string("$AI Maybe Links Energy Weapons:"))
					parse_float_list(profile->link_energy_levels_maybe, NUM_SKILL_LEVELS);

				if (optional_string("$Max Missles Locked on Player:") || optional_string("$Max Missiles Locked on Player:"))
					parse_int_list(profile->max_allowed_player_homers, NUM_SKILL_LEVELS);

				if (optional_string("$Max Player Attackers:"))
					parse_int_list(profile->max_attackers, NUM_SKILL_LEVELS);

				if (optional_string("$Max Incoming Asteroids:"))
					parse_int_list(profile->max_incoming_asteroids, NUM_SKILL_LEVELS);

				if (optional_string("$Player Damage Factor:") || optional_string("$AI Damage Reduction to Player Hull:"))
					parse_float_list(profile->player_damage_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Player Subsys Damage Factor:") || optional_string("$AI Damage Reduction to Player Subsys:"))
					parse_float_list(profile->subsys_damage_scale, NUM_SKILL_LEVELS);

				// represented in fractions of F1_0
				if (optional_string("$Predict Position Delay:"))
				{
					int iLoop;
					float temp_list[NUM_SKILL_LEVELS];

					parse_float_list(temp_list, NUM_SKILL_LEVELS);

					for (iLoop = 0; iLoop < NUM_SKILL_LEVELS; iLoop++)
						profile->predict_position_delay[iLoop] = fl2f(temp_list[iLoop]);
				}

				if (optional_string("$AI Shield Manage Delay:") || optional_string("$AI Shield Manage Delays:"))
					parse_float_list(profile->shield_manage_delay, NUM_SKILL_LEVELS);

				if (optional_string("$Friendly AI Fire Delay Scale:"))
					parse_float_list(profile->ship_fire_delay_scale_friendly, NUM_SKILL_LEVELS);

				if (optional_string("$Hostile AI Fire Delay Scale:"))
					parse_float_list(profile->ship_fire_delay_scale_hostile, NUM_SKILL_LEVELS);

				if (optional_string("$Friendly AI Secondary Fire Delay Scale:"))
					parse_float_list(profile->ship_fire_secondary_delay_scale_friendly, NUM_SKILL_LEVELS);

				if (optional_string("$Hostile AI Secondary Fire Delay Scale:"))
					parse_float_list(profile->ship_fire_secondary_delay_scale_hostile, NUM_SKILL_LEVELS);

				if (optional_string("$AI Turn Time Scale:"))
					parse_float_list(profile->turn_time_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Glide Attack Percent:")) {
					parse_float_list(profile->glide_attack_percent, NUM_SKILL_LEVELS);
					//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
					//While we're at it, verify the range
					for (i = 0; i < NUM_SKILL_LEVELS; i++) {
						if (profile->glide_attack_percent[i] < 0.0f || profile->glide_attack_percent[i] > 100.0f) {
							Warning(LOCATION, "$Glide Attack Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_attack_percent[i]);
							profile->glide_attack_percent[i] = 0.0f;
						}
						profile->glide_attack_percent[i] /= 100.0;
					}
				}

				if (optional_string("$Circle Strafe Percent:")) {
					parse_float_list(profile->circle_strafe_percent, NUM_SKILL_LEVELS);
					//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
					//While we're at it, verify the range
					for (i = 0; i < NUM_SKILL_LEVELS; i++) {
						if (profile->circle_strafe_percent[i] < 0.0f || profile->circle_strafe_percent[i] > 100.0f) {
							Warning(LOCATION, "$Circle Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->circle_strafe_percent[i]);
							profile->circle_strafe_percent[i] = 0.0f;
						}
						profile->circle_strafe_percent[i] /= 100.0;
					}
				}

				if (optional_string("$Glide Strafe Percent:")) {
					parse_float_list(profile->glide_strafe_percent, NUM_SKILL_LEVELS);
					//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
					//While we're at it, verify the range
					for (i = 0; i < NUM_SKILL_LEVELS; i++) {
						if (profile->glide_strafe_percent[i] < 0.0f || profile->glide_strafe_percent[i] > 100.0f) {
							Warning(LOCATION, "$Glide Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_strafe_percent[i]);
							profile->glide_strafe_percent[i] = 0.0f;
						}
						profile->glide_strafe_percent[i] /= 100.0;
					}
				}

				if (optional_string("$Random Sidethrust Percent:")) {
					parse_float_list(profile->random_sidethrust_percent, NUM_SKILL_LEVELS);
					//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
					//While we're at it, verify the range
					for (i = 0; i < NUM_SKILL_LEVELS; i++) {
						if (profile->random_sidethrust_percent[i] < 0.0f || profile->random_sidethrust_percent[i] > 100.0f) {
							Warning(LOCATION, "$Random Sidethrust Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->random_sidethrust_percent[i]);
							profile->random_sidethrust_percent[i] = 0.0f;
						}
						profile->random_sidethrust_percent[i] /= 100.0;
					}
				}

				if (optional_string("$Stalemate Time Threshold:"))
					parse_float_list(profile->stalemate_time_thresh, NUM_SKILL_LEVELS);

				if (optional_string("$Stalemate Distance Threshold:"))
					parse_float_list(profile->stalemate_dist_thresh, NUM_SKILL_LEVELS);

				if (optional_string("$Player Shield Recharge Scale:"))
					parse_float_list(profile->shield_energy_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Player Weapon Recharge Scale:"))
					parse_float_list(profile->weapon_energy_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Max Turret Target Ownage:"))
					parse_int_list(profile->max_turret_ownage_target, NUM_SKILL_LEVELS);

				if (optional_string("$Max Turret Player Ownage:"))
					parse_int_list(profile->max_turret_ownage_player, NUM_SKILL_LEVELS);

				if (optional_string("$Percentage Required For Kill Scale:"))
					parse_float_list(profile->kill_percentage_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Percentage Required For Assist Scale:"))
					parse_float_list(profile->assist_percentage_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Percentage Awarded For Capship Assist:"))
					parse_float_list(profile->assist_award_percentage_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Repair Penalty:"))
					parse_int_list(profile->repair_penalty, NUM_SKILL_LEVELS);

				if (optional_string("$Delay Before Allowing Bombs to Be Shot Down:"))
					parse_float_list(profile->delay_bomb_arm_timer, NUM_SKILL_LEVELS);

				if (optional_string("$Chance AI Has to Fire Missiles at Player:"))
					parse_int_list(profile->chance_to_use_missiles_on_plr, NUM_SKILL_LEVELS);

				if (optional_string("$Max Aim Update Delay:"))
					parse_float_list(profile->max_aim_update_delay, NUM_SKILL_LEVELS);

				if (optional_string("$Turret Max Aim Update Delay:"))
					parse_float_list(profile->turret_max_aim_update_delay, NUM_SKILL_LEVELS);

				if (optional_string("$Player Autoaim FOV:"))
				{
					float fov_list[NUM_SKILL_LEVELS];
					parse_float_list(fov_list, NUM_SKILL_LEVELS);
					for (i = 0; i < NUM_SKILL_LEVELS; i++)
					{
						//Enforce range
						if (fov_list[i] < 0.0f || fov_list[i] >= 360.0f)
						{
							Warning(LOCATION, "$Player Autoaim FOV should be >= 0 and < 360.0 (read %f). Setting to 0.", fov_list[i]);
							fov_list[i] = 0.0f;
						}

						//Convert units
						profile->player_autoaim_fov[i] = fov_list[i] * PI / 180.0f;
					}
				}

				if (optional_string("$Detail Distance Multiplier:"))
					parse_float_list(profile->detail_distance_mult, MAX_DETAIL_LEVEL + 1);

				set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AI::Profile_Flags::Big_ships_can_attack_beam_turrets_on_untargeted_ships);

				set_flag(profile, "$smart primary weapon selection:", AI::Profile_Flags::Smart_primary_weapon_selection);

				set_flag(profile, "$smart secondary weapon selection:", AI::Profile_Flags::Smart_secondary_weapon_selection);

				set_flag(profile, "$smart shield management:", AI::Profile_Flags::Smart_shield_management);

				set_flag(profile, "$smart afterburner management:", AI::Profile_Flags::Smart_afterburner_management);

				set_flag(profile, "$free afterburner use:", AI::Profile_Flags::Free_afterburner_use);

				set_flag(profile, "$allow rapid secondary dumbfire:", AI::Profile_Flags::Allow_rapid_secondary_dumbfire);

				set_flag(profile, "$huge turret weapons ignore bombs:", AI::Profile_Flags::Huge_turret_weapons_ignore_bombs);

				set_flag(profile, "$don't insert random turret fire delay:", AI::Profile_Flags::Dont_insert_random_turret_fire_delay);

				set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AI::Profile_Flags::Hack_improve_non_homing_swarm_turret_fire_accuracy);

				set_flag(profile, "$shockwaves damage small ship subsystems:", AI::Profile_Flags::Shockwaves_damage_small_ship_subsystems);

				set_flag(profile, "$navigation subsystem governs warpout capability:", AI::Profile_Flags::Navigation_subsys_governs_warp);

				set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AI::Profile_Flags::No_min_dock_speed_cap);

				set_flag(profile, "$disable linked fire penalty:", AI::Profile_Flags::Disable_linked_fire_penalty);

				set_flag(profile, "$disable weapon damage scaling:", AI::Profile_Flags::Disable_weapon_damage_scaling);

				set_flag(profile, "$use additive weapon velocity:", AI::Profile_Flags::Use_additive_weapon_velocity);

				set_flag(profile, "$use newtonian dampening:", AI::Profile_Flags::Use_newtonian_dampening);

				set_flag(profile, "$include beams for kills and assists:", AI::Profile_Flags::Include_beams_in_stat_calcs);

				set_flag(profile, "$score kills based on damage caused:", AI::Profile_Flags::Kill_scoring_scales_with_damage);

				set_flag(profile, "$score assists based on damage caused:", AI::Profile_Flags::Assist_scoring_scales_with_damage);

				set_flag(profile, "$allow event and goal scoring in multiplayer:", AI::Profile_Flags::Allow_multi_event_scoring);

				set_flag(profile, "$fix linked primary weapon decision bug:", AI::Profile_Flags::Fix_linked_primary_bug);

				set_flag(profile, "$prevent turrets targeting too distant bombs:", AI::Profile_Flags::Prevent_targeting_bombs_beyond_range);

				set_flag(profile, "$smart subsystem targeting for turrets:", AI::Profile_Flags::Smart_subsystem_targeting_for_turrets);

				set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AI::Profile_Flags::Fix_heat_seeker_stealth_bug);

				set_flag(profile, "$multi allow empty primaries:", AI::Profile_Flags::Multi_allow_empty_primaries);

				set_flag(profile, "$multi allow empty secondaries:", AI::Profile_Flags::Multi_allow_empty_secondaries);

				set_flag(profile, "$allow turrets target weapons freely:", AI::Profile_Flags::Allow_turrets_target_weapons_freely);

				set_flag(profile, "$use only single fov for turrets:", AI::Profile_Flags::Use_only_single_fov_for_turrets);

				set_flag(profile, "$allow vertical dodge:", AI::Profile_Flags::Allow_vertical_dodge);

				set_flag(profile, "$force beam turrets to use normal fov:", AI::Profile_Flags::Force_beam_turret_fov);

				set_flag(profile, "$fix ai class bug:", AI::Profile_Flags::Fix_ai_class_bug);

				set_flag(profile, "$turrets ignore targets radius in range checks:", AI::Profile_Flags::Turrets_ignore_target_radius);

				set_flag(profile, "$no extra collision avoidance vs player:", AI::Profile_Flags::No_special_player_avoid);

				set_flag(profile, "$perform fewer checks for death screams:", AI::Profile_Flags::Perform_fewer_scream_checks);

				set_flag(profile, "$advanced turret fov edge checks:", AI::Profile_Flags::Advanced_turret_fov_edge_checks);

				set_flag(profile, "$require turrets to have target in fov:", AI::Profile_Flags::Require_turret_to_have_target_in_fov);

				set_flag(profile, "$all ships manage shields:", AI::Profile_Flags::All_ships_manage_shields);

				set_flag(profile, "$ai aims from ship center:", AI::Profile_Flags::Ai_aims_from_ship_center);

				set_flag(profile, "$allow primary link at mission start:", AI::Profile_Flags::Allow_primary_link_at_start);

				set_flag(profile, "$allow beams to damage bombs:", AI::Profile_Flags::Beams_damage_weapons);

				set_flag(profile, "$disable weapon damage scaling for player:", AI::Profile_Flags::Player_weapon_scale_fix);

				set_flag(profile, "$countermeasures affect aspect seekers:", AI::Profile_Flags::Aspect_lock_countermeasure);

				set_flag(profile, "$ai guards specific ship in wing:", AI::Profile_Flags::Ai_guards_specific_ship_in_wing);

				profile->ai_path_mode = AI_PATH_MODE_NORMAL;
				if (optional_string("$ai path mode:"))
				{
					stuff_string(buf, F_NAME, NAME_LENGTH);
					int j = ai_path_type_match(buf);
					if (j >= 0) {
						profile->ai_path_mode = j;
					}
					else {
						Warning(LOCATION, "Invalid ai path mode '%s' specified", buf);
					}
				}

				set_flag(profile, "$no warp camera:", AI::Profile_Flags::No_warp_camera);

				set_flag(profile, "$fix ai path order bug:", AI::Profile_Flags::Fix_ai_path_order_bug);

				set_flag(profile, "$strict turret-tagged-only targeting:", AI::Profile_Flags::Strict_turred_tagged_only_targeting);

				set_flag(profile, "$aspect bomb invulnerability fix:", AI::Profile_Flags::Aspect_invulnerability_fix);

				set_flag(profile, "$glide decay requires thrust:", AI::Profile_Flags::Glide_decay_requires_thrust);

				set_flag(profile, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships);

				set_flag(profile, "$use actual primary range:", AI::Profile_Flags::Use_actual_primary_range);

				profile->bay_arrive_speed_mult = 1.0f;
				profile->bay_depart_speed_mult = 1.0f;
				if (optional_string("$bay arrive speed multiplier:")) {
					stuff_float(&profile->bay_arrive_speed_mult);
				}
				if (optional_string("$bay depart speed multiplier:")) {
					stuff_float(&profile->bay_depart_speed_mult);
				}

				// ----------

				// compatibility
				if (optional_string("$perform less checks for death screams:"))
				{
					mprintf(("Warning: \"$perform less checks for death screams\" flag is deprecated in favor of \"$perform fewer checks for death screams\"\n"));
					bool temp;
					stuff_boolean(&temp);
                    profile->flags.set(AI::Profile_Flags::Perform_fewer_scream_checks, temp);
				}
				if (optional_string("$allow primary link delay:"))
				{
					mprintf(("Warning: \"$allow primary link delay\" flag is deprecated in favor of \"$allow primary link at mission start\"\n"));
					bool temp;
					stuff_boolean(&temp);
                    profile->flags.set(AI::Profile_Flags::Allow_primary_link_at_start, !temp);
				}


				// if we've been through once already and are at the same place, force a move
				if (saved_Mp && (saved_Mp == Mp))
				{
					char tmp[60];
					memset(tmp, 0, 60);
					strncpy(tmp, Mp, 59);
					mprintf(("WARNING: Unrecognized parameter in ai_profiles: %s\n", tmp));

					Mp++;
				}

				// find next valid option
				if (!skip_to_start_of_string_either("$", "#"))
					break;
				saved_Mp = Mp;
			}
		}

		required_string("#End");
	}
	catch (const parse::ParseException& e)
	{
		mprintf(("TABLES: Unable to parse '%s'!  Error message = %s.\n", (filename) ? filename : "<default ai_profiles.tbl>", e.what()));
		return;
	}

	// add tbl/tbm to multiplayer validation list
	extern void fs2netd_add_table_validation(const char *tblname);
	fs2netd_add_table_validation(filename);
}
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_thrust_anims(species_info *species, bool no_create)
{
	if (!no_create)
	{
		required_string("$ThrustAnims:");

		generic_anim_init(&species->thruster_info.flames.normal, NULL);
		generic_anim_init(&species->thruster_info.flames.afterburn, NULL);
		generic_bitmap_init(&species->thruster_secondary_glow_info.normal, NULL);
		generic_bitmap_init(&species->thruster_secondary_glow_info.afterburn, NULL);
		generic_bitmap_init(&species->thruster_tertiary_glow_info.normal, NULL);
		generic_bitmap_init(&species->thruster_tertiary_glow_info.afterburn, NULL);
		generic_bitmap_init(&species->thruster_distortion_info.normal, NULL);
		generic_bitmap_init(&species->thruster_distortion_info.afterburn, NULL);
	}
	else if (!optional_string("$ThrustAnims:"))
	{
		return;
	}

	// favor new style
	if (no_create)
	{
		if (optional_string("+Pri_Normal:") || optional_string("+Normal:"))
			stuff_string(species->thruster_info.flames.normal.filename, F_NAME, MAX_FILENAME_LEN);
	}
	else
	{
		if (!optional_string("+Pri_Normal:"))
			required_string("+Normal:");

		stuff_string(species->thruster_info.flames.normal.filename, F_NAME, MAX_FILENAME_LEN);
	}

	// if no primary thruster anim is wanted then clear it
	if ( !VALID_FNAME(species->thruster_info.flames.normal.filename) )
		generic_anim_init(&species->thruster_info.flames.normal, NULL);

	// and again
	if (no_create)
	{
		if (optional_string("+Pri_Afterburn:") || optional_string("+Afterburn:"))
			stuff_string(species->thruster_info.flames.afterburn.filename, F_NAME, MAX_FILENAME_LEN);
	}
	else
	{
		if (!optional_string("+Pri_Afterburn:"))
			required_string("+Afterburn:");

		stuff_string(species->thruster_info.flames.afterburn.filename, F_NAME, MAX_FILENAME_LEN);
	}

	// if no primary thruster anim is wanted then clear it
	if ( !VALID_FNAME(species->thruster_info.flames.afterburn.filename) )
		generic_anim_init(&species->thruster_info.flames.afterburn, NULL);

	// extra thruster stuff, bah
	if (optional_string("+Sec_Normal:"))
		stuff_string(species->thruster_secondary_glow_info.normal.filename, F_NAME, MAX_FILENAME_LEN);

	// etc.
	if (optional_string("+Sec_Afterburn:"))
		stuff_string(species->thruster_secondary_glow_info.afterburn.filename, F_NAME, MAX_FILENAME_LEN);

	// etc.
	if (optional_string("+Ter_Normal:"))
		stuff_string(species->thruster_tertiary_glow_info.normal.filename, F_NAME, MAX_FILENAME_LEN);

	// etc.
	if (optional_string("+Ter_Afterburn:"))
		stuff_string(species->thruster_tertiary_glow_info.afterburn.filename, F_NAME, MAX_FILENAME_LEN);
	
	// etc.
	if (optional_string("+Dist_Normal:"))
		stuff_string(species->thruster_distortion_info.normal.filename, F_NAME, MAX_FILENAME_LEN);

	// etc.
	if (optional_string("+Dist_Afterburn:"))
		stuff_string(species->thruster_distortion_info.afterburn.filename, F_NAME, MAX_FILENAME_LEN);
}
Esempio n. 14
0
void parse_mod_table(const char *filename)
{
	// SCP_vector<SCP_string> lines;

	try
	{
		if (filename == NULL)
			read_file_text_from_default(defaults_get_file("game_settings.tbl"));
		else
			read_file_text(filename, CF_TYPE_TABLES);

		reset_parse();

		// start parsing
		optional_string("#GAME SETTINGS");
		
		if (optional_string("$Minimum version:")) {
			int major = 0;
			int minor = 0;
			int build = 0;
			int revision = 0;
			
			required_string("+Major:");
			stuff_int(&major);
			
			required_string("+Minor:");
			stuff_int(&minor);
			
			required_string("+Build:");
			stuff_int(&build);
			
			if (optional_string("+Revision:")) {
				stuff_int(&revision);
			}
			
			mprintf(("Game Settings Table: Parsed minimum version of %s\n", version::format_version(major, minor, build, revision).c_str()));
			
			if (!version::check_at_least(major, minor, build, revision)) {
				Error(LOCATION, "This modification needs at least version %s of FreeSpace Open. However, the current is only %s!",
					  version::format_version(major, minor, build, revision).c_str(),
					  version::format_version(FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD, FS_VERSION_REVIS).c_str());
			}
		}
		
		optional_string("#CAMPAIGN SETTINGS");

		if (optional_string("$Default Campaign File Name:")) {
			char temp[MAX_FILENAME_LEN];
			stuff_string(temp, F_NAME, MAX_FILENAME_LEN);

			// remove extension?
			if (drop_extension(temp)) {
				mprintf(("Game Settings Table: Removed extension on default campaign file name %s\n", temp));
			}

			// check length
			size_t maxlen = (MAX_FILENAME_LEN - 4);
			auto len = strlen(temp);
			if (len > maxlen) {
				Warning(LOCATION, "Token too long: [%s].  Length = " SIZE_T_ARG ".  Max is " SIZE_T_ARG ".\n", temp, len, maxlen);
				temp[maxlen] = 0;
			}

			strcpy_s(Default_campaign_file_name, temp);
		}

		if (optional_string("#Ignored Campaign File Names")) {
			SCP_string campaign_name;

			while (optional_string("$Campaign File Name:")) {
				stuff_string(campaign_name, F_NAME);

				// remove extension?
				if (drop_extension(campaign_name)) {
					mprintf(("Game Settings Table: Removed extension on ignored campaign file name %s\n", campaign_name.c_str()));
				}

				Ignored_campaigns.push_back(campaign_name);
			}
		}

		if (optional_string("$Red-alert applies to delayed ships:")) {
			stuff_boolean(&Red_alert_applies_to_delayed_ships);
			if (Red_alert_applies_to_delayed_ships) {
				mprintf(("Game Settings Table: Red-alert stats will be loaded for ships that arrive later in missions\n"));
			}
			else {
				mprintf(("Game Settings Table: Red-alert stats will NOT be loaded for ships that arrive later in missions (this is retail behavior)\n"));
			}
		}

		optional_string("#HUD SETTINGS");

		// how long should the game wait before displaying a directive?
		if (optional_string("$Directive Wait Time:")) {
			stuff_int(&Directive_wait_time);
		}

		if (optional_string("$Cutscene camera displays HUD:")) {
			stuff_boolean(&Cutscene_camera_displays_hud);
		}
		// compatibility
		if (optional_string("$Cutscene camera disables HUD:")) {
			mprintf(("Game Settings Table: \"$$Cutscene camera disables HUD\" is deprecated in favor of \"$Cutscene camera displays HUD\"\n"));
			bool temp;
			stuff_boolean(&temp);
			Cutscene_camera_displays_hud = !temp;
		}

		if (optional_string("$Full color head animations:")) {
			stuff_boolean(&Full_color_head_anis);
		}
		// compatibility
		if (optional_string("$Color head animations with hud colors:")) {
			mprintf(("Game Settings Table: \"$Color head animations with hud colors\" is deprecated in favor of \"$Full color head animations\"\n"));
			bool temp;
			stuff_boolean(&temp);
			Full_color_head_anis = !temp;
		}

		optional_string("#SEXP SETTINGS");

		if (optional_string("$Loop SEXPs Then Arguments:")) {
			stuff_boolean(&True_loop_argument_sexps);
			if (True_loop_argument_sexps) {
				mprintf(("Game Settings Table: Using Reversed Loops For SEXP Arguments\n"));
			}
			else {
				mprintf(("Game Settings Table: Using Standard Loops For SEXP Arguments\n"));
			}
		}

		if (optional_string("$Use Alternate Chaining Behavior:")) {
			stuff_boolean(&Alternate_chaining_behavior);
			if (Alternate_chaining_behavior) {
				mprintf(("Game Settings Table: Using alternate event chaining behavior\n"));
			}
			else {
				mprintf(("Game Settings Table: Using standard event chaining behavior\n"));
			}
		}

		optional_string("#GRAPHICS SETTINGS");

		if (optional_string("$Enable External Shaders:")) {
			stuff_boolean(&Enable_external_shaders);
			if (Enable_external_shaders)
				mprintf(("Game Settings Table: External shaders are enabled\n"));
			else
				mprintf(("Game Settings Table: External shaders are DISABLED\n"));
		}

		if (optional_string("$Default Detail Level:")) {
			int detail_level;

			stuff_int(&detail_level);

			mprintf(("Game Settings Table: Setting default detail level to %i of %i-%i\n", detail_level, 0, NUM_DEFAULT_DETAIL_LEVELS - 1));

			if (detail_level < 0 || detail_level > NUM_DEFAULT_DETAIL_LEVELS - 1) {
				Warning(LOCATION, "Invalid detail level: %i, setting to %i\n", detail_level, Default_detail_level);
			}
			else {
				Default_detail_level = detail_level;
			}
		}

		if (optional_string("$Briefing Window FOV:")) {
			float fov;

			stuff_float(&fov);

			mprintf(("Game Settings Table: Setting briefing window FOV from %f to %f\n", Briefing_window_FOV, fov));

			Briefing_window_FOV = fov;
		}

		
			if (optional_string("$Generic Pain Flash Factor:")) {
			stuff_float(&Generic_pain_flash_factor);
			if (Generic_pain_flash_factor != 1.0f)
				mprintf(("Game Settings Table: Setting generic pain flash factor to %.2f\n", Generic_pain_flash_factor));
			
		}
		
			if (optional_string("$Shield Pain Flash Factor:")) {
			stuff_float(&Shield_pain_flash_factor);
			if (Shield_pain_flash_factor != 0.0f)
				 mprintf(("Game Settings Table: Setting shield pain flash factor to %.2f\n", Shield_pain_flash_factor));
			
		}

		optional_string("#NETWORK SETTINGS");

		if (optional_string("$FS2NetD port:")) {
			stuff_int(&FS2NetD_port);
			if (FS2NetD_port)
				mprintf(("Game Settings Table: FS2NetD connecting to port %i\n", FS2NetD_port));
		}

		optional_string("#SOUND SETTINGS");

		if (optional_string("$Default Sound Volume:")) {
			stuff_float(&Master_sound_volume);
		}

		if (optional_string("$Default Music Volume:")) {
			stuff_float(&Master_event_music_volume);
		}

		if (optional_string("$Default Voice Volume:")) {
			stuff_float(&Master_voice_volume);
		}

		optional_string("#FRED SETTINGS");

		if (optional_string("$Disable Hard Coded Message Head Ani Files:")) {
			stuff_boolean(&Disable_hc_message_ani);
			if (Disable_hc_message_ani) {
				mprintf(("Game Settings Table: FRED - Disabling Hard Coded Message Ani Files\n"));
			}
			else {
				mprintf(("Game Settings Table: FRED - Using Hard Coded Message Ani Files\n"));

			}
		}

		optional_string("#OTHER SETTINGS");

		if (optional_string("$Fixed Turret Collisions:")) {
			stuff_boolean(&Fixed_turret_collisions);
		}

		if (optional_string("$Damage Impacted Subsystem First:")) {
			stuff_boolean(&Damage_impacted_subsystem_first);
		}

		if (optional_string("$Default ship select effect:")) {
			char effect[NAME_LENGTH];
			stuff_string(effect, F_NAME, NAME_LENGTH);
			if (!stricmp(effect, "FS2"))
				Default_ship_select_effect = 2;
			else if (!stricmp(effect, "FS1"))
				Default_ship_select_effect = 1;
			else if (!stricmp(effect, "off"))
				Default_ship_select_effect = 0;
		}

		if (optional_string("$Default weapon select effect:")) {
			char effect[NAME_LENGTH];
			stuff_string(effect, F_NAME, NAME_LENGTH);
			if (!stricmp(effect, "FS2"))
				Default_weapon_select_effect = 2;
			else if (!stricmp(effect, "FS1"))
				Default_weapon_select_effect = 1;
			else if (!stricmp(effect, "off"))
				Default_weapon_select_effect = 0;
		}

		if (optional_string("$Weapons inherit parent collision group:")) {
			stuff_boolean(&Weapons_inherit_parent_collision_group);
			if (Weapons_inherit_parent_collision_group)
				mprintf(("Game Settings Table: Weapons inherit parent collision group\n"));
		}

		if (optional_string("$Flight controls follow eyepoint orientation:")) {
			stuff_boolean(&Flight_controls_follow_eyepoint_orientation);
			if (Flight_controls_follow_eyepoint_orientation)
				mprintf(("Game Settings Table: Flight controls follow eyepoint orientation\n"));
		}

		if (optional_string("$Beams Use Damage Factors:")) {
			stuff_boolean(&Beams_use_damage_factors);
			if (Beams_use_damage_factors) {
				mprintf(("Game Settings Table: Beams will use Damage Factors\n"));
			}
			else {
				mprintf(("Game Settings Table: Beams will ignore Damage Factors (retail behavior)\n"));
			}
		}

		if (optional_string("$Default fiction viewer UI:")) {
			char ui_name[NAME_LENGTH];
			stuff_string(ui_name, F_NAME, NAME_LENGTH);
			if (!stricmp(ui_name, "auto"))
				Default_fiction_viewer_ui = -1;
			else {
				int ui_index = fiction_viewer_ui_name_to_index(ui_name);
				if (ui_index >= 0)
					Default_fiction_viewer_ui = ui_index;
				else
					Warning(LOCATION, "Unrecognized fiction viewer UI: %s", ui_name);
			}
		}

		required_string("#END");
	}
	catch (const parse::ParseException& e)
	{
		mprintf(("TABLES: Unable to parse '%s'!  Error message = %s.\n", (filename) ? filename : "<default game_settings.tbl>", e.what()));
		return;
	}
}
void parse_sound_environments()
{
	char name[65] = { '\0' };
	char template_name[65] = { '\0' };
	EFXREVERBPROPERTIES *props;

	while (required_string_either("#Sound Environments End", "$Name:"))
	{
		required_string("$Name:");
		stuff_string(name, F_NAME, sizeof(name)-1);

		if (optional_string("$Template:"))
		{
			stuff_string(template_name, F_NAME, sizeof(template_name)-1);
		}
		else
		{
			template_name[0] = '\0';
		}

		ds_eax_get_prop(&props, name, template_name);

		if (optional_string("+Density:"))
		{
			stuff_float(&props->flDensity);
			CLAMP(props->flDensity, 0.0f, 1.0f);
		}

		if (optional_string("+Diffusion:"))
		{
			stuff_float(&props->flDiffusion);
			CLAMP(props->flDiffusion, 0.0f, 1.0f);
		}

		if (optional_string("+Gain:"))
		{
			stuff_float(&props->flGain);
			CLAMP(props->flGain, 0.0f, 1.0f);
		}

		if (optional_string("+Gain HF:"))
		{
			stuff_float(&props->flGainHF);
			CLAMP(props->flGainHF, 0.0f, 1.0f);
		}

		if (optional_string("+Gain LF:"))
		{
			stuff_float(&props->flGainLF);
			CLAMP(props->flGainLF, 0.0f, 1.0f);
		}

		if (optional_string("+Decay Time:"))
		{
			stuff_float(&props->flDecayTime);
			CLAMP(props->flDecayTime, 0.01f, 20.0f);
		}

		if (optional_string("+Decay HF Ratio:"))
		{
			stuff_float(&props->flDecayHFRatio);
			CLAMP(props->flDecayHFRatio, 0.1f, 20.0f);
		}

		if (optional_string("+Decay LF Ratio:"))
		{
			stuff_float(&props->flDecayLFRatio);
			CLAMP(props->flDecayLFRatio, 0.1f, 20.0f);
		}

		if (optional_string("+Reflections Gain:"))
		{
			stuff_float(&props->flReflectionsGain);
			CLAMP(props->flReflectionsGain, 0.0f, 3.16f);
		}

		if (optional_string("+Reflections Delay:"))
		{
			stuff_float(&props->flReflectionsDelay);
			CLAMP(props->flReflectionsDelay, 0.0f, 0.3f);
		}

		if (optional_string("+Reflections Pan:"))
		{
			stuff_float_list(props->flReflectionsPan, 3);
			CLAMP(props->flReflectionsPan[0], 0.0f, 1.0f);
			CLAMP(props->flReflectionsPan[1], 0.0f, 1.0f);
			CLAMP(props->flReflectionsPan[2], 0.0f, 1.0f);
		}

		if (optional_string("+Late Reverb Gain:"))
		{
			stuff_float(&props->flLateReverbGain);
			CLAMP(props->flLateReverbGain, 0.0f, 10.0f);
		}

		if (optional_string("+Late Reverb Delay:"))
		{
			stuff_float(&props->flLateReverbDelay);
			CLAMP(props->flLateReverbDelay, 0.0f, 0.1f);
		}

		if (optional_string("+Late Reverb Pan:"))
		{
			stuff_float_list(props->flLateReverbPan, 3);
			CLAMP(props->flLateReverbPan[0], 0.0f, 1.0f);
			CLAMP(props->flLateReverbPan[1], 0.0f, 1.0f);
			CLAMP(props->flLateReverbPan[2], 0.0f, 1.0f);
		}

		if (optional_string("+Echo Time:"))
		{
			stuff_float(&props->flEchoTime);
			CLAMP(props->flEchoTime, 0.075f, 0.25f);
		}

		if (optional_string("+Echo Depth:"))
		{
			stuff_float(&props->flEchoDepth);
			CLAMP(props->flEchoDepth, 0.0f, 1.0f);
		}

		if (optional_string("+Modulation Time:"))
		{
			stuff_float(&props->flModulationTime);
			CLAMP(props->flModulationTime, 0.004f, 4.0f);
		}

		if (optional_string("+Modulation Depth:"))
		{
			stuff_float(&props->flModulationDepth);
			CLAMP(props->flModulationDepth, 0.0f, 1.0f);
		}

		if (optional_string("+HF Reference:"))
		{
			stuff_float(&props->flHFReference);
			CLAMP(props->flHFReference, 1000.0f, 20000.0f);
		}

		if (optional_string("+LF Reference:"))
		{
			stuff_float(&props->flLFReference);
			CLAMP(props->flLFReference, 20.0f, 1000.0f);
		}

		if (optional_string("+Room Rolloff Factor:"))
		{
			stuff_float(&props->flRoomRolloffFactor);
			CLAMP(props->flRoomRolloffFactor, 0.0f, 10.0f);
		}

		if (optional_string("+Air Absorption Gain HF:"))
		{
			stuff_float(&props->flAirAbsorptionGainHF);
			CLAMP(props->flAirAbsorptionGainHF, 0.892f, 1.0f);
		}

		if (optional_string("+Decay HF Limit:"))
		{
			stuff_int(&props->iDecayHFLimit);
			CLAMP(props->iDecayHFLimit, 0, 1);
		}
	}

	required_string("#Sound Environments End");
}
Esempio n. 16
0
void parse_ai_profiles_tbl(const char *filename)
{
	int i;
	char profile_name[NAME_LENGTH];
	ai_profile_t dummy_profile;
	char *saved_Mp = NULL;
	char buf[NAME_LENGTH];

	try
	{
		if (filename == NULL)
			read_file_text_from_default(defaults_get_file("ai_profiles.tbl"));
		else
			read_file_text(filename, CF_TYPE_TABLES);

		reset_parse();


		// start parsing
		required_string("#AI Profiles");

		// new default?
		if (optional_string("$Default Profile:"))
			stuff_string(Default_profile_name, F_NAME, NAME_LENGTH);

		// begin reading data
		while (required_string_either("#End", "$Profile Name:"))
		{
			ai_profile_t *profile = &dummy_profile;
			ai_profile_t *previous_profile = NULL;
			bool no_create = false;

			// get the name
			required_string("$Profile Name:");
			stuff_string(profile_name, F_NAME, NAME_LENGTH);

			// see if it exists
			for (i = 0; i < Num_ai_profiles; i++)
			{
				if (!stricmp(Ai_profiles[i].profile_name, profile_name))
				{
					previous_profile = &Ai_profiles[i];
					break;
				}
			}

			// modular table stuff
			if (optional_string("+nocreate"))
			{
				no_create = true;

				// use the previous one if possible,
				// otherwise continue to use the dummy one
				if (previous_profile != NULL)
					profile = previous_profile;
			}
			else
			{
				// don't create multiple profiles with the same name
				if (previous_profile != NULL)
				{
					Warning(LOCATION, "An ai profile named '%s' already exists!  The new one will not be created.\n", profile_name);
				}
				else
				{
					// make sure we're under the limit
					if (Num_ai_profiles >= MAX_AI_PROFILES)
					{
						Warning(LOCATION, "Too many profiles in ai_profiles.tbl!  Max is %d.\n", MAX_AI_PROFILES - 1);	// -1 because one is built-in
						skip_to_string("#End", NULL);
						break;
					}

					profile = &Ai_profiles[Num_ai_profiles];
					Num_ai_profiles++;
				}
			}

			// initialize profile if we're not building from a previously parsed one
			if (!no_create)
			{
				// base profile, so zero it out
				if (profile == &Ai_profiles[0])
				{
					memset(profile, 0, sizeof(ai_profile_t));
				}
				// brand new profile, so set it to the base defaults
				else
				{
					memcpy(profile, &Ai_profiles[0], sizeof(ai_profile_t));
				}
			}

			// set the name
			strcpy_s(profile->profile_name, profile_name);


			// fill in any and all settings; they're all optional and can be in any order
			while (!check_for_string("$Profile Name:") && !check_for_string("#End"))
			{
				if (optional_string("$Player Afterburner Recharge Scale:"))
					parse_float_list(profile->afterburner_recharge_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Max Beam Friendly Fire Damage:"))
					parse_float_list(profile->beam_friendly_damage_cap, NUM_SKILL_LEVELS);

				if (optional_string("$Player Countermeasure Life Scale:"))
					parse_float_list(profile->cmeasure_life_scale, NUM_SKILL_LEVELS);

				if (optional_string("$AI Countermeasure Firing Chance:"))
					parse_float_list(profile->cmeasure_fire_chance, NUM_SKILL_LEVELS);

				if (optional_string("$AI In Range Time:"))
					parse_float_list(profile->in_range_time, NUM_SKILL_LEVELS);

				if (optional_string("$AI Always Links Ammo Weapons:"))
					parse_float_list(profile->link_ammo_levels_always, NUM_SKILL_LEVELS);

				if (optional_string("$AI Maybe Links Ammo Weapons:"))
					parse_float_list(profile->link_ammo_levels_maybe, NUM_SKILL_LEVELS);

				if (optional_string("$Primary Ammo Burst Multiplier:"))
					parse_float_list(profile->primary_ammo_burst_mult, NUM_SKILL_LEVELS);

				if (optional_string("$AI Always Links Energy Weapons:"))
					parse_float_list(profile->link_energy_levels_always, NUM_SKILL_LEVELS);

				if (optional_string("$AI Maybe Links Energy Weapons:"))
					parse_float_list(profile->link_energy_levels_maybe, NUM_SKILL_LEVELS);

				if (optional_string("$Max Missles Locked on Player:") || optional_string("$Max Missiles Locked on Player:"))
					parse_int_list(profile->max_allowed_player_homers, NUM_SKILL_LEVELS);

				if (optional_string("$Max Player Attackers:"))
					parse_int_list(profile->max_attackers, NUM_SKILL_LEVELS);

				if (optional_string("$Max Incoming Asteroids:"))
					parse_int_list(profile->max_incoming_asteroids, NUM_SKILL_LEVELS);

				if (optional_string("$Player Damage Factor:") || optional_string("$AI Damage Reduction to Player Hull:"))
					parse_float_list(profile->player_damage_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Player Subsys Damage Factor:") || optional_string("$AI Damage Reduction to Player Subsys:"))
					parse_float_list(profile->subsys_damage_scale, NUM_SKILL_LEVELS);

				// represented in fractions of F1_0
				if (optional_string("$Predict Position Delay:"))
				{
					int iLoop;
					float temp_list[NUM_SKILL_LEVELS];

					parse_float_list(temp_list, NUM_SKILL_LEVELS);

					for (iLoop = 0; iLoop < NUM_SKILL_LEVELS; iLoop++)
						profile->predict_position_delay[iLoop] = fl2f(temp_list[iLoop]);
				}

				if (optional_string("$AI Shield Manage Delay:") || optional_string("$AI Shield Manage Delays:"))
					parse_float_list(profile->shield_manage_delay, NUM_SKILL_LEVELS);

				if (optional_string("$Friendly AI Fire Delay Scale:"))
					parse_float_list(profile->ship_fire_delay_scale_friendly, NUM_SKILL_LEVELS);

				if (optional_string("$Hostile AI Fire Delay Scale:"))
					parse_float_list(profile->ship_fire_delay_scale_hostile, NUM_SKILL_LEVELS);

				if (optional_string("$Friendly AI Secondary Fire Delay Scale:"))
					parse_float_list(profile->ship_fire_secondary_delay_scale_friendly, NUM_SKILL_LEVELS);

				if (optional_string("$Hostile AI Secondary Fire Delay Scale:"))
					parse_float_list(profile->ship_fire_secondary_delay_scale_hostile, NUM_SKILL_LEVELS);

				if (optional_string("$AI Turn Time Scale:"))
					parse_float_list(profile->turn_time_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Glide Attack Percent:")) {
					parse_float_list(profile->glide_attack_percent, NUM_SKILL_LEVELS);
					//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
					//While we're at it, verify the range
					for (i = 0; i < NUM_SKILL_LEVELS; i++) {
						if (profile->glide_attack_percent[i] < 0.0f || profile->glide_attack_percent[i] > 100.0f) {
							Warning(LOCATION, "$Glide Attack Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_attack_percent[i]);
							profile->glide_attack_percent[i] = 0.0f;
						}
						profile->glide_attack_percent[i] /= 100.0;
					}
				}

				if (optional_string("$Circle Strafe Percent:")) {
					parse_float_list(profile->circle_strafe_percent, NUM_SKILL_LEVELS);
					//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
					//While we're at it, verify the range
					for (i = 0; i < NUM_SKILL_LEVELS; i++) {
						if (profile->circle_strafe_percent[i] < 0.0f || profile->circle_strafe_percent[i] > 100.0f) {
							Warning(LOCATION, "$Circle Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->circle_strafe_percent[i]);
							profile->circle_strafe_percent[i] = 0.0f;
						}
						profile->circle_strafe_percent[i] /= 100.0;
					}
				}

				if (optional_string("$Glide Strafe Percent:")) {
					parse_float_list(profile->glide_strafe_percent, NUM_SKILL_LEVELS);
					//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
					//While we're at it, verify the range
					for (i = 0; i < NUM_SKILL_LEVELS; i++) {
						if (profile->glide_strafe_percent[i] < 0.0f || profile->glide_strafe_percent[i] > 100.0f) {
							Warning(LOCATION, "$Glide Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_strafe_percent[i]);
							profile->glide_strafe_percent[i] = 0.0f;
						}
						profile->glide_strafe_percent[i] /= 100.0;
					}
				}

				if (optional_string("$Random Sidethrust Percent:")) {
					parse_float_list(profile->random_sidethrust_percent, NUM_SKILL_LEVELS);
					//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
					//While we're at it, verify the range
					for (i = 0; i < NUM_SKILL_LEVELS; i++) {
						if (profile->random_sidethrust_percent[i] < 0.0f || profile->random_sidethrust_percent[i] > 100.0f) {
							Warning(LOCATION, "$Random Sidethrust Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->random_sidethrust_percent[i]);
							profile->random_sidethrust_percent[i] = 0.0f;
						}
						profile->random_sidethrust_percent[i] /= 100.0;
					}
				}

				if (optional_string("$Stalemate Time Threshold:"))
					parse_float_list(profile->stalemate_time_thresh, NUM_SKILL_LEVELS);

				if (optional_string("$Stalemate Distance Threshold:"))
					parse_float_list(profile->stalemate_dist_thresh, NUM_SKILL_LEVELS);

				if (optional_string("$Player Shield Recharge Scale:"))
					parse_float_list(profile->shield_energy_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Player Weapon Recharge Scale:"))
					parse_float_list(profile->weapon_energy_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Max Turret Target Ownage:"))
					parse_int_list(profile->max_turret_ownage_target, NUM_SKILL_LEVELS);

				if (optional_string("$Max Turret Player Ownage:"))
					parse_int_list(profile->max_turret_ownage_player, NUM_SKILL_LEVELS);

				if (optional_string("$Percentage Required For Kill Scale:"))
					parse_float_list(profile->kill_percentage_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Percentage Required For Assist Scale:"))
					parse_float_list(profile->assist_percentage_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Percentage Awarded For Capship Assist:"))
					parse_float_list(profile->assist_award_percentage_scale, NUM_SKILL_LEVELS);

				if (optional_string("$Repair Penalty:"))
					parse_int_list(profile->repair_penalty, NUM_SKILL_LEVELS);

				if (optional_string("$Delay Before Allowing Bombs to Be Shot Down:"))
					parse_float_list(profile->delay_bomb_arm_timer, NUM_SKILL_LEVELS);

				if (optional_string("$Chance AI Has to Fire Missiles at Player:"))
					parse_int_list(profile->chance_to_use_missiles_on_plr, NUM_SKILL_LEVELS);

				if (optional_string("$Max Aim Update Delay:"))
					parse_float_list(profile->max_aim_update_delay, NUM_SKILL_LEVELS);

				if (optional_string("$Turret Max Aim Update Delay:"))
					parse_float_list(profile->turret_max_aim_update_delay, NUM_SKILL_LEVELS);

				if (optional_string("$Player Autoaim FOV:"))
				{
					float fov_list[NUM_SKILL_LEVELS];
					parse_float_list(fov_list, NUM_SKILL_LEVELS);
					for (i = 0; i < NUM_SKILL_LEVELS; i++)
					{
						//Enforce range
						if (fov_list[i] < 0.0f || fov_list[i] >= 360.0f)
						{
							Warning(LOCATION, "$Player Autoaim FOV should be >= 0 and < 360.0 (read %f). Setting to 0.", fov_list[i]);
							fov_list[i] = 0.0f;
						}

						//Convert units
						profile->player_autoaim_fov[i] = fov_list[i] * PI / 180.0f;
					}
				}

				if (optional_string("$Detail Distance Multiplier:"))
					parse_float_list(profile->detail_distance_mult, NUM_SKILL_LEVELS);

				set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AIPF_BIG_SHIPS_CAN_ATTACK_BEAM_TURRETS_ON_UNTARGETED_SHIPS, AIP_FLAG);

				set_flag(profile, "$smart primary weapon selection:", AIPF_SMART_PRIMARY_WEAPON_SELECTION, AIP_FLAG);

				set_flag(profile, "$smart secondary weapon selection:", AIPF_SMART_SECONDARY_WEAPON_SELECTION, AIP_FLAG);

				set_flag(profile, "$smart shield management:", AIPF_SMART_SHIELD_MANAGEMENT, AIP_FLAG);

				set_flag(profile, "$smart afterburner management:", AIPF_SMART_AFTERBURNER_MANAGEMENT, AIP_FLAG);

				set_flag(profile, "$allow rapid secondary dumbfire:", AIPF_ALLOW_RAPID_SECONDARY_DUMBFIRE, AIP_FLAG);

				set_flag(profile, "$huge turret weapons ignore bombs:", AIPF_HUGE_TURRET_WEAPONS_IGNORE_BOMBS, AIP_FLAG);

				set_flag(profile, "$don't insert random turret fire delay:", AIPF_DONT_INSERT_RANDOM_TURRET_FIRE_DELAY, AIP_FLAG);

				set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AIPF_HACK_IMPROVE_NON_HOMING_SWARM_TURRET_FIRE_ACCURACY, AIP_FLAG);

				set_flag(profile, "$shockwaves damage small ship subsystems:", AIPF_SHOCKWAVES_DAMAGE_SMALL_SHIP_SUBSYSTEMS, AIP_FLAG);

				set_flag(profile, "$navigation subsystem governs warpout capability:", AIPF_NAVIGATION_SUBSYS_GOVERNS_WARP, AIP_FLAG);

				set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AIPF_NO_MIN_DOCK_SPEED_CAP, AIP_FLAG);

				set_flag(profile, "$disable linked fire penalty:", AIPF_DISABLE_LINKED_FIRE_PENALTY, AIP_FLAG);

				set_flag(profile, "$disable weapon damage scaling:", AIPF_DISABLE_WEAPON_DAMAGE_SCALING, AIP_FLAG);

				set_flag(profile, "$use additive weapon velocity:", AIPF_USE_ADDITIVE_WEAPON_VELOCITY, AIP_FLAG);

				set_flag(profile, "$use newtonian dampening:", AIPF_USE_NEWTONIAN_DAMPENING, AIP_FLAG);

				set_flag(profile, "$include beams for kills and assists:", AIPF_INCLUDE_BEAMS_IN_STAT_CALCS, AIP_FLAG);

				set_flag(profile, "$score kills based on damage caused:", AIPF_KILL_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG);

				set_flag(profile, "$score assists based on damage caused:", AIPF_ASSIST_SCORING_SCALES_WITH_DAMAGE, AIP_FLAG);

				set_flag(profile, "$allow event and goal scoring in multiplayer:", AIPF_ALLOW_MULTI_EVENT_SCORING, AIP_FLAG);

				set_flag(profile, "$fix linked primary weapon decision bug:", AIPF_FIX_LINKED_PRIMARY_BUG, AIP_FLAG);

				set_flag(profile, "$prevent turrets targeting too distant bombs:", AIPF_PREVENT_TARGETING_BOMBS_BEYOND_RANGE, AIP_FLAG);

				set_flag(profile, "$smart subsystem targeting for turrets:", AIPF_SMART_SUBSYSTEM_TARGETING_FOR_TURRETS, AIP_FLAG);

				set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AIPF_FIX_HEAT_SEEKER_STEALTH_BUG, AIP_FLAG);

				set_flag(profile, "$multi allow empty primaries:", AIPF_MULTI_ALLOW_EMPTY_PRIMARIES, AIP_FLAG);

				set_flag(profile, "$multi allow empty secondaries:", AIPF_MULTI_ALLOW_EMPTY_SECONDARIES, AIP_FLAG);

				set_flag(profile, "$allow turrets target weapons freely:", AIPF_ALLOW_TURRETS_TARGET_WEAPONS_FREELY, AIP_FLAG);

				set_flag(profile, "$use only single fov for turrets:", AIPF_USE_ONLY_SINGLE_FOV_FOR_TURRETS, AIP_FLAG);

				set_flag(profile, "$allow vertical dodge:", AIPF_ALLOW_VERTICAL_DODGE, AIP_FLAG);

				set_flag(profile, "$force beam turrets to use normal fov:", AIPF_FORCE_BEAM_TURRET_FOV, AIP_FLAG);

				set_flag(profile, "$fix ai class bug:", AIPF_FIX_AI_CLASS_BUG, AIP_FLAG);

				set_flag(profile, "$turrets ignore targets radius in range checks:", AIPF2_TURRETS_IGNORE_TARGET_RADIUS, AIP_FLAG2);

				set_flag(profile, "$no extra collision avoidance vs player:", AIPF2_NO_SPECIAL_PLAYER_AVOID, AIP_FLAG2);

				set_flag(profile, "$perform fewer checks for death screams:", AIPF2_PERFORM_FEWER_SCREAM_CHECKS, AIP_FLAG2);

				set_flag(profile, "$advanced turret fov edge checks:", AIPF2_ADVANCED_TURRET_FOV_EDGE_CHECKS, AIP_FLAG2);

				set_flag(profile, "$require turrets to have target in fov:", AIPF2_REQUIRE_TURRET_TO_HAVE_TARGET_IN_FOV, AIP_FLAG2);

				set_flag(profile, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2);

				set_flag(profile, "$ai aims from ship center:", AIPF2_AI_AIMS_FROM_SHIP_CENTER, AIP_FLAG2);

				set_flag(profile, "$allow primary link at mission start:", AIPF2_ALLOW_PRIMARY_LINK_AT_START, AIP_FLAG2);

				set_flag(profile, "$allow beams to damage bombs:", AIPF2_BEAMS_DAMAGE_WEAPONS, AIP_FLAG2);

				set_flag(profile, "$disable weapon damage scaling for player:", AIPF2_PLAYER_WEAPON_SCALE_FIX, AIP_FLAG2);

				set_flag(profile, "$countermeasures affect aspect seekers:", AIPF2_ASPECT_LOCK_COUNTERMEASURE, AIP_FLAG2);

				set_flag(profile, "$ai guards specific ship in wing:", AIPF2_AI_GUARDS_SPECIFIC_SHIP_IN_WING, AIP_FLAG2);

				profile->ai_path_mode = AI_PATH_MODE_NORMAL;
				if (optional_string("$ai path mode:"))
				{
					stuff_string(buf, F_NAME, NAME_LENGTH);
					int j = ai_path_type_match(buf);
					if (j >= 0) {
						profile->ai_path_mode = j;
					}
					else {
						Warning(LOCATION, "Invalid ai path mode '%s' specified", buf);
					}
				}

				set_flag(profile, "$no warp camera:", AIPF2_NO_WARP_CAMERA, AIP_FLAG2);

				set_flag(profile, "$fix ai path order bug:", AIPF2_FIX_AI_PATH_ORDER_BUG, AIP_FLAG2);

				set_flag(profile, "$strict turret-tagged-only targeting:", AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING, AIP_FLAG2);

				set_flag(profile, "$aspect bomb invulnerability fix:", AIPF2_ASPECT_INVULNERABILITY_FIX, AIP_FLAG2);

				set_flag(profile, "$glide decay requires thrust:", AIPF2_GLIDE_DECAY_REQUIRES_THRUST, AIP_FLAG2);

				set_flag(profile, "$ai can slow down when attacking big ships:", AIPF2_AI_CAN_SLOW_DOWN_ATTACKING_BIG_SHIPS, AIP_FLAG2);

				profile->bay_arrive_speed_mult = 1.0f;
				profile->bay_depart_speed_mult = 1.0f;
				if (optional_string("$bay arrive speed multiplier:")) {
					stuff_float(&profile->bay_arrive_speed_mult);
				}
				if (optional_string("$bay depart speed multiplier:")) {
					stuff_float(&profile->bay_depart_speed_mult);
				}

				// ----------

				// compatibility
				if (optional_string("$perform less checks for death screams:"))
				{
					mprintf(("Warning: \"$perform less checks for death screams\" flag is deprecated in favor of \"$perform fewer checks for death screams\"\n"));
					bool temp;
					stuff_boolean(&temp);
					if (temp)
						profile->flags2 |= AIPF2_PERFORM_FEWER_SCREAM_CHECKS;
					else
						profile->flags2 &= ~AIPF2_PERFORM_FEWER_SCREAM_CHECKS;
				}
				if (optional_string("$allow primary link delay:"))
				{
					mprintf(("Warning: \"$allow primary link delay\" flag is deprecated in favor of \"$allow primary link at mission start\"\n"));
					bool temp;
					stuff_boolean(&temp);
					if (temp)
						profile->flags2 &= ~AIPF2_ALLOW_PRIMARY_LINK_AT_START;
					else
						profile->flags2 |= AIPF2_ALLOW_PRIMARY_LINK_AT_START;
				}


				// if we've been through once already and are at the same place, force a move
				if (saved_Mp && (saved_Mp == Mp))
				{
					char tmp[60];
					memset(tmp, 0, 60);
					strncpy(tmp, Mp, 59);
					mprintf(("WARNING: Unrecognized parameter in ai_profiles: %s\n", tmp));

					Mp++;
				}

				// find next valid option
				skip_to_start_of_string_either("$", "#");
				saved_Mp = Mp;
			}
		}

		required_string("#End");
	}
	catch (const parse::ParseException& e)
	{
		mprintf(("TABLES: Unable to parse '%s'!  Error message = %s.\n", (filename) ? filename : "<default ai_profiles.tbl>", e.what()));
		return;
	}

	// add tbl/tbm to multiplayer validation list
	extern void fs2netd_add_table_validation(const char *tblname);
	fs2netd_add_table_validation(filename);
}
void parse_gamesnd_new(game_snd* gs, bool no_create)
{
	char name[MAX_FILENAME_LEN];
	// New extended format found
	stuff_string(name, F_NAME, MAX_FILENAME_LEN);

	if (!stricmp(name, NOX("empty")))
	{
		gs->filename[0] = 0;
		return;
	}

	// If the name _doesn't_ match <same> put it into gs->filename;
	if (stricmp(name, "<same>"))
	{
		strcpy_s(gs->filename, name);
	}
	else if (!no_create)
	{
		// Throw an error if <same> was specified but we are creating a new entry
		error_display(1, "'<same>' is only allowed if +nocreate was specified!");
		return;
	}

	if (required_string_no_create("+Preload:", no_create))
	{
		stuff_boolean(&gs->preload);
	}

	if (required_string_no_create("+Volume:", no_create))
	{
		stuff_float(&gs->default_volume);
	}

	if (optional_string("+3D Sound:"))
	{
		gs->flags |= GAME_SND_USE_DS3D;
		required_string("+Attenuation start:");

		stuff_int(&gs->min);

		required_string("+Attenuation end:");

		stuff_int(&gs->max);
	}
	else
	{
		gs->min = 0;
		gs->max = 0;
	}

	// jg18 - enhanced sound parameters
	if (optional_string("+Priority:"))
	{
		SCP_string priority_string;
		stuff_string(priority_string, F_NAME);
		EnhancedSoundPriority priority = convert_to_enhanced_priority(priority_string.c_str());
		if (priority != SND_ENHANCED_PRIORITY_INVALID)
		{
			gs->enhanced_sound_data.priority= priority;
		}
		// else case not needed since conversion function displays message on error
	}

	if (optional_string("+Limit:"))
	{
		int temp_limit;
		stuff_int(&temp_limit);

		if ((temp_limit > 0) && (static_cast<uint>(temp_limit) <= SND_ENHANCED_MAX_LIMIT))
		{
			gs->enhanced_sound_data.limit = (unsigned int)temp_limit;
		}
		else
		{
			error_display(1, "Invalid enhanced sound limit: %d\n", temp_limit);
		}
	}
}
Esempio n. 18
0
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");
	}
}
Esempio n. 19
0
void parse_medal_tbl()
{
	int rval, i;
	int num_badges = 0;

	// open localization
	lcl_ext_open();

	if ((rval = setjmp(parse_abort)) != 0)
	{
		mprintf(("TABLES: Unable to parse '%s'!  Error code = %i.\n", "medals.tbl", rval));
		lcl_ext_close();
		return;
	}

	read_file_text("medals.tbl", CF_TYPE_TABLES);
	reset_parse();

	// parse in all the rank names
	Num_medals = 0;
	required_string("#Medals");
	while (required_string_either("#End", "$Name:"))
	{
		medal_stuff temp_medal;

		required_string("$Name:");
		stuff_string(temp_medal.name, F_NAME, NAME_LENGTH);

		required_string("$Bitmap:");
		stuff_string(temp_medal.bitmap, F_NAME, MAX_FILENAME_LEN);

		required_string("$Num mods:");
		stuff_int(&temp_medal.num_versions);

		// 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];

			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);
			//stuff_string(Badge_info[bi].wave2, F_NAME, NULL, MAX_FILENAME_LEN);

			if (optional_string("$Wavefile Base:"))
				stuff_string(temp_medal.voice_base, F_NAME, MAX_FILENAME_LEN);

			//required_string("$Wavefile 2:");
			//stuff_string(Badge_info[bi].wave2, F_NAME, NULL, MAX_FILENAME_LEN);

			required_string("$Promotion Text:");
			stuff_string(buf, F_MULTITEXT, sizeof(buf));
			temp_medal.promotion_text = vm_strdup(buf);

			// since badges (ace ranks) are handled a little differently we need to know
			// which we are in the list of badges.
			temp_medal.badge_num = num_badges++;
		}

		Medals.push_back(temp_medal);
	}

	required_string("#End");

	Num_medals = Medals.size();
	Assert(Num_medals == MAX_MEDALS);

	// 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;
	}

	// close localization
	lcl_ext_close();
}
Esempio n. 20
0
void script_parse_table(char* filename)
{
	script_state* st = &Script_system;
	int rval;
	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();

	if (optional_string("#Global Hooks"))
	{
		//int num = 42;
		//Script_system.SetHookVar("Version", 'i', &num);
		if (optional_string("$Global:"))
		{
			Script_globalhook = st->ParseChunk("Global");
		}

		if (optional_string("$Splash:"))
		{
			Script_splashhook = st->ParseChunk("Splash");
		}

		if (optional_string("$GameInit:"))
		{
			Script_gameinithook = st->ParseChunk("GameInit");
		}

		if (optional_string("$Simulation:"))
		{
			Script_simulationhook = st->ParseChunk("Simulation");
		}

		if (optional_string("$HUD:"))
		{
			Script_hudhook = st->ParseChunk("HUD");
		}

		required_string("#End");
	}
	/*
		if(optional_string("#State Hooks"))
		{
			while(optional_string("$State:")) {
				char buf[NAME_LENGTH];
				int idx;
				stuff_string(buf, F_NAME, sizeof(buf));
	
				idx = gameseq_get_state_idx(buf);
	
				if(optional_string("$Hook:"))
				{
					if(idx > -1) {
						GS_state_hooks[idx] = st->ParseChunk(buf);
					} else {
						st->ParseChunk(buf);
					}
				}
			}
			required_string("#End");
		}
	*/
	if (optional_string("#Conditional Hooks"))
	{
		while (st->ParseCondition(filename));
		required_string("#End");
	}

	// add tbl/tbm to multiplayer validation list
	extern void fs2netd_add_table_validation(char* tblname);
	fs2netd_add_table_validation(filename);
}
Esempio n. 21
0
/**
 * 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;
	}
}
  bool generate() {
    code_.Clear();
    code_ += "{";
    code_ += "  \"$schema\": \"http://json-schema.org/draft-04/schema#\",";
    code_ += "  \"definitions\": {";
    for (auto e = parser_.enums_.vec.cbegin(); e != parser_.enums_.vec.cend();
         ++e) {
      code_ += "    \"" + GenFullName(*e) + "\" : {";
      code_ += "      " + GenType("string") + ",";
      std::string enumdef("      \"enum\": [");
      for (auto enum_value = (*e)->vals.vec.begin();
           enum_value != (*e)->vals.vec.end(); ++enum_value) {
        enumdef.append("\"" + (*enum_value)->name + "\"");
        if (*enum_value != (*e)->vals.vec.back()) { enumdef.append(", "); }
      }
      enumdef.append("]");
      code_ += enumdef;
      code_ += "    },";  // close type
    }
    for (auto s = parser_.structs_.vec.cbegin();
         s != parser_.structs_.vec.cend(); ++s) {
      const auto &structure = *s;
      code_ += "    \"" + GenFullName(structure) + "\" : {";
      code_ += "      " + GenType("object") + ",";
      std::string comment;
      const auto &comment_lines = structure->doc_comment;
      for (auto comment_line = comment_lines.cbegin();
           comment_line != comment_lines.cend(); ++comment_line) {
        comment.append(*comment_line);
      }
      if (comment.size() > 0) {
        code_ += "      \"description\" : \"" + comment + "\",";
      }
      code_ += "      \"properties\" : {";

      const auto &properties = structure->fields.vec;
      for (auto prop = properties.cbegin(); prop != properties.cend(); ++prop) {
        const auto &property = *prop;
        std::string typeLine("        \"" + property->name + "\" : { " +
                             GenType(property->value.type) + " }");
        if (property != properties.back()) { typeLine.append(","); }
        code_ += typeLine;
      }
      code_ += "      },";  // close properties

      std::vector<FieldDef *> requiredProperties;
      std::copy_if(properties.begin(), properties.end(),
                   back_inserter(requiredProperties),
                   [](FieldDef const *prop) { return prop->required; });
      if (requiredProperties.size() > 0) {
        std::string required_string("      \"required\" : [");
        for (auto req_prop = requiredProperties.cbegin();
             req_prop != requiredProperties.cend(); ++req_prop) {
          required_string.append("\"" + (*req_prop)->name + "\"");
          if (*req_prop != requiredProperties.back()) {
            required_string.append(", ");
          }
        }
        required_string.append("],");
        code_ += required_string;
      }
      code_ += "      \"additionalProperties\" : false";
      std::string closeType("    }");
      if (*s != parser_.structs_.vec.back()) { closeType.append(","); }
      code_ += closeType;  // close type
    }
    code_ += "  },";  // close definitions

    // mark root type
    code_ += "  \"$ref\" : \"#/definitions/" +
             GenFullName(parser_.root_struct_def_) + "\"";

    code_ += "}";  // close schema root
    const std::string file_path = GeneratedFileName(path_, file_name_);
    const std::string final_code = code_.ToString();
    return SaveFile(file_path.c_str(), final_code, false);
  }
Esempio n. 23
0
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;
	}
}
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;
	}
}
// 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
}
Esempio n. 26
0
// -------------------------------------------------------------------------------------------------
// gamesnd_parse_soundstbl() will parse the sounds.tbl file, and load the specified sounds.
//
//
void gamesnd_parse_soundstbl()
{
	int rval;
	int num_game_sounds = 0;
	int num_iface_sounds = 0;
	int i;
	char cstrtemp[NAME_LENGTH+3];
	char* missing_species_names = NULL;
	ubyte* missing_species = NULL;
	int sanity_check = 0;

	gamesnd_init_sounds();

	// open localization
	lcl_ext_open();

	if ((rval = setjmp(parse_abort)) != 0)
	{
		mprintf(("TABLES: Unable to parse '%s'!  Error code = %i.\n", "sounds.tbl", rval));
		lcl_ext_close();
		return;
	}

	read_file_text("sounds.tbl", CF_TYPE_TABLES);
	reset_parse();

	// Parse the gameplay sounds section
	required_string("#Game Sounds Start");
	while (required_string_either("#Game Sounds End", "$Name:"))
	{
		Assert(num_game_sounds < Num_game_sounds);
		gamesnd_parse_line(&Snds[num_game_sounds], "$Name:");
		num_game_sounds++;
		gamesnd_add_sound_slot(GAME_SND, num_game_sounds);
	}
	required_string("#Game Sounds End");

	// Parse the interface sounds section
	required_string("#Interface Sounds Start");
	while (required_string_either("#Interface Sounds End", "$Name:"))
	{
		Assert(num_iface_sounds < Num_iface_sounds);
		gamesnd_parse_line(&Snds_iface[num_iface_sounds], "$Name:");
		num_iface_sounds++;
		gamesnd_add_sound_slot(IFACE_SND, num_iface_sounds);
	}
	required_string("#Interface Sounds End");

	// parse flyby sound section	
	required_string("#Flyby Sounds Start");

	missing_species_names = new char[Species_info.size() * (NAME_LENGTH + 2)];
	missing_species = new ubyte[Species_info.size()];

	memset(missing_species_names, 0, Species_info.size() * (NAME_LENGTH + 2));
	memset(missing_species, 1, Species_info.size());	// assume they are all missing

	while (!check_for_string("#Flyby Sounds End") && (sanity_check <= (int)Species_info.size()))
	{
		for (i = 0; i < (int)Species_info.size(); i++)
		{
			species_info* species = &Species_info[i];

			sprintf(cstrtemp, "$%s:", species->species_name);

			if (check_for_string(cstrtemp))
			{
				gamesnd_parse_line(&species->snd_flyby_fighter, cstrtemp);
				gamesnd_parse_line(&species->snd_flyby_bomber, cstrtemp);
				missing_species[i] = 0;
				sanity_check--;
			}
			else
			{
				sanity_check++;
			}
		}
	}

	// if we are missing any species then report it
	for (i = 0; i < (int)Species_info.size(); i++)
	{
		if (missing_species[i])
		{
			strcat(missing_species_names, Species_info[i].species_name);
			strcat(missing_species_names, "\n");
		}
	}

	if (strlen(missing_species_names))
	{
		Error(LOCATION, "The following species are missing flyby sounds in sounds.tbl:\n%s", missing_species_names);
	}

	delete[] missing_species_names;
	delete[] missing_species;

	required_string("#Flyby Sounds End");

	// close localization
	lcl_ext_close();
}
Esempio n. 27
0
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");
	}
}
Esempio n. 28
0
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;
	}
}
Esempio n. 29
0
// initialization stuff for cutscenes
void cutscene_init()
{
	atexit(cutscene_close);
	char buf[MULTITEXT_LENGTH];
	int rval;
    cutscene_info cutinfo;

	// open localization
	lcl_ext_open();

	if ((rval = setjmp(parse_abort)) != 0) {
		mprintf(("TABLES: Unable to parse '%s'!  Error code = %i.\n", "cutscenes.tbl", rval));
		lcl_ext_close();
		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:") ) 
    {
        memset(&cutinfo, 0, sizeof(cutscene_info));

		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);

		required_string("$cd:");
		stuff_int( &cutinfo.cd );

		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");

	// close localization
	lcl_ext_close();
}
void parse_sound_table(const char* filename)
{
	try
	{
		read_file_text(filename, CF_TYPE_TABLES);
		reset_parse();

		// Parse the gameplay sounds section
		if (optional_string("#Game Sounds Start"))
		{
			while (!check_for_string("#Game Sounds End"))
			{
				game_snd tempSound;
				if (gamesnd_parse_line(&tempSound, "$Name:", &Snds))
				{
					Snds.push_back(game_snd(tempSound));
				}
			}

			required_string("#Game Sounds End");
		}

		// Parse the interface sounds section
		if (optional_string("#Interface Sounds Start"))
		{
			while (!check_for_string("#Interface Sounds End"))
			{
				game_snd tempSound;
				if (gamesnd_parse_line(&tempSound, "$Name:", &Snds_iface))
				{
					Snds_iface.push_back(game_snd(tempSound));
					Snds_iface_handle.push_back(-1);
				}
			}

			required_string("#Interface Sounds End");
		}

		// parse flyby sound section
		if (optional_string("#Flyby Sounds Start"))
		{
			char species_name_tag[NAME_LENGTH + 2];
			int	sanity_check = 0;
			size_t i;

			while (!check_for_string("#Flyby Sounds End") && (sanity_check <= (int)Species_info.size()))
			{
				for (i = 0; i < Species_info.size(); i++)
				{
					species_info *species = &Species_info[i];

					sprintf(species_name_tag, "$%s:", species->species_name);

					if (check_for_string(species_name_tag))
					{
						gamesnd_parse_line(&species->snd_flyby_fighter, species_name_tag);
						gamesnd_parse_line(&species->snd_flyby_bomber, species_name_tag);
						sanity_check--;
					}
					else
					{
						sanity_check++;
					}
				}
			}

			required_string("#Flyby Sounds End");
		}

		if (optional_string("#Sound Environments Start"))
		{
			parse_sound_environments();
		}
	}
	catch (const parse::ParseException& e)
	{
		mprintf(("TABLES: Unable to parse '%s'!  Error message = %s.\n", filename, e.what()));
		return;
	}

	gamesnd_add_retail_default_enhanced_sound_data();
}