Beispiel #1
0
void MenuPowers::loadUpgrade(FileParser &infile) {
	// @ATTR upgrade.id|integer|A power id from powers/powers.txt for this upgrade.
	if (infile.key == "id") {
		int id = popFirstInt(infile.val);
		if (id > 0) {
			skip_section = false;
			power_cell_upgrade.back().id = static_cast<short>(id);
		}
		else {
			skip_section = true;
			power_cell_upgrade.pop_back();
			infile.error("MenuPowers: Power index out of bounds 1-%d, skipping power.", INT_MAX);
		}
		return;
	}

	if (skip_section)
		return;

	// @ATTR upgrade.requires_physoff|integer|Upgrade requires Physical and Offense stat of this value.
	if (infile.key == "requires_physoff") power_cell_upgrade.back().requires_physoff = static_cast<short>(toInt(infile.val));
	// @ATTR upgrade.requires_physdef|integer|Upgrade requires Physical and Defense stat of this value.
	else if (infile.key == "requires_physdef") power_cell_upgrade.back().requires_physdef = static_cast<short>(toInt(infile.val));
	// @ATTR upgrade.requires_mentoff|integer|Upgrade requires Mental and Offense stat of this value.
	else if (infile.key == "requires_mentoff") power_cell_upgrade.back().requires_mentoff = static_cast<short>(toInt(infile.val));
	// @ATTR upgrade.requires_mentdef|integer|Upgrade requires Mental and Defense stat of this value.
	else if (infile.key == "requires_mentdef") power_cell_upgrade.back().requires_mentdef = static_cast<short>(toInt(infile.val));

	// @ATTR upgrade.requires_defense|integer|Upgrade requires Defense stat of this value.
	else if (infile.key == "requires_defense") power_cell_upgrade.back().requires_defense = static_cast<short>(toInt(infile.val));
	// @ATTR upgrade.requires_offense|integer|Upgrade requires Offense stat of this value.
	else if (infile.key == "requires_offense") power_cell_upgrade.back().requires_offense = static_cast<short>(toInt(infile.val));
	// @ATTR upgrade.requires_physical|integer|Upgrade requires Physical stat of this value.
	else if (infile.key == "requires_physical") power_cell_upgrade.back().requires_physical = static_cast<short>(toInt(infile.val));
	// @ATTR upgrade.requires_mental|integer|Upgrade requires Mental stat of this value.
	else if (infile.key == "requires_mental") power_cell_upgrade.back().requires_mental = static_cast<short>(toInt(infile.val));

	// @ATTR upgrade.requires_point|boolean|Upgrade requires a power point to unlock.
	else if (infile.key == "requires_point") power_cell_upgrade.back().requires_point = toBool(infile.val);
	// @ATTR upgrade.requires_level|integer|Upgrade requires at least this level for the hero.
	else if (infile.key == "requires_level") power_cell_upgrade.back().requires_level = static_cast<short>(toInt(infile.val));
	// @ATTR upgrade.requires_power|integer|Upgrade requires another power id.
	else if (infile.key == "requires_power") power_cell_upgrade.back().requires_power.push_back(static_cast<short>(toInt(infile.val)));

	// @ATTR upgrade.visible_requires_status|string|Hide the upgrade if we don't have this campaign status.
	else if (infile.key == "visible_requires_status") power_cell_upgrade.back().visible_requires_status.push_back(infile.val);
	// @ATTR upgrade.visible_requires_not_status|string|Hide the upgrade if we have this campaign status.
	else if (infile.key == "visible_requires_not_status") power_cell_upgrade.back().visible_requires_not.push_back(infile.val);

	else infile.error("MenuPowers: '%s' is not a valid key.", infile.key.c_str());
}
Beispiel #2
0
void Map::loadLayer(FileParser &infile) {
	if (infile.key == "type") {
		// @ATTR layer.type|string|Map layer type.
		layers.resize(layers.size()+1);
		layers.back().resize(w);
		for (size_t i=0; i<layers.back().size(); ++i) {
			layers.back()[i].resize(h);
		}
		layernames.push_back(infile.val);
		if (infile.val == "collision")
			collision_layer = static_cast<int>(layernames.size())-1;
	}
	else if (infile.key == "format") {
		// @ATTR layer.format|string|Format for map layer, must be 'dec'
		if (infile.val != "dec") {
			infile.error("Map: The format of a layer must be 'dec'!");
			logErrorDialog("Map: The format of a layer must be 'dec'!");
			mods->resetModConfig();
			Exit(1);
		}
	}
	else if (infile.key == "data") {
		// @ATTR layer.data|raw|Raw map layer data
		// layer map data handled as a special case
		// The next h lines must contain layer data.
		for (int j=0; j<h; j++) {
			std::string val = infile.getRawLine();
			infile.incrementLineNum();
			if (!val.empty() && val[val.length()-1] != ',') {
				val += ',';
			}

			// verify the width of this row
			int comma_count = 0;
			for (unsigned i=0; i<val.length(); ++i) {
				if (val[i] == ',') comma_count++;
			}
			if (comma_count != w) {
				infile.error("Map: A row of layer data has a width not equal to %d.", w);
				mods->resetModConfig();
				Exit(1);
			}

			for (int i=0; i<w; i++)
				layers.back()[i][j] = static_cast<unsigned short>(popFirstInt(val));
		}
	}
	else {
		infile.error("Map: '%s' is not a valid key.", infile.key.c_str());
	}
}
MenuExit::MenuExit() : Menu() {

	// Load config settings
	FileParser infile;
	if(infile.open("menus/exit.txt")) {
		while(infile.next()) {
			if (parseMenuKey(infile.key, infile.val))
				continue;
			else
				infile.error("MenuExit: '%s' is not a valid key.", infile.key.c_str());
		}
		infile.close();
	}

	exitClicked = false;

	buttonExit = new WidgetButton();

	if (SAVE_ONEXIT)
		buttonExit->label = msg->get("Save & Exit");
	else
		buttonExit->label = msg->get("Exit");

	buttonClose = new WidgetButton("images/menus/buttons/button_x.png");

	setBackground("images/menus/confirm_bg.png");

	tablist.add(buttonExit);
	tablist.add(buttonClose);

	align();
}
Beispiel #4
0
void GameStatePlay::loadTitles() {
	FileParser infile;
	// @CLASS GameStatePlay: Titles|Description of engine/titles.txt
	if (infile.open("engine/titles.txt")) {
		while (infile.next()) {
			if (infile.new_section && infile.section == "title") {
				Title t;
				titles.push_back(t);
			}

			if (titles.empty()) continue;

			// @ATTR title.title|string|The displayed title.
			if (infile.key == "title") titles.back().title = infile.val;
			// @ATTR title.level|int|Requires level.
			else if (infile.key == "level") titles.back().level = toInt(infile.val);
			// @ATTR title.power|power_id|Requires power.
			else if (infile.key == "power") titles.back().power = toInt(infile.val);
			// @ATTR title.requires_status|string|Requires status.
			else if (infile.key == "requires_status") titles.back().requires_status = infile.val;
			// @ATTR title.requires_not_status|string|Requires not status.
			else if (infile.key == "requires_not_status") titles.back().requires_not = infile.val;
			// @ATTR title.primary_stat|predefined_string, predefined_string : Primary stat, Lesser primary stat|Required primary stat(s). The lesser stat is optional.
			else if (infile.key == "primary_stat") {
				titles.back().primary_stat_1 = popFirstString(infile.val);
				titles.back().primary_stat_2 = popFirstString(infile.val);
			}
			else infile.error("GameStatePlay: '%s' is not a valid key.", infile.key.c_str());
		}
		infile.close();
	}
}
MenuActiveEffects::MenuActiveEffects(StatBlock *_stats)
	: timer(NULL)
	, stats(_stats)
	, orientation(false) { // horizontal
	// Load config settings
	FileParser infile;
	// @CLASS MenuActiveEffects|Description of menus/activeeffects.txt
	if(infile.open("menus/activeeffects.txt")) {
		while(infile.next()) {
			if (parseMenuKey(infile.key, infile.val))
				continue;

			// @ATTR orientation|bool|True is vertical orientation; False is horizontal orientation.
			if(infile.key == "orientation") {
				orientation = toBool(infile.val);
			}
			else {
				infile.error("MenuActiveEffects: '%s' is not a valid key.", infile.key.c_str());
			}
		}
		infile.close();
	}

	loadGraphics();
	align();
}
Beispiel #6
0
void MenuBook::loadText(FileParser &infile) {
	// @ATTR text.text_pos|int, int, int, ["left", "center", "right"] : X, Y, Width, Text justify|Position of the text.
	if (infile.key == "text_pos") {
		size.back().x = popFirstInt(infile.val);
		size.back().y = popFirstInt(infile.val);
		size.back().w = popFirstInt(infile.val);
		std::string _justify = popFirstString(infile.val);

		if (_justify == "left") justify.back() = JUSTIFY_LEFT;
		else if (_justify == "center") justify.back() = JUSTIFY_CENTER;
		else if (_justify == "right") justify.back() = JUSTIFY_RIGHT;
	}
	// @ATTR text.text_font|color, string : Font color, Font style|Font color and style.
	else if (infile.key == "text_font") {
		Color color;
		color.r = static_cast<Uint8>(popFirstInt(infile.val));
		color.g = static_cast<Uint8>(popFirstInt(infile.val));
		color.b = static_cast<Uint8>(popFirstInt(infile.val));
		textColor.back() = color;
		textFont.back() = popFirstString(infile.val);
	}
	// @ATTR text.text|string|The text to be displayed.
	else if (infile.key == "text") {
		// we use substr here to remove the comma from the end
		textData.back() = msg->get(infile.val.substr(0, infile.val.length() - 1));
	}
	else {
		infile.error("MenuBook: '%s' is not a valid key.", infile.key.c_str());
	}
}
void GameSwitcher::loadMusic() {
	if (AUDIO && MUSIC_VOLUME) {
		Mix_FreeMusic(music);
		music = NULL;

		std::string music_filename = "";
		FileParser infile;
		// @CLASS GameSwitcher: Default music|Description of engine/default_music.txt
		if (infile.open("engine/default_music.txt", true, "")) {
			while (infile.next()) {
				// @ATTR music|string|Filename of a music file to play during game states that don't already have music.
				if (infile.key == "music") music_filename = infile.val;
				else infile.error("GameSwitcher: '%s' is not a valid key.", infile.key.c_str());
			}
			infile.close();
		}

		if (music_filename != "") {
			music = Mix_LoadMUS((mods->locate(music_filename)).c_str());
			if (!music)
				logError("GameSwitcher: Mix_LoadMUS: %s\n", Mix_GetError());
		}
	}

	if (music) {
		Mix_VolumeMusic(MUSIC_VOLUME);
		Mix_PlayMusic(music, -1);
	}
}
MenuHUDLog::MenuHUDLog()
	: overlay_bg(NULL)
	, click_to_dismiss(false)
	, hide_overlay(false)
{

	// Load config settings
	FileParser infile;
	if(infile.open("menus/hudlog.txt")) {
		while(infile.next()) {
			if (parseMenuKey(infile.key, infile.val))
				continue;
			else
				infile.error("MenuHUDLog: '%s' is not a valid key.", infile.key.c_str());
		}
		infile.close();
	}

	align();

	font->setFont("font_regular");
	paragraph_spacing = font->getLineHeight()/2;

	color_normal = font->getColor("menu_normal");
}
CombatText::CombatText() {
	msg_color[MSG_GIVEDMG] = font->getColor(FontEngine::COLOR_COMBAT_GIVEDMG);
	msg_color[MSG_TAKEDMG] = font->getColor(FontEngine::COLOR_COMBAT_TAKEDMG);
	msg_color[MSG_CRIT] = font->getColor(FontEngine::COLOR_COMBAT_CRIT);
	msg_color[MSG_BUFF] = font->getColor(FontEngine::COLOR_COMBAT_BUFF);
	msg_color[MSG_MISS] = font->getColor(FontEngine::COLOR_COMBAT_MISS);

	duration = settings->max_frames_per_sec; // 1 second
	speed = 60.f / settings->max_frames_per_sec;
	offset = 48; // average height of flare-game enemies, so a sensible default

	// Load config settings
	FileParser infile;
	// @CLASS CombatText|Description of engine/combat_text.txt
	if(infile.open("engine/combat_text.txt", FileParser::MOD_FILE, FileParser::ERROR_NORMAL)) {
		while(infile.next()) {
			if(infile.key == "duration") {
				// @ATTR duration|duration|Duration of the combat text in 'ms' or 's'.
				duration = Parse::toDuration(infile.val);
			}
			else if(infile.key == "speed") {
				// @ATTR speed|int|Motion speed of the combat text.
				speed = static_cast<float>(Parse::toInt(infile.val) * 60) / settings->max_frames_per_sec;
			}
			else if (infile.key == "offset") {
				// @ATTR offset|int|The vertical offset for the combat text's starting position.
				offset = Parse::toInt(infile.val);
			}
			else {
				infile.error("CombatText: '%s' is not a valid key.",infile.key.c_str());
			}
		}
		infile.close();
	}
}
Beispiel #10
0
CombatText::CombatText() {
	msg_color[COMBAT_MESSAGE_GIVEDMG] = font->getColor("combat_givedmg");
	msg_color[COMBAT_MESSAGE_TAKEDMG] = font->getColor("combat_takedmg");
	msg_color[COMBAT_MESSAGE_CRIT] = font->getColor("combat_crit");
	msg_color[COMBAT_MESSAGE_BUFF] = font->getColor("combat_buff");
	msg_color[COMBAT_MESSAGE_MISS] = font->getColor("combat_miss");

	duration = MAX_FRAMES_PER_SEC; // 1 second
	speed = 60.f / MAX_FRAMES_PER_SEC;
	offset = 48; // average height of flare-game enemies, so a sensible default

	// Load config settings
	FileParser infile;
	// @CLASS CombatText|Description of engine/combat_text.txt
	if(infile.open("engine/combat_text.txt")) {
		while(infile.next()) {
			if(infile.key == "duration") {
				// @ATTR duration|duration|Duration of the combat text in 'ms' or 's'.
				duration = parse_duration(infile.val);
			}
			else if(infile.key == "speed") {
				// @ATTR speed|int|Motion speed of the combat text.
				speed = static_cast<float>(toInt(infile.val) * 60) / MAX_FRAMES_PER_SEC;
			}
			else if (infile.key == "offset") {
				// @ATTR offset|int|The vertical offset for the combat text's starting position.
				offset = toInt(infile.val);
			}
			else {
				infile.error("CombatText: '%s' is not a valid key.",infile.key.c_str());
			}
		}
		infile.close();
	}
}
Beispiel #11
0
void MenuBook::loadText(FileParser &infile) {
	// @ATTR text.text_pos|x (integer), y (integer), w (integer), [left:center:right]|Position of the text.
	if (infile.key == "text_pos") {
		size.back().x = popFirstInt(infile.val);
		size.back().y = popFirstInt(infile.val);
		size.back().w = popFirstInt(infile.val);
		std::string _justify = popFirstString(infile.val);

		if (_justify == "left") justify.back() = JUSTIFY_LEFT;
		else if (_justify == "center") justify.back() = JUSTIFY_CENTER;
		else if (_justify == "right") justify.back() = JUSTIFY_RIGHT;
	}
	// @ATTR text.text_font|r (integer), g (integer), b (integer), style (string)|Font color and style.
	else if (infile.key == "text_font") {
		Color color;
		color.r = popFirstInt(infile.val);
		color.g = popFirstInt(infile.val);
		color.b = popFirstInt(infile.val);
		textColor.back() = color;
		textFont.back() = popFirstString(infile.val);
	}
	// @ATTR text.text|string|The text to be displayed.
	else if (infile.key == "text") {
		textData.back() = infile.val;
		// remove comma from the end
		textData.back() = textData.back().substr(0, textData.back().length() - 1);
	}
	else {
		infile.error("MenuBook: '%s' is not a valid key.", infile.key.c_str());
	}
}
void GameStateConfigBase::readConfig() {
	//Load the menu configuration from file

	FileParser infile;
	if (infile.open("menus/config.txt")) {
		while (infile.next()) {
			if (parseKeyButtons(infile))
				continue;

			int x1 = popFirstInt(infile.val);
			int y1 = popFirstInt(infile.val);
			int x2 = popFirstInt(infile.val);
			int y2 = popFirstInt(infile.val);

			if (parseKey(infile, x1, y1, x2, y2))
				continue;
			else if (parseStub(infile))
				continue;
			else {
				infile.error("GameStateConfigBase: '%s' is not a valid key.", infile.key.c_str());
			}
		}
		infile.close();
	}
}
Beispiel #13
0
LootManager::LootManager()
	: sfx_loot(0)
	, drop_max(1)
	, drop_radius(1)
	, hero(NULL)
	, tooltip_margin(0)
{
	tip = new WidgetTooltip();

	FileParser infile;
	// load loot animation settings from engine config file
	// @CLASS Loot|Description of engine/loot.txt
	if (infile.open("engine/loot.txt")) {
		while (infile.next()) {
			if (infile.key == "tooltip_margin") {
				// @ATTR tooltip_margin|integer|Vertical offset of the loot tooltip from the loot itself.
				tooltip_margin = toInt(infile.val);
			}
			else if (infile.key == "autopickup_currency") {
				// @ATTR autopickup_currency|boolean|Enable autopickup for currency
				AUTOPICKUP_CURRENCY = toBool(infile.val);
			}
			else if (infile.key == "currency_name") {
				// @ATTR currenct_name|string|Define the name of currency in game
				CURRENCY = msg->get(infile.val);
			}
			else if (infile.key == "vendor_ratio") {
				// @ATTR vendor_ratio|integer|Prices ratio for vendors
				VENDOR_RATIO = toInt(infile.val) / 100.0f;
			}
			else if (infile.key == "sfx_loot") {
				// @ATTR sfx_loot|string|Sound effect for dropping loot.
				sfx_loot =  snd->load(infile.val, "LootManager dropping loot");
			}
			else if (infile.key == "drop_max") {
				// @ATTR drop_max|integer|The maximum number of random item stacks that can drop at once
				drop_max = toInt(infile.val);
				clampFloor(drop_max, 1);
			}
			else if (infile.key == "drop_radius") {
				// @ATTR drop_radius|integer|The distance (in tiles) away from the origin that loot can drop
				drop_radius = toInt(infile.val);
				clampFloor(drop_radius, 1);
			}
			else {
				infile.error("LootManager: '%s' is not a valid key.", infile.key.c_str());
			}
		}
		infile.close();
	}

	// reset current map loot
	loot.clear();

	loadGraphics();

	full_msg = false;

	loadLootTables();
}
Beispiel #14
0
void Map::loadNPC(FileParser &infile) {
	std::string s;
	if (infile.key == "type") {
		// @ATTR npc.type|string|(IGNORED BY ENGINE) The "type" field, as used by Tiled and other mapping tools.
		npcs.back().type = infile.val;
	}
	else if (infile.key == "filename") {
		// @ATTR npc.filename|string|Filename of an NPC definition.
		npcs.back().id = infile.val;
	}
	else if (infile.key == "requires_status") {
		// @ATTR npc.requires_status|list(string)|Status required for NPC load. There can be multiple states, separated by comma
		while ( (s = popFirstString(infile.val)) != "")
			npcs.back().requires_status.push_back(s);
	}
	else if (infile.key == "requires_not_status") {
		// @ATTR npc.requires_not_status|list(string)|Status required to be missing for NPC load. There can be multiple states, separated by comma
		while ( (s = popFirstString(infile.val)) != "")
			npcs.back().requires_not_status.push_back(s);
	}
	else if (infile.key == "location") {
		// @ATTR npc.location|point|Location of NPC
		npcs.back().pos.x = static_cast<float>(popFirstInt(infile.val)) + 0.5f;
		npcs.back().pos.y = static_cast<float>(popFirstInt(infile.val)) + 0.5f;
	}
	else {
		infile.error("Map: '%s' is not a valid key.", infile.key.c_str());
	}
}
Beispiel #15
0
void GameSwitcher::loadFPS() {
	// Load FPS rendering settings
	FileParser infile;
	// @CLASS GameSwitcher: FPS counter|Description of menus/fps.txt
	if (infile.open("menus/fps.txt")) {
		while(infile.next()) {
			// @ATTR position|x (integer), y (integer), align (alignment)|Position of the fps counter.
			if(infile.key == "position") {
				fps_position.x = popFirstInt(infile.val);
				fps_position.y = popFirstInt(infile.val);
				fps_corner = parse_alignment(popFirstString(infile.val));
			}
			// @ATTR color|r (integer), g (integer), b (integer)|Color of the fps counter text.
			else if(infile.key == "color") {
				fps_color = toRGB(infile.val);
			}
			else {
				infile.error("GameSwitcher: '%s' is not a valid key.", infile.key.c_str());
			}
		}
		infile.close();
	}

	// this is a dummy string used to approximate the fps position when aligned to the right
	font->setFont("font_regular");
	fps_position.w = font->calc_width("00 fps");
	fps_position.h = font->getLineHeight();

	// Delete the label object if it exists (we'll recreate this with showFPS())
	if (label_fps) {
		delete label_fps;
		label_fps = NULL;
	}
}
void GameStatePlay::loadTitles() {
	FileParser infile;
	// @CLASS GameStatePlay: Titles|Description of engine/titles.txt
	if (infile.open("engine/titles.txt")) {
		while (infile.next()) {
			if (infile.new_section && infile.section == "title") {
				Title t;
				titles.push_back(t);
			}

			if (titles.empty()) continue;

			// @ATTR title.title|string|The displayed title.
			if (infile.key == "title") titles.back().title = infile.val;
			// @ATTR title.level|int|Requires level.
			else if (infile.key == "level") titles.back().level = toInt(infile.val);
			// @ATTR title.power|power_id|Requires power.
			else if (infile.key == "power") titles.back().power = toInt(infile.val);
			// @ATTR title.requires_status|string|Requires status.
			else if (infile.key == "requires_status") titles.back().requires_status = infile.val;
			// @ATTR title.requires_not_status|string|Requires not status.
			else if (infile.key == "requires_not_status") titles.back().requires_not = infile.val;
			// @ATTR title.primary_stat|["physical", "mental", "offense", "defense", "physoff", "physment", "physdef", "mentoff", "offdef", "mentdef"]|Required primary stat.
			else if (infile.key == "primary_stat") titles.back().primary_stat = infile.val;
			else infile.error("GameStatePlay: '%s' is not a valid key.", infile.key.c_str());
		}
		infile.close();
	}
}
Beispiel #17
0
void LootManager::loadLootTables() {
	std::vector<std::string> filenames = mods->list("loot", false);

	for (unsigned i=0; i<filenames.size(); i++) {
		FileParser infile;
		if (!infile.open(filenames[i]))
			continue;

		std::vector<Event_Component> *ec_list = &loot_tables[filenames[i]];
		Event_Component *ec = NULL;
		bool skip_to_next = false;

		while (infile.next()) {
			if (infile.section == "") {
				if (infile.key == "loot") {
					ec_list->push_back(Event_Component());
					ec = &ec_list->back();
					parseLoot(infile.val, ec, ec_list);
				}
			}
			else if (infile.section == "loot") {
				if (infile.new_section) {
					ec_list->push_back(Event_Component());
					ec = &ec_list->back();
					ec->type = EC_LOOT;
					skip_to_next = false;
				}

				if (skip_to_next || ec == NULL)
					continue;

				if (infile.key == "id") {
					ec->s = infile.val;

					if (ec->s == "currency")
						ec->c = CURRENCY_ID;
					else if (toInt(ec->s, -1) != -1)
						ec->c = toInt(ec->s);
					else {
						skip_to_next = true;
						infile.error("LootManager: Invalid item id for loot.");
					}
				}
				else if (infile.key == "chance") {
					if (infile.val == "fixed")
						ec->z = 0;
					else
						ec->z = toInt(infile.val);
				}
				else if (infile.key == "quantity") {
					ec->a = std::max(popFirstInt(infile.val), 1);
					ec->b = std::max(popFirstInt(infile.val), ec->a);
				}
			}
		}

		infile.close();
	}
}
Beispiel #18
0
void LootManager::loadLootTables() {
	std::vector<std::string> filenames = mods->list("loot", !ModManager::LIST_FULL_PATHS);

	for (unsigned i=0; i<filenames.size(); i++) {
		FileParser infile;
		if (!infile.open(filenames[i], FileParser::MOD_FILE, FileParser::ERROR_NORMAL))
			continue;

		std::vector<EventComponent> *ec_list = &loot_tables[filenames[i]];
		EventComponent *ec = NULL;
		bool skip_to_next = false;

		while (infile.next()) {
			if (infile.section == "") {
				if (infile.key == "loot") {
					ec_list->push_back(EventComponent());
					ec = &ec_list->back();
					parseLoot(infile.val, ec, ec_list);
				}
			}
			else if (infile.section == "loot") {
				if (infile.new_section) {
					ec_list->push_back(EventComponent());
					ec = &ec_list->back();
					ec->type = EventComponent::LOOT;
					skip_to_next = false;
				}

				if (skip_to_next || ec == NULL)
					continue;

				if (infile.key == "id") {
					ec->s = infile.val;

					if (ec->s == "currency")
						ec->c = eset->misc.currency_id;
					else if (Parse::toInt(ec->s, -1) != -1)
						ec->c = Parse::toInt(ec->s);
					else {
						skip_to_next = true;
						infile.error("LootManager: Invalid item id for loot.");
					}
				}
				else if (infile.key == "chance") {
					if (infile.val == "fixed")
						ec->f = 0;
					else
						ec->f = Parse::toFloat(infile.val);
				}
				else if (infile.key == "quantity") {
					ec->a = std::max(Parse::popFirstInt(infile.val), 1);
					ec->b = std::max(Parse::popFirstInt(infile.val), ec->a);
				}
			}
		}

		infile.close();
	}
}
Beispiel #19
0
void MenuPowers::loadUpgrade(FileParser &infile) {
	// @ATTR upgrade.id|int|A power id from powers/powers.txt for this upgrade.
	if (infile.key == "id") {
		int id = popFirstInt(infile.val);
		if (id > 0) {
			skip_section = false;
			power_cell_upgrade.back().id = (id);
		}
		else {
			skip_section = true;
			power_cell_upgrade.pop_back();
			infile.error("MenuPowers: Power index out of bounds 1-%d, skipping power.", INT_MAX);
		}
		return;
	}

	if (skip_section)
		return;

	// @ATTR upgrade.requires_primary|predefined_string, int : Primary stat name, Required value|Upgrade requires this primary stat to be at least the specificed value.
	if (infile.key == "requires_primary") {
		std::string prim_stat = popFirstString(infile.val);
		size_t prim_stat_index = getPrimaryStatIndex(prim_stat);

		if (prim_stat_index != PRIMARY_STATS.size()) {
			power_cell_upgrade.back().requires_primary[prim_stat_index] = toInt(infile.val);
		}
		else {
			infile.error("MenuPowers: '%s' is not a valid primary stat.", prim_stat.c_str());
		}
	}
	// @ATTR upgrade.requires_point|bool|Upgrade requires a power point to unlock.
	else if (infile.key == "requires_point") power_cell_upgrade.back().requires_point = toBool(infile.val);
	// @ATTR upgrade.requires_level|int|Upgrade requires at least this level for the hero.
	else if (infile.key == "requires_level") power_cell_upgrade.back().requires_level = toInt(infile.val);
	// @ATTR upgrade.requires_power|int|Upgrade requires another power id.
	else if (infile.key == "requires_power") power_cell_upgrade.back().requires_power.push_back(toInt(infile.val));

	// @ATTR upgrade.visible_requires_status|repeatable(string)|Hide the upgrade if we don't have this campaign status.
	else if (infile.key == "visible_requires_status") power_cell_upgrade.back().visible_requires_status.push_back(infile.val);
	// @ATTR upgrade.visible_requires_not_status|repeatable(string)|Hide the upgrade if we have this campaign status.
	else if (infile.key == "visible_requires_not_status") power_cell_upgrade.back().visible_requires_not.push_back(infile.val);

	else infile.error("MenuPowers: '%s' is not a valid key.", infile.key.c_str());
}
Beispiel #20
0
MenuTalker::MenuTalker(MenuManager *_menu)
	: Menu()
	, menu(_menu)
	, portrait(NULL)
	, dialog_node(0)
	, event_cursor(0)
	, font_who("font_regular")
	, font_dialog("font_regular")
	, color_normal(font->getColor("menu_normal"))
	, npc(NULL)
	, advanceButton(new WidgetButton("images/menus/buttons/right.png"))
	, closeButton(new WidgetButton("images/menus/buttons/button_x.png")) {

	setBackground("images/menus/dialog_box.png");

	// Load config settings
	FileParser infile;
	// @CLASS MenuTalker|Description of menus/talker.txt
	if(infile.open("menus/talker.txt")) {
		while(infile.next()) {
			if (parseMenuKey(infile.key, infile.val))
				continue;

			// @ATTR close|x (integer), y (integer)|Position of the close button.
			if(infile.key == "close") close_pos = toPoint(infile.val);
			// @ATTR advance|x (integer), y (integer)|Position of the button to advance dialog.
			else if(infile.key == "advance") advance_pos = toPoint(infile.val);
			// @ATTR dialogbox|x (integer), y (integer), w (integer), h (integer)|Position and dimensions of the text box graphics.
			else if (infile.key == "dialogbox") dialog_pos = toRect(infile.val);
			// @ATTR dialogtext|x (integer), y (integer), w (integer), h (integer)|Rectangle where the dialog text is placed.
			else if (infile.key == "dialogtext") text_pos = toRect(infile.val);
			// @ATTR text_offset|x (integer), y (integer)|Margins for the left/right and top/bottom of the dialog text.
			else if (infile.key == "text_offset") text_offset = toPoint(infile.val);
			// @ATTR portrait_he|x (integer), y (integer), w (integer), h (integer)|Position and dimensions of the NPC portrait graphics.
			else if (infile.key == "portrait_he") portrait_he = toRect(infile.val);
			// @ATTR portrait_you|x (integer), y (integer), w (integer), h (integer)|Position and dimensions of the player's portrait graphics.
			else if (infile.key == "portrait_you") portrait_you = toRect(infile.val);
			// @ATTR font_who|string|Font style to use for the name of the currently talking person.
			else if (infile.key == "font_who") font_who = infile.val;
			// @ATTR font_dialog|string|Font style to use for the dialog text.
			else if (infile.key == "font_dialog") font_dialog = infile.val;

			else infile.error("MenuTalker: '%s' is not a valid key.", infile.key.c_str());
		}
		infile.close();
	}

	label_name = new WidgetLabel();
	textbox = new WidgetScrollBox(text_pos.w, text_pos.h-(text_offset.y*2));

	tablist.add(advanceButton);
	tablist.add(closeButton);
	tablist.add(textbox);

	align();
	alignElements();
}
MenuDevConsole::MenuDevConsole() : Menu() {

    button_close = new WidgetButton("images/menus/buttons/button_x.png");
    tablist.add(button_close);

    input_box = new WidgetInput("images/menus/input_console.png");
    tablist.add(input_box);

    button_confirm = new WidgetButton();
    button_confirm->label = msg->get("Execute");
    tablist.add(button_confirm);

    // Load config settings
    FileParser infile;
    // @CLASS MenuDevConsole|Description of menus/devconsole.txt
    if(infile.open("menus/devconsole.txt")) {
        while(infile.next()) {
            if (parseMenuKey(infile.key, infile.val))
                continue;

            // @ATTR close|x (integer), y (integer)|Position of the close button.
            if(infile.key == "close") {
                Point pos = toPoint(infile.val);
                button_close->setBasePos(pos.x, pos.y);
            }
            // @ATTR label_title|label|Position of the "Developer Console" label.
            else if(infile.key == "label_title") title = eatLabelInfo(infile.val);
            // @ATTR confirm|x (integer), y (integer)|Position of the "Execute" button.
            else if(infile.key == "confirm") {
                Point pos = toPoint(infile.val);
                button_confirm->setBasePos(pos.x, pos.y);
            }
            // @ATTR input|x (integer), y (integer)|Position of the command entry widget.
            else if(infile.key == "input") {
                Point pos = toPoint(infile.val);
                input_box->setBasePos(pos.x, pos.y);
            }
            // @ATTR history|x (integer), y (integer), w (integer), h (integer)|Position and dimensions of the command history.
            else if(infile.key == "history") history_area = toRect(infile.val);

            else infile.error("MenuDevConsole: '%s' is not a valid key.", infile.key.c_str());
        }
        infile.close();
    }

    log_history = new WidgetLog(history_area.w, history_area.h);
    log_history->setBasePos(history_area.x, history_area.y);
    tablist.add(log_history->getWidget());

    setBackground("images/menus/dev_console.png");

    color_echo = font->getColor("widget_disabled");
    color_error = font->getColor("menu_penalty");

    align();
    input_box->inFocus = true;
}
Beispiel #22
0
MenuLog::MenuLog() {
	visible = false;

	closeButton = new WidgetButton("images/menus/buttons/button_x.png");

	// Load config settings
	FileParser infile;
	// @CLASS MenuLog|Description of menus/log.txt
	if(infile.open("menus/log.txt")) {
		while(infile.next()) {
			if (parseMenuKey(infile.key, infile.val))
				continue;

			// @ATTR label_title|label|Position of the "Log" text.
			if(infile.key == "label_title") {
				title = eatLabelInfo(infile.val);
			}
			// @ATTR close|point|Position of the close button.
			else if(infile.key == "close") {
				Point pos = toPoint(infile.val);
				closeButton->setBasePos(pos.x, pos.y);
			}
			// @ATTR tab_area|rectangle|The position of the row of tabs, followed by the dimensions of the log text area.
			else if(infile.key == "tab_area") {
				tab_area = toRect(infile.val);
			}
			else {
				infile.error("MenuLog: '%s' is not a valid key.", infile.key.c_str());
			}
		}
		infile.close();
	}

	// Initialize the tab control.
	tabControl = new WidgetTabControl();
	tablist.add(tabControl);

	// Store the amount of displayed log messages on each log, and the maximum.
	tablist_log.resize(LOG_TYPE_COUNT);
	for (unsigned i=0; i<LOG_TYPE_COUNT; i++) {
		log[i] = new WidgetLog(tab_area.w,tab_area.h);
		log[i]->setBasePos(tab_area.x, tab_area.y + tabControl->getTabHeight());

		tablist_log[i].add(log[i]->getWidget());
		tablist_log[i].setPrevTabList(&tablist);
		tablist_log[i].lock();
	}

	// Define the header.
	tabControl->setTabTitle(LOG_TYPE_MESSAGES, msg->get("Notes"));
	tabControl->setTabTitle(LOG_TYPE_QUESTS, msg->get("Quests"));

	setBackground("images/menus/log.png");

	align();
}
CursorManager::CursorManager()
	: cursor_normal(NULL)
	, cursor_interact(NULL)
	, cursor_talk(NULL)
	, cursor_attack(NULL)
	, cursor_current(NULL)
	, offset_current(NULL) {
	Image *graphics;
	FileParser infile;
	// @CLASS CursorManager|Description of engine/mouse_cursor.txt
	if (infile.open("engine/mouse_cursor.txt", true, "")) {
		while (infile.next()) {
			if (infile.key == "normal") {
				// @ATTR normal|string|Filename of an image for the normal cursor.
				graphics = render_device->loadImage(popFirstString(infile.val));
				if (graphics) {
					cursor_normal = graphics->createSprite();
					graphics->unref();
				}
				offset_normal = toPoint(infile.val);
			}
			else if (infile.key == "interact") {
				// @ATTR interact|string|Filename of an image for the object interaction cursor.
				graphics = render_device->loadImage(popFirstString(infile.val));
				if (graphics) {
					cursor_interact = graphics->createSprite();
					graphics->unref();
				}
				offset_interact = toPoint(infile.val);
			}
			else if (infile.key == "talk") {
				// @ATTR talk|string|Filename of an image for the NPC interaction cursor.
				graphics = render_device->loadImage(popFirstString(infile.val));
				if (graphics) {
					cursor_talk = graphics->createSprite();
					graphics->unref();
				}
				offset_talk = toPoint(infile.val);
			}
			else if (infile.key == "attack") {
				// @ATTR attack|string|Filename of an image for the cursor when attacking enemies.
				graphics = render_device->loadImage(popFirstString(infile.val));
				if (graphics) {
					cursor_attack = graphics->createSprite();
					graphics->unref();
				}
				offset_attack = toPoint(infile.val);
			}
			else {
				infile.error("CursorManager: '%s' is not a valid key.", infile.key.c_str());
			}
		}
		infile.close();
	}
}
Beispiel #24
0
/**
 * Load avatar sprite layer definitions into vector.
 */
void Avatar::loadLayerDefinitions() {
	layer_def = vector<vector<unsigned> >(8, vector<unsigned>());
	layer_reference_order = vector<string>();

	FileParser infile;
	// @CLASS Avatar: Hero layers|Description of engine/hero_layers.txt
	if (infile.open("engine/hero_layers.txt")) {
		while(infile.next()) {
			if (infile.key == "layer") {
				// @ATTR layer|direction (integer), string, ...]|Defines the hero avatar sprite layer
				unsigned dir = popFirstInt(infile.val);
				if (dir>7) {
					infile.error("Avatar: Hero layer direction must be in range [0,7]");
					SDL_Quit();
					exit(1);
				}
				string layer = popFirstString(infile.val);
				while (layer != "") {
					// check if already in layer_reference:
					unsigned ref_pos;
					for (ref_pos = 0; ref_pos < layer_reference_order.size(); ++ref_pos)
						if (layer == layer_reference_order[ref_pos])
							break;
					if (ref_pos == layer_reference_order.size())
						layer_reference_order.push_back(layer);
					layer_def[dir].push_back(ref_pos);

					layer = popFirstString(infile.val);
				}
			}
			else {
				infile.error("Avatar: '%s' is not a valid key.", infile.key.c_str());
			}
		}
		infile.close();
	}

	// There are the positions of the items relative to layer_reference_order
	// so if layer_reference_order=main,body,head,off
	// and we got a layer=3,off,body,head,main
	// then the layer_def[3] looks like (3,1,2,0)
}
Beispiel #25
0
void StatBlock::loadHeroStats() {
	// Redefine numbers from config file if present
	FileParser infile;
	// @CLASS StatBlock: Hero stats|Description of engine/stats.txt
	if (infile.open("engine/stats.txt")) {
		while (infile.next()) {
			int value = toInt(infile.val);

			bool valid = loadCoreStat(&infile);

			if (infile.key == "max_points_per_stat") {
				// @ATTR max_points_per_stat|integer|Maximum points for each primary stat.
				max_points_per_stat = value;
			}
			else if (infile.key == "sfx_step") {
				// @ATTR sfx_step|string|An id for a set of step sound effects. See items/step_sounds.txt.
				sfx_step = infile.val;
			}
			else if (infile.key == "stat_points_per_level") {
				// @ATTR stat_points_per_level|integer|The amount of stat points awarded each level.
				stat_points_per_level = value;
			}
			else if (infile.key == "power_points_per_level") {
				// @ATTR power_points_per_level|integer|The amount of power points awarded each level.
				power_points_per_level = value;
			}
			else if (!valid) {
				infile.error("StatBlock: '%s' is not a valid key.", infile.key.c_str());
			}
		}
		infile.close();
	}

	if (max_points_per_stat == 0) max_points_per_stat = max_spendable_stat_points / 4 + 1;
	statsLoaded = true;

	// load the XP table
	// @CLASS StatBlock: XP table|Description of engine/xp_table.txt
	if (infile.open("engine/xp_table.txt")) {
		while(infile.next()) {
			unsigned key = toInt(infile.key);
			if (key > 0) {
				// @ATTR $LEVEL|integer|The amount of XP required for this level.
				if (key > xp_table.size())
					xp_table.resize(key);
				xp_table[key - 1] = toInt(infile.val);
			}
		}
		infile.close();
	}
	max_spendable_stat_points = xp_table.size() * stat_points_per_level;
}
Beispiel #26
0
void GameSwitcher::loadBackgroundList() {
	background_list.clear();
	freeBackground();

	FileParser infile;
	// @CLASS GameSwitcher: Background images|Description of engine/menu_backgrounds.txt
	if (infile.open("engine/menu_backgrounds.txt", true, "")) {
		while (infile.next()) {
			// @ATTR background|string|Filename of a background image to be added to the pool of random menu backgrounds
			if (infile.key == "background") background_list.push_back(infile.val);
			else infile.error("GameSwitcher: '%s' is not a valid key.", infile.key.c_str());
		}
		infile.close();
	}
}
Beispiel #27
0
void Map::loadHeader(FileParser &infile) {
	if (infile.key == "title") {
		// @ATTR title|string|Title of map
		this->title = msg->get(infile.val);
	}
	else if (infile.key == "width") {
		// @ATTR width|int|Width of map
		this->w = static_cast<unsigned short>(std::max(toInt(infile.val), 1));
	}
	else if (infile.key == "height") {
		// @ATTR height|int|Height of map
		this->h = static_cast<unsigned short>(std::max(toInt(infile.val), 1));
	}
	else if (infile.key == "tileset") {
		// @ATTR tileset|filename|Filename of a tileset definition to use for map
		this->tileset = infile.val;
	}
	else if (infile.key == "music") {
		// @ATTR music|filename|Filename of background music to use for map
		music_filename = infile.val;
	}
	else if (infile.key == "hero_pos") {
		// @ATTR hero_pos|point|The player will spawn in this location if no point was previously given.
		hero_pos.x = static_cast<float>(popFirstInt(infile.val)) + 0.5f;
		hero_pos.y = static_cast<float>(popFirstInt(infile.val)) + 0.5f;
		hero_pos_enabled = true;
	}
	else if (infile.key == "parallax_layers") {
		// @ATTR parallax_layers|filename|Filename of a parallax layers definition.
		parallax_filename = infile.val;
	}
	else if (infile.key == "background_color") {
		// @ATTR background_color|color, int : Color, alpha|Background color for the map.
		background_color = toRGBA(infile.val);
	}
	else if (infile.key == "tilewidth") {
		// @ATTR tilewidth|int|Inherited from Tiled map file. Unused by engine.
	}
	else if (infile.key == "tileheight") {
		// @ATTR tileheight|int|Inherited from Tiled map file. Unused by engine.
	}
	else if (infile.key == "orientation") {
		// this is only used by Tiled when importing Flare maps
	}
	else {
		infile.error("Map: '%s' is not a valid key.", infile.key.c_str());
	}
}
Beispiel #28
0
MenuPowers::MenuPowers(StatBlock *_stats, MenuActionBar *_action_bar)
	: stats(_stats)
	, action_bar(_action_bar)
	, skip_section(false)
	, powers_unlock(NULL)
	, overlay_disabled(NULL)
	, points_left(0)
	, default_background("")
	, tab_control(NULL)
	, tree_loaded(false)
	, prev_powers_list_size(0)
	, newPowerNotification(false)
{

	closeButton = new WidgetButton("images/menus/buttons/button_x.png");

	// Read powers data from config file
	FileParser infile;
	// @CLASS MenuPowers: Menu layout|Description of menus/powers.txt
	if (infile.open("menus/powers.txt")) {
		while (infile.next()) {
			if (parseMenuKey(infile.key, infile.val))
				continue;

			// @ATTR label_title|label|Position of the "Powers" text.
			if (infile.key == "label_title") title = eatLabelInfo(infile.val);
			// @ATTR unspent_points|label|Position of the text that displays the amount of unused power points.
			else if (infile.key == "unspent_points") unspent_points = eatLabelInfo(infile.val);
			// @ATTR close|point|Position of the close button.
			else if (infile.key == "close") close_pos = toPoint(infile.val);
			// @ATTR tab_area|rectangle|Position and dimensions of the tree pages.
			else if (infile.key == "tab_area") tab_area = toRect(infile.val);

			else infile.error("MenuPowers: '%s' is not a valid key.", infile.key.c_str());
		}
		infile.close();
	}

	loadGraphics();

	menu_powers = this;

	color_bonus = font->getColor("menu_bonus");
	color_penalty = font->getColor("menu_penalty");
	color_flavor = font->getColor("item_flavor");

	align();
}
void ItemManager::parseBonus(BonusData& bdata, FileParser& infile) {
	std::string bonus_str = Parse::popFirstString(infile.val);
	bdata.value = Parse::popFirstInt(infile.val);

	if (bonus_str == "speed") {
		bdata.is_speed = true;
		return;
	}
	else if (bonus_str == "attack_speed") {
		bdata.is_attack_speed = true;
		return;
	}

	for (int i=0; i<Stats::COUNT; ++i) {
		if (bonus_str == Stats::KEY[i]) {
			bdata.stat_index = static_cast<Stats::STAT>(i);
			return;
		}
	}

	for (size_t i = 0; i < eset->damage_types.list.size(); ++i) {
		if (bonus_str == eset->damage_types.list[i].min) {
			bdata.damage_index_min = static_cast<int>(i);
			return;
		}
		else if (bonus_str == eset->damage_types.list[i].max) {
			bdata.damage_index_max = static_cast<int>(i);
			return;
		}
	}

	for (unsigned i=0; i<eset->elements.list.size(); ++i) {
		if (bonus_str == eset->elements.list[i].id + "_resist") {
			bdata.resist_index = i;
			return;
		}
	}

	for (size_t i = 0; i < eset->primary_stats.list.size(); ++i) {
		if (bonus_str == eset->primary_stats.list[i].id) {
			bdata.base_index = static_cast<int>(i);
			return;
		}
	}

	infile.error("ItemManager: Unknown bonus type '%s'.", bonus_str.c_str());
}
MenuNPCActions::MenuNPCActions()
	: Menu()
	, npc(NULL)
	, is_selected(false)
	, is_empty(true)
	, first_dialog_node(-1)
	, current_action(-1)
	, action_menu(NULL)
	, vendor_label(msg->get("Trade"))
	, cancel_label(msg->get("Cancel"))
	, dialog_selected(false)
	, vendor_selected(false)
	, cancel_selected(false)
	, selected_dialog_node(-1) {
	// Load config settings
	FileParser infile;
	// @CLASS MenuNPCActions|Description of menus/npc.txt
	if (infile.open("menus/npc.txt")) {
		while(infile.next()) {
			if (parseMenuKey(infile.key, infile.val))
				continue;

			// @ATTR background_color|r (integer), g (integer), b (integer), a (integer)|Color and alpha of the menu's background.
			if(infile.key == "background_color") background_color = toRGBA(infile.val);
			// @ATTR topic_normal_color|r (integer), g (integer), b (integer)|The normal color of a generic topic text.
			else if(infile.key == "topic_normal_color") topic_normal_color = toRGB(infile.val);
			// @ATTR topic_hilight_color|r (integer), g (integer), b (integer)|The color of generic topic text when it's hovered over or selected.
			else if(infile.key == "topic_hilight_color") topic_hilight_color = toRGB(infile.val);
			// @ATTR vendor_normal_color|r (integer), g (integer), b (integer)|The normal color of the vendor option text.
			else if(infile.key == "vendor_normal_color") vendor_normal_color = toRGB(infile.val);
			// @ATTR vendor_hilight_color|r (integer), g (integer), b (integer)|The color of vendor option text when it's hovered over or selected.
			else if(infile.key == "vendor_hilight_color") vendor_hilight_color = toRGB(infile.val);
			// @ATTR cancel_normal_color|r (integer), g (integer), b (integer)|The normal color of the option to close the menu.
			else if(infile.key == "cancel_normal_color") cancel_normal_color = toRGB(infile.val);
			// @ATTR cancel_hilight_color|r (integer), g (integer), b (integer)|The color of the option to close the menu when it's hovered over or selected.
			else if(infile.key == "cancel_hilight_color") cancel_hilight_color = toRGB(infile.val);

			else infile.error("MenuNPCActions: '%s' is not a valid key.", infile.key.c_str());
		}
		infile.close();
	}

	// save the x/y pos coordinates here, since we call align() during each update() call
	base_pos.x = window_area.x;
	base_pos.y = window_area.y;
}