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(); } }
/** * 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; }
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; } } } } } }
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; }
/** * 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; }
/** * 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; } }
/** * 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; }
/** * 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; }
/** * 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(); }
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")); } } }
/** * 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(); }
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(); } }
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(); } }
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(); } }