Пример #1
0
void MenuPowers::setUnlockedPowers() {
	std::vector<int> power_ids;
	bool unlocked_cleared = false;

	// only clear/repopulate power_cell_unlocked if the size of the hero's powers_list has changed
	if (prev_powers_list_size != stats->powers_list.size() || power_cell_unlocked.empty()) {
		prev_powers_list_size = stats->powers_list.size();
		power_cell_unlocked.clear();
		unlocked_cleared = true;
	}

	for (size_t i=0; i<power_cell.size(); ++i) {
		if (std::find(stats->powers_list.begin(), stats->powers_list.end(), power_cell[i].id) != stats->powers_list.end()) {
			if (!unlocked_cleared)
				continue;

			// base power
			if (std::find(power_ids.begin(), power_ids.end(), power_cell[i].id) == power_ids.end()) {
				power_ids.push_back(power_cell_base[i].id);
				power_cell_unlocked.push_back(power_cell_base[i]);
			}
			if (power_cell[i].id == power_cell_base[i].id)
				continue;

			//upgrades
			for (size_t j=0; j<power_cell[i].upgrades.size(); ++j) {
				if (std::find(power_ids.begin(), power_ids.end(), power_cell[i].upgrades[j]) == power_ids.end()) {
					int id = getCellByPowerIndex(power_cell[i].upgrades[j], power_cell_upgrade);
					if (id != -1) {
						power_ids.push_back(power_cell[i].upgrades[j]);
						power_cell_unlocked.push_back(power_cell_upgrade[id]);

						if (power_cell[i].id == power_cell[i].upgrades[j])
							break;
					}
					else {
						break;
					}
				}
			}
		}
		else {
			// power is unlocked, but not in the player's powers_list
			int pci = getCellByPowerIndex(power_cell[i].id, power_cell_all);
			if (checkUnlocked(pci)) {
				stats->powers_list.push_back(power_cell[i].id);
			}
		}
	}

	// the hero's powers_list may have grown, so we need to re-check unlocked powers
	if (prev_powers_list_size != stats->powers_list.size()) {
		setUnlockedPowers();
	}
}
Пример #2
0
/**
 * Show mouseover descriptions of disciplines and powers
 */
TooltipData MenuPowers::checkTooltip(const Point& mouse) {

	TooltipData tip;

	for (size_t i=0; i<power_cell.size(); i++) {

		if (tab_control && (tab_control->getActiveTab() != power_cell[i].tab)) continue;

		int cell_index = getCellByPowerIndex(power_cell[i].id, power_cell_all);
		if (!checkCellVisible(cell_index)) continue;

		if (slots[i] && isWithinRect(slots[i]->pos, mouse)) {
			bool base_unlocked = checkUnlocked(cell_index) || std::find(stats->powers_list.begin(), stats->powers_list.end(), power_cell[i].id) != stats->powers_list.end();

			createTooltip(&tip, static_cast<int>(i), power_cell, !base_unlocked);
			if (!power_cell[i].upgrades.empty()) {
				int next_level = getNextLevelCell(static_cast<int>(i));
				if (next_level != -1) {
					tip.addText("\n" + msg->get("Next Level:"));
					createTooltip(&tip, next_level, power_cell_upgrade, base_unlocked);
				}
			}

			return tip;
		}
	}

	return tip;
}
Пример #3
0
void MenuPowers::setUnlockedPowers() {
	std::vector<int> power_ids;
	power_cell_unlocked.clear();

	for (size_t i=0; i<power_cell.size(); ++i) {
		if (std::find(stats->powers_list.begin(), stats->powers_list.end(), power_cell[i].id) != stats->powers_list.end()) {
			// base power
			if (std::find(power_ids.begin(), power_ids.end(), power_cell[i].id) == power_ids.end()) {
				power_ids.push_back(power_cell_base[i].id);
				power_cell_unlocked.push_back(power_cell_base[i]);
			}
			if (power_cell[i].id == power_cell_base[i].id)
				continue;

			//upgrades
			for (size_t j=0; j<power_cell[i].upgrades.size(); ++j) {
				if (std::find(power_ids.begin(), power_ids.end(), power_cell[i].upgrades[j]) == power_ids.end()) {
					int id = getCellByPowerIndex(power_cell[i].upgrades[j], power_cell_upgrade);
					if (id != -1) {
						power_ids.push_back(power_cell[i].upgrades[j]);
						power_cell_unlocked.push_back(power_cell_upgrade[id]);

						if (power_cell[i].id == power_cell[i].upgrades[j])
							break;
					}
					else {
						break;
					}
				}
			}
		}
	}
}
Пример #4
0
bool MenuPowers::checkUpgrade(int pci) {
	int id = getCellByPowerIndex(power_cell[pci].id, power_cell_all);
	if (!checkUnlocked(id))
		return false;

	int next_index = getNextLevelCell(pci);
	if (next_index == -1)
		return false;
	if (power_cell_upgrade[next_index].requires_point && points_left < 1)
		return false;

	int id_upgrade = getCellByPowerIndex(power_cell_upgrade[next_index].id, power_cell_all);
	if (!checkUnlock(id_upgrade))
		return false;

	return true;
}
Пример #5
0
/**
 * Return true if required stats for power usage are met. Else return false.
 */
bool MenuPowers::meetsUsageStats(int power_index) {
	// Find cell with our power
	int id = getCellByPowerIndex(power_index, power_cell);

	// If we didn't find power in power_menu, than it has no stats requirements
	if (id == -1) return true;

	for (size_t i = 0; i < PRIMARY_STATS.size(); ++i) {
		if (stats->get_primary(i) < power_cell[id].requires_primary[i])
			return false;
	}

	return true;
}
Пример #6
0
/**
 * Find cell in upgrades with next upgrade for current power_cell
 */
int MenuPowers::getNextLevelCell(int pci) {
	if (power_cell[pci].upgrades.empty()) {
		return -1;
	}

	std::vector<int>::iterator level_it;
	level_it = std::find(power_cell[pci].upgrades.begin(),
					power_cell[pci].upgrades.end(),
					power_cell[pci].id);

	if (level_it == power_cell[pci].upgrades.end()) {
		// current power is base power, take first upgrade
		int index = power_cell[pci].upgrades[0];
		return getCellByPowerIndex(index, power_cell_upgrade);
	}
	// current power is an upgrade, take next upgrade if avaliable
	size_t index = std::distance(power_cell[pci].upgrades.begin(), level_it);
	if (power_cell[pci].upgrades.size() > index + 1) {
		return getCellByPowerIndex(*(++level_it), power_cell_upgrade);
	}
	else {
		return -1;
	}
}
Пример #7
0
/**
 * Click-to-drag a power (to the action bar)
 */
int MenuPowers::click(const Point& mouse) {
	int active_tab = (tab_control) ? tab_control->getActiveTab() : 0;

	for (size_t i=0; i<power_cell.size(); i++) {
		if (slots[i] && isWithinRect(slots[i]->pos, mouse) && (power_cell[i].tab == active_tab)) {
			if (TOUCHSCREEN) {
				if (!slots[i]->in_focus) {
					slots[i]->in_focus = true;
					if (!tabs.empty()) {
						tablist_pow[active_tab].setCurrent(slots[i]);
					}
					else {
						tablist.setCurrent(slots[i]);
					}
					return 0;
				}
			}

			int cell_index = getCellByPowerIndex(power_cell[i].id, power_cell_all);
			if (checkUnlock(cell_index) && points_left > 0 && power_cell[i].requires_point) {
				// unlock power
				stats->powers_list.push_back(power_cell[i].id);
				stats->check_title = true;
				setUnlockedPowers();
				action_bar->addPower(power_cell[i].id, 0);
				return 0;
			}
			else if (checkUnlocked(cell_index) && !powers->powers[power_cell[i].id].passive) {
				// pick up and drag power
				slots[i]->defocus();
				if (!tabs.empty()) {
					tablist_pow[active_tab].setCurrent(NULL);
				}
				else {
					tablist.setCurrent(NULL);
				}
				return power_cell[i].id;
			}
			else
				return 0;
		}
	}

	// nothing selected, defocus everything
	defocusTabLists();

	return 0;
}
Пример #8
0
/**
 * Return true if required stats for power usage are met. Else return false.
 */
bool MenuPowers::meetsUsageStats(int power_index) {
	// Find cell with our power
	int id = getCellByPowerIndex(power_index, power_cell);

	// If we didn't find power in power_menu, than it has no stats requirements
	if (id == -1) return true;

	return stats->physoff() >= power_cell[id].requires_physoff
		   && stats->physdef() >= power_cell[id].requires_physdef
		   && stats->mentoff() >= power_cell[id].requires_mentoff
		   && stats->mentdef() >= power_cell[id].requires_mentdef
		   && stats->get_defense() >= power_cell[id].requires_defense
		   && stats->get_offense() >= power_cell[id].requires_offense
		   && stats->get_mental() >= power_cell[id].requires_mental
		   && stats->get_physical() >= power_cell[id].requires_physical;
}
Пример #9
0
/**
 * Apply power upgrades on savegame loading
 */
void MenuPowers::applyPowerUpgrades() {
	for (size_t i=0; i<power_cell.size(); i++) {
		if (!power_cell[i].upgrades.empty()) {
			std::vector<int>::iterator it;
			for (it = power_cell[i].upgrades.end(); it != power_cell[i].upgrades.begin(); ) {
				--it;
				std::vector<int>::iterator upgrade_it;
				upgrade_it = std::find(stats->powers_list.begin(), stats->powers_list.end(), *it);
				if (upgrade_it != stats->powers_list.end()) {
					int upgrade_index = getCellByPowerIndex((*upgrade_it), power_cell_upgrade);
					if (upgrade_index != -1)
						replaceCellWithUpgrade(static_cast<int>(i), upgrade_index);
					break;
				}
			}
		}
	}
	setUnlockedPowers();
}
Пример #10
0
void MenuPowers::createTooltip(TooltipData* tip, int slot_num, const std::vector<Power_Menu_Cell>& power_cells, bool show_unlock_prompt) {
	if (power_cells[slot_num].upgrade_level > 0)
		tip->addText(powers->powers[power_cells[slot_num].id].name + " (" + msg->get("Level %d", power_cells[slot_num].upgrade_level) + ")");
	else
		tip->addText(powers->powers[power_cells[slot_num].id].name);

	if (powers->powers[power_cells[slot_num].id].passive) tip->addText(msg->get("Passive"));
	tip->addColoredText(substituteVarsInString(powers->powers[power_cells[slot_num].id].description, pc), color_flavor);

	// add mana cost
	if (powers->powers[power_cells[slot_num].id].requires_mp > 0) {
		tip->addText(msg->get("Costs %d MP", powers->powers[power_cells[slot_num].id].requires_mp));
	}
	// add health cost
	if (powers->powers[power_cells[slot_num].id].requires_hp > 0) {
		tip->addText(msg->get("Costs %d HP", powers->powers[power_cells[slot_num].id].requires_hp));
	}
	// add cooldown time
	if (powers->powers[power_cells[slot_num].id].cooldown > 0) {
		std::stringstream ss;
		ss << msg->get("Cooldown:") << " " << getDurationString(powers->powers[power_cells[slot_num].id].cooldown);
		tip->addText(ss.str());
	}

	const Power &pwr = powers->powers[power_cells[slot_num].id];
	for (size_t i=0; i<pwr.post_effects.size(); ++i) {
		std::stringstream ss;
		EffectDef* effect_ptr = powers->getEffectDef(pwr.post_effects[i].id);

		// base stats
		if (effect_ptr == NULL) {
			if (pwr.post_effects[i].magnitude > 0) {
				ss << "+";
			}

			ss << pwr.post_effects[i].magnitude;
			bool found_key = false;

			for (size_t j=0; j<STAT_COUNT; ++j) {
				if (pwr.post_effects[i].id == STAT_KEY[j]) {
					if (STAT_PERCENT[j])
						ss << "%";

					ss << " " << STAT_NAME[j];

					found_key = true;
					break;
				}
			}

			if (!found_key) {
				for (size_t j=0; j<ELEMENTS.size(); ++j) {
					if (pwr.post_effects[i].id == ELEMENTS[j].id + "_resist") {
						ss << "% " << msg->get("%s Resistance", ELEMENTS[j].name.c_str());
						found_key = true;
						break;
					}
				}
			}

			if (!found_key) {
				for (size_t j=0; j<PRIMARY_STATS.size(); ++j) {
					if (pwr.post_effects[i].id == PRIMARY_STATS[j].id) {
						ss << " " << PRIMARY_STATS[j].name;
						found_key = true;
						break;
					}
				}
			}

			if (!found_key) {
				for (size_t j=0; j<DAMAGE_TYPES.size(); ++j) {
					if (pwr.post_effects[i].id == DAMAGE_TYPES[j].min) {
						ss << " " << DAMAGE_TYPES[j].name_min;
						found_key = true;
						break;
					}
					else if (pwr.post_effects[i].id == DAMAGE_TYPES[j].max) {
						ss << " " << DAMAGE_TYPES[j].name_max;
						found_key = true;
						break;
					}
				}
			}
		}
		else {
			if (effect_ptr->type == "damage") {
				ss << pwr.post_effects[i].magnitude << " " << msg->get("Damage per second");
			}
			else if (effect_ptr->type == "damage_percent") {
				ss << pwr.post_effects[i].magnitude << "% " << msg->get("Damage per second");
			}
			else if (effect_ptr->type == "hpot") {
				ss << pwr.post_effects[i].magnitude << " " << msg->get("HP per second");
			}
			else if (effect_ptr->type == "hpot_percent") {
				ss << pwr.post_effects[i].magnitude << "% " << msg->get("HP per second");
			}
			else if (effect_ptr->type == "mpot") {
				ss << pwr.post_effects[i].magnitude << " " << msg->get("MP per second");
			}
			else if (effect_ptr->type == "mpot_percent") {
				ss << pwr.post_effects[i].magnitude << "% " << msg->get("MP per second");
			}
			else if (effect_ptr->type == "speed") {
				if (pwr.post_effects[i].magnitude == 0)
					ss << msg->get("Immobilize");
				else
					ss << msg->get("%d%% Speed", pwr.post_effects[i].magnitude);
			}
			else if (effect_ptr->type == "attack_speed") {
				ss << msg->get("%d%% Attack Speed", pwr.post_effects[i].magnitude);
			}
			else if (effect_ptr->type == "immunity") {
				ss << msg->get("Immunity");
			}
			else if (effect_ptr->type == "immunity_damage") {
				ss << msg->get("Immunity to damage over time");
			}
			else if (effect_ptr->type == "immunity_slow") {
				ss << msg->get("Immunity to slow");
			}
			else if (effect_ptr->type == "immunity_stun") {
				ss << msg->get("Immunity to stun");
			}
			else if (effect_ptr->type == "immunity_hp_steal") {
				ss << msg->get("Immunity to HP steal");
			}
			else if (effect_ptr->type == "immunity_mp_steal") {
				ss << msg->get("Immunity to MP steal");
			}
			else if (effect_ptr->type == "immunity_knockback") {
				ss << msg->get("Immunity to knockback");
			}
			else if (effect_ptr->type == "immunity_damage_reflect") {
				ss << msg->get("Immunity to damage reflection");
			}
			else if (effect_ptr->type == "stun") {
				ss << msg->get("Stun");
			}
			else if (effect_ptr->type == "revive") {
				ss << msg->get("Automatic revive on death");
			}
			else if (effect_ptr->type == "convert") {
				ss << msg->get("Convert");
			}
			else if (effect_ptr->type == "fear") {
				ss << msg->get("Fear");
			}
			else if (effect_ptr->type == "death_sentence") {
				ss << msg->get("Lifespan");
			}
			else if (effect_ptr->type == "shield") {
				if (pwr.base_damage == DAMAGE_TYPES.size())
					continue;

				if (pwr.mod_damage_mode == STAT_MODIFIER_MODE_MULTIPLY) {
					int magnitude = stats->getDamageMax(pwr.base_damage) * pwr.mod_damage_value_min / 100;
					ss << magnitude;
				}
				else if (pwr.mod_damage_mode == STAT_MODIFIER_MODE_ADD) {
					int magnitude = stats->getDamageMax(pwr.base_damage) + pwr.mod_damage_value_min;
					ss << magnitude;
				}
				else if (pwr.mod_damage_mode == STAT_MODIFIER_MODE_ABSOLUTE) {
					if (pwr.mod_damage_value_max == 0 || pwr.mod_damage_value_min == pwr.mod_damage_value_max)
						ss << pwr.mod_damage_value_min;
					else
						ss << pwr.mod_damage_value_min << "-" << pwr.mod_damage_value_max;
				}
				else {
					ss << stats->getDamageMax(pwr.base_damage);
				}

				ss << " " << msg->get("Magical Shield");
			}
			else if (effect_ptr->type == "heal") {
				if (pwr.base_damage == DAMAGE_TYPES.size())
					continue;

				int mag_min = stats->getDamageMin(pwr.base_damage);
				int mag_max = stats->getDamageMax(pwr.base_damage);

				if (pwr.mod_damage_mode == STAT_MODIFIER_MODE_MULTIPLY) {
					mag_min = mag_min * pwr.mod_damage_value_min / 100;
					mag_max = mag_max * pwr.mod_damage_value_min / 100;
					ss << mag_min << "-" << mag_max;
				}
				else if (pwr.mod_damage_mode == STAT_MODIFIER_MODE_ADD) {
					mag_min = mag_min + pwr.mod_damage_value_min;
					mag_max = mag_max + pwr.mod_damage_value_min;
					ss << mag_min << "-" << mag_max;
				}
				else if (pwr.mod_damage_mode == STAT_MODIFIER_MODE_ABSOLUTE) {
					if (pwr.mod_damage_value_max == 0 || pwr.mod_damage_value_min == pwr.mod_damage_value_max)
						ss << pwr.mod_damage_value_min;
					else
						ss << pwr.mod_damage_value_min << "-" << pwr.mod_damage_value_max;
				}
				else {
					ss << mag_min << "-" << mag_max;
				}

				ss << " " << msg->get("Healing");
			}
			else if (effect_ptr->type == "knockback") {
				ss << pwr.post_effects[i].magnitude << " " << msg->get("Knockback");
			}
			else if (pwr.post_effects[i].magnitude == 0) {
				// nothing
			}
		}

		if (!ss.str().empty()) {
			if (pwr.post_effects[i].duration > 0) {
				if (effect_ptr && effect_ptr->type == "death_sentence") {
					ss << ": " << getDurationString(pwr.post_effects[i].duration);
				}
				else {
					ss << " (" << getDurationString(pwr.post_effects[i].duration) << ")";
				}

				if (pwr.post_effects[i].chance != 100)
					ss << " ";
			}
			if (pwr.post_effects[i].chance != 100) {
				ss << "(" << msg->get("%d%% chance", pwr.post_effects[i].chance) << ")";
			}

			tip->addColoredText(ss.str(), color_bonus);
		}
	}

	if (pwr.use_hazard || pwr.type == POWTYPE_REPEATER) {
		std::stringstream ss;

		// modifier_damage
		if (pwr.mod_damage_mode > -1) {
			if (pwr.mod_damage_mode == STAT_MODIFIER_MODE_ADD && pwr.mod_damage_value_min > 0)
				ss << "+";

			if (pwr.mod_damage_value_max == 0 || pwr.mod_damage_value_min == pwr.mod_damage_value_max) {
				ss << pwr.mod_damage_value_min;
			}
			else {
				ss << pwr.mod_damage_value_min << "-" << pwr.mod_damage_value_max;
			}

			if (pwr.mod_damage_mode == STAT_MODIFIER_MODE_MULTIPLY) {
				ss << "%";
			}
			ss << " ";

			if (pwr.base_damage != DAMAGE_TYPES.size()) {
				ss << DAMAGE_TYPES[pwr.base_damage].name;
			}

			if (pwr.count > 1 && pwr.type != POWTYPE_REPEATER)
				ss << " (x" << pwr.count << ")";

			if (!ss.str().empty())
				tip->addColoredText(ss.str(), color_bonus);
		}

		// modifier_accuracy
		if (pwr.mod_accuracy_mode > -1) {
			ss.str("");

			if (pwr.mod_accuracy_mode == STAT_MODIFIER_MODE_ADD && pwr.mod_accuracy_value > 0)
				ss << "+";

			ss << pwr.mod_accuracy_value;

			if (pwr.mod_accuracy_mode == STAT_MODIFIER_MODE_MULTIPLY) {
				ss << "%";
			}
			ss << " ";

			ss << msg->get("Base Accuracy");

			if (!ss.str().empty())
				tip->addColoredText(ss.str(), color_bonus);
		}

		// modifier_critical
		if (pwr.mod_crit_mode > -1) {
			ss.str("");

			if (pwr.mod_crit_mode == STAT_MODIFIER_MODE_ADD && pwr.mod_crit_value > 0)
				ss << "+";

			ss << pwr.mod_crit_value;

			if (pwr.mod_crit_mode == STAT_MODIFIER_MODE_MULTIPLY) {
				ss << "%";
			}
			ss << " ";

			ss << msg->get("Base Critical Chance");

			if (!ss.str().empty())
				tip->addColoredText(ss.str(), color_bonus);
		}

		if (pwr.trait_armor_penetration) {
			ss.str("");
			ss << msg->get("Ignores Absorbtion");
			tip->addColoredText(ss.str(), color_bonus);
		}
		if (pwr.trait_avoidance_ignore) {
			ss.str("");
			ss << msg->get("Ignores Avoidance");
			tip->addColoredText(ss.str(), color_bonus);
		}
		if (pwr.trait_crits_impaired > 0) {
			ss.str("");
			ss << msg->get("%d%% Chance to crit slowed targets", pwr.trait_crits_impaired);
			tip->addColoredText(ss.str(), color_bonus);
		}
		if (pwr.trait_elemental > -1) {
			ss.str("");
			ss << msg->get("%s Elemental Damage", ELEMENTS[pwr.trait_elemental].name.c_str());
			tip->addColoredText(ss.str(), color_bonus);
		}
	}

	std::set<std::string>::iterator it;
	for (it = powers->powers[power_cells[slot_num].id].requires_flags.begin(); it != powers->powers[power_cells[slot_num].id].requires_flags.end(); ++it) {
		for (size_t i=0; i<EQUIP_FLAGS.size(); ++i) {
			if ((*it) == EQUIP_FLAGS[i].id) {
				tip->addText(msg->get("Requires a %s", msg->get(EQUIP_FLAGS[i].name)));
			}
		}
	}

	// add requirement
	for (size_t i = 0; i < PRIMARY_STATS.size(); ++i) {
		if (power_cells[slot_num].requires_primary[i] > 0) {
			if (stats->get_primary(i) < power_cells[slot_num].requires_primary[i])
				tip->addColoredText(msg->get("Requires %s %d", power_cells[slot_num].requires_primary[i], PRIMARY_STATS[i].name.c_str()), color_penalty);
			else
				tip->addText(msg->get("Requires %s %d", power_cells[slot_num].requires_primary[i], PRIMARY_STATS[i].name.c_str()));
		}
	}

	// Draw required Level Tooltip
	if ((power_cells[slot_num].requires_level > 0) && stats->level < power_cells[slot_num].requires_level) {
		tip->addColoredText(msg->get("Requires Level %d", power_cells[slot_num].requires_level), color_penalty);
	}
	else if ((power_cells[slot_num].requires_level > 0) && stats->level >= power_cells[slot_num].requires_level) {
		tip->addText(msg->get("Requires Level %d", power_cells[slot_num].requires_level));
	}

	for (size_t j=0; j < power_cells[slot_num].requires_power.size(); ++j) {
		if (power_cells[slot_num].requires_power[j] == 0) continue;

		int req_index = getCellByPowerIndex(power_cells[slot_num].requires_power[j], power_cell_all);
		if (req_index == -1) continue;

		std::string req_power_name;
		if (power_cell_all[req_index].upgrade_level > 0)
			req_power_name = powers->powers[power_cell_all[req_index].id].name + " (" + msg->get("Level %d", power_cell_all[req_index].upgrade_level) + ")";
		else
			req_power_name = powers->powers[power_cell_all[req_index].id].name;


		// Required Power Tooltip
		int req_cell_index = getCellByPowerIndex(power_cells[slot_num].requires_power[j], power_cell_all);
		if (!checkUnlocked(req_cell_index)) {
			tip->addColoredText(msg->get("Requires Power: %s", req_power_name), color_penalty);
		}
		else {
			tip->addText(msg->get("Requires Power: %s", req_power_name));
		}

	}

	// Draw unlock power Tooltip
	if (power_cells[slot_num].requires_point && !(std::find(stats->powers_list.begin(), stats->powers_list.end(), power_cells[slot_num].id) != stats->powers_list.end())) {
		int unlock_id = getCellByPowerIndex(power_cells[slot_num].id, power_cell_all);
		if (show_unlock_prompt && points_left > 0 && checkUnlock(unlock_id)) {
			tip->addColoredText(msg->get("Click to Unlock (uses 1 Skill Point)"), color_bonus);
		}
		else {
			if (power_cells[slot_num].requires_point && points_left < 1)
				tip->addColoredText(msg->get("Requires 1 Skill Point"), color_penalty);
			else
				tip->addText(msg->get("Requires 1 Skill Point"));
		}
	}
}
Пример #11
0
/**
 * Loads a given power tree and sets up the menu accordingly
 *
 * @param filename Path to the file that will be loaded
 */
void MenuPowers::loadPowerTree(const std::string &filename) {
	// only load the power tree once per instance
	if (tree_loaded) return;

	// First, parse the power tree file

	FileParser infile;
	// @CLASS MenuPowers: Power tree layout|Description of powers/trees/
	if (infile.open(filename)) {
		while (infile.next()) {
			if (infile.new_section) {
				// for sections that are stored in collections, add a new object here
				if (infile.section == "power") {
					slots.push_back(NULL);
					upgradeButtons.push_back(NULL);
					power_cell.push_back(Power_Menu_Cell());
				}
				else if (infile.section == "upgrade")
					power_cell_upgrade.push_back(Power_Menu_Cell());
				else if (infile.section == "tab")
					tabs.push_back(Power_Menu_Tab());
			}

			if (infile.section == "") {
				// @ATTR background|filename|Filename of the default background image
				if (infile.key == "background") default_background = infile.val;
			}
			else if (infile.section == "tab")
				loadTab(infile);
			else if (infile.section == "power")
				loadPower(infile);
			else if (infile.section == "upgrade")
				loadUpgrade(infile);
		}
		infile.close();
	}

	// save a copy of the base level powers, as they get overwritten during upgrades
	power_cell_base = power_cell;

	// store the appropriate level for all upgrades
	for (size_t i=0; i<power_cell_upgrade.size(); ++i) {
		for (size_t j=0; j<power_cell_base.size(); j++) {
			std::vector<int>::iterator it = std::find(power_cell_base[j].upgrades.begin(), power_cell_base[j].upgrades.end(), power_cell_upgrade[i].id);
			if (it != power_cell_base[j].upgrades.end()) {
				power_cell_upgrade[i].upgrade_level = static_cast<int>(std::distance(power_cell_base[j].upgrades.begin(), it) + 2);
				break;
			}
		}
	}

	// combine base and upgrade powers into a single list
	for (size_t i=0; i<power_cell_base.size(); ++i) {
		power_cell_all.push_back(power_cell_base[i]);
	}
	for (size_t i=0; i<power_cell_upgrade.size(); ++i) {
		power_cell_all.push_back(power_cell_upgrade[i]);
	}

	// save cell indexes for required powers
	for (size_t i=0; i<power_cell_all.size(); ++i) {
		for (size_t j=0; j<power_cell_all[i].requires_power.size(); ++j) {
			int cell_index = getCellByPowerIndex(power_cell_all[i].requires_power[j], power_cell_all);
			power_cell_all[i].requires_power_cell.push_back(cell_index);
		}
	}

	// load any specified graphics into the tree_surf vector
	Image *graphics;
	if (tabs.empty() && default_background != "") {
		graphics = render_device->loadImage(default_background);
		if (graphics) {
			tree_surf.push_back(graphics->createSprite());
			graphics->unref();
		}
	}
	else {
		for (size_t i=0; i<tabs.size(); ++i) {
			if (tabs[i].background == "")
				tabs[i].background = default_background;

			if (tabs[i].background == "") {
				tree_surf.push_back(NULL);
				continue;
			}

			graphics = render_device->loadImage(tabs[i].background);
			if (graphics) {
				tree_surf.push_back(graphics->createSprite());
				graphics->unref();
			}
			else {
				tree_surf.push_back(NULL);
			}
		}
	}

	// If we have more than one tab, create tab_control
	if (!tabs.empty()) {
		tab_control = new WidgetTabControl();

		if (tab_control) {
			// Initialize the tab control.
			tab_control->setMainArea(window_area.x+tab_area.x, window_area.y+tab_area.y, tab_area.w, tab_area.h);

			// Define the header.
			for (size_t i=0; i<tabs.size(); i++)
				tab_control->setTabTitle(static_cast<unsigned>(i), msg->get(tabs[i].title));
			tab_control->updateHeader();

			tablist.add(tab_control);
		}

		tablist_pow.resize(tabs.size());
	}

	// create power slots
	for (size_t i=0; i<slots.size(); i++) {
		if (static_cast<size_t>(power_cell[i].id) < powers->powers.size()) {
			slots[i] = new WidgetSlot(powers->powers[power_cell[i].id].icon);
			slots[i]->setBasePos(power_cell[i].pos.x, power_cell[i].pos.y);

			if (!tablist_pow.empty()) {
				tablist_pow[power_cell[i].tab].add(slots[i]);
				tablist_pow[power_cell[i].tab].setPrevTabList(&tablist);
				tablist_pow[power_cell[i].tab].lock();
			}
			else {
				tablist.add(slots[i]);
			}

			if (upgradeButtons[i] != NULL) {
				upgradeButtons[i]->setBasePos(power_cell[i].pos.x + ICON_SIZE, power_cell[i].pos.y);
			}
		}
	}

	applyPowerUpgrades();

	tree_loaded = true;

	align();
}
Пример #12
0
void MenuPowers::logic() {
	setUnlockedPowers();

	for (size_t i=0; i<power_cell_unlocked.size(); i++) {
		if (static_cast<size_t>(power_cell_unlocked[i].id) < powers->powers.size() && powers->powers[power_cell_unlocked[i].id].passive) {
			bool unlocked_power = std::find(stats->powers_list.begin(), stats->powers_list.end(), power_cell_unlocked[i].id) != stats->powers_list.end();
			std::vector<int>::iterator it = std::find(stats->powers_passive.begin(), stats->powers_passive.end(), power_cell_unlocked[i].id);

			int cell_index = getCellByPowerIndex(power_cell_unlocked[i].id, power_cell_all);
			bool is_current_upgrade_max = (getCellByPowerIndex(power_cell_unlocked[i].id, power_cell) != -1);

			if (it != stats->powers_passive.end()) {
				if (!is_current_upgrade_max || (!checkRequirements(cell_index) && power_cell_unlocked[i].passive_on)) {
					// passive power is activated, but does not meet requirements, so remove it
					stats->powers_passive.erase(it);
					stats->effects.removeEffectPassive(power_cell_unlocked[i].id);
					power_cell[i].passive_on = false;
					stats->refresh_stats = true;
				}
			}
			else if (is_current_upgrade_max && ((checkRequirements(cell_index) && !power_cell_unlocked[i].requires_point) || unlocked_power) && !power_cell_unlocked[i].passive_on) {
				// passive power has not been activated, so activate it here
				stats->powers_passive.push_back(power_cell_unlocked[i].id);
				power_cell_unlocked[i].passive_on = true;
				// for passives without special triggers, we need to trigger them here
				if (stats->effects.triggered_others)
					powers->activateSinglePassive(stats, power_cell_unlocked[i].id);
			}
		}
	}

	for (size_t i=0; i<power_cell.size(); i++) {
		//upgrade buttons logic
		if (upgradeButtons[i] != NULL) {
			upgradeButtons[i]->enabled = false;
			// enable button only if current level is unlocked and next level can be unlocked
			if (checkUpgrade(static_cast<int>(i))) {
				upgradeButtons[i]->enabled = true;
			}
			if ((!tab_control || power_cell[i].tab == tab_control->getActiveTab()) && upgradeButtons[i]->checkClick()) {
				upgradePower(static_cast<int>(i));
			}

			// automatically apply upgrades when requires_point = false
			if (upgradeButtons[i]->enabled) {
				int next_index;
				int prev_index = -1;
				while ((next_index = getNextLevelCell(static_cast<int>(i))) != -1) {
					if (prev_index == next_index) {
						// this should never happen, but if it ever does, it would be an infinite loop
						break;
					}

					if (!power_cell_upgrade[next_index].requires_point && checkUpgrade(static_cast<int>(i))) {
						upgradePower(static_cast<int>(i), true);
					}
					else {
						break;
					}

					prev_index = next_index;
				}
			}
		}
	}

	points_left = (stats->level * stats->power_points_per_level) - getPointsUsed();
	if (points_left > 0) {
		newPowerNotification = true;
	}

	if (!visible) return;

	tablist.logic();
	if (!tabs.empty()) {
		for (size_t i=0; i<tabs.size(); i++) {
			if (tab_control && tab_control->getActiveTab() == static_cast<int>(i)) {
				tablist.setNextTabList(&tablist_pow[i]);
			}
			tablist_pow[i].logic();
		}
	}

	if (closeButton->checkClick()) {
		visible = false;
		snd->play(sfx_close);
	}

	if (tab_control) {
		// make shure keyboard navigation leads us to correct tab
		for (size_t i=0; i<slots.size(); i++) {
			if (power_cell[i].tab == tab_control->getActiveTab())
				continue;

			if (slots[i] && slots[i]->in_focus)
				slots[i]->defocus();
		}

		tab_control->logic();
	}
}
Пример #13
0
void MenuPowers::renderPowers(int tab_num) {

	Rect disabled_src;
	disabled_src.x = disabled_src.y = 0;
	disabled_src.w = disabled_src.h = ICON_SIZE;

	for (size_t i=0; i<power_cell.size(); i++) {
		bool power_in_vector = false;

		// Continue if slot is not filled with data
		if (power_cell[i].tab != tab_num) continue;

		int cell_index = getCellByPowerIndex(power_cell[i].id, power_cell_all);
		if (!checkCellVisible(cell_index)) continue;

		if (std::find(stats->powers_list.begin(), stats->powers_list.end(), power_cell[i].id) != stats->powers_list.end()) power_in_vector = true;

		if (slots[i])
			slots[i]->render();

		// highlighting
		if (power_in_vector || checkUnlocked(cell_index)) {
			Rect src_unlock;

			src_unlock.x = 0;
			src_unlock.y = 0;
			src_unlock.w = ICON_SIZE;
			src_unlock.h = ICON_SIZE;

			int selected_slot = -1;
			if (isTabListSelected()) {
				selected_slot = getSelectedCellIndex();
			}

			for (size_t j=0; j<power_cell.size(); j++) {
				if (selected_slot == static_cast<int>(j))
					continue;

				if (power_cell[j].id == power_cell[i].id && powers_unlock && slots[j]) {
					powers_unlock->setClip(src_unlock);
					powers_unlock->setDest(slots[j]->pos);
					render_device->render(powers_unlock);
				}
			}
		}
		else {
			if (overlay_disabled && slots[i]) {
				overlay_disabled->setClip(disabled_src);
				overlay_disabled->setDest(slots[i]->pos);
				render_device->render(overlay_disabled);
			}
		}

		if (slots[i])
			slots[i]->renderSelection();

		// upgrade buttons
		if (upgradeButtons[i])
			upgradeButtons[i]->render();
	}
}
Пример #14
0
void MenuPowers::logic() {
	for (size_t i=0; i<power_cell_unlocked.size(); i++) {
		if (static_cast<size_t>(power_cell_unlocked[i].id) < powers->powers.size() && powers->powers[power_cell_unlocked[i].id].passive) {
			bool unlocked_power = std::find(stats->powers_list.begin(), stats->powers_list.end(), power_cell_unlocked[i].id) != stats->powers_list.end();
			std::vector<int>::iterator it = std::find(stats->powers_passive.begin(), stats->powers_passive.end(), power_cell_unlocked[i].id);

			int cell_index = getCellByPowerIndex(power_cell_unlocked[i].id, power_cell_all);
			if (it != stats->powers_passive.end()) {
				if (!checkRequirements(cell_index) && power_cell_unlocked[i].passive_on) {
					stats->powers_passive.erase(it);
					stats->effects.removeEffectPassive(power_cell_unlocked[i].id);
					power_cell[i].passive_on = false;
					stats->refresh_stats = true;
				}
			}
			else if (((checkRequirements(cell_index) && !power_cell_unlocked[i].requires_point) || unlocked_power) && !power_cell_unlocked[i].passive_on) {
				stats->powers_passive.push_back(power_cell_unlocked[i].id);
				power_cell_unlocked[i].passive_on = true;
				// for passives without special triggers, we need to trigger them here
				if (stats->effects.triggered_others)
					powers->activateSinglePassive(stats, power_cell_unlocked[i].id);
			}
		}
	}

	for (size_t i=0; i<power_cell.size(); i++) {
		//upgrade buttons logic
		if (upgradeButtons[i] != NULL) {
			upgradeButtons[i]->enabled = false;
			// enable button only if current level is unlocked and next level can be unlocked
			if (checkUpgrade(static_cast<int>(i))) {
				upgradeButtons[i]->enabled = true;
			}
			if ((!tab_control || power_cell[i].tab == tab_control->getActiveTab()) && upgradeButtons[i]->checkClick()) {
				upgradePower(static_cast<int>(i));
			}
		}
	}

	points_left = (stats->level * stats->power_points_per_level) - getPointsUsed();
	if (points_left > 0) {
		newPowerNotification = true;
	}

	if (!visible) return;

	tablist.logic();
	if (!tabs.empty()) {
		for (size_t i=0; i<tabs.size(); i++) {
			if (tab_control->getActiveTab() == static_cast<int>(i)) {
				tablist.setNextTabList(&tablist_pow[i]);
			}
			tablist_pow[i].logic();
		}
	}

	if (closeButton->checkClick()) {
		visible = false;
		snd->play(sfx_close);
	}

	if (tab_control) {
		// make shure keyboard navigation leads us to correct tab
		for (size_t i=0; i<slots.size(); i++) {
			if (power_cell[i].tab == tab_control->getActiveTab())
				continue;

			if (slots[i] && slots[i]->in_focus)
				slots[i]->defocus();
		}

		tab_control->logic();
	}
}