void player::power_bionics() { std::vector <bionic *> passive; std::vector <bionic *> active; for (std::vector<bionic>::iterator it = my_bionics.begin(); it != my_bionics.end(); ++it) { if (!bionics[it->id]->activated) { passive.push_back(&*it); } else { active.push_back(&*it); } } // maximal number of rows in both columns const int bionic_count = std::max(passive.size(), active.size()); int TITLE_HEIGHT = 2; int DESCRIPTION_HEIGHT = 5; // Main window /** Total required height is: * top frame line: + 1 * height of title window: + TITLE_HEIGHT * line after the title: + 1 * line with active/passive bionic captions: + 1 * height of the biggest list of active/passive bionics: + bionic_count * line before bionic description: + 1 * height of description window: + DESCRIPTION_HEIGHT * bottom frame line: + 1 * TOTAL: TITLE_HEIGHT + bionic_count + DESCRIPTION_HEIGHT + 5 */ int HEIGHT = std::min(TERMY, std::max(FULL_SCREEN_HEIGHT, TITLE_HEIGHT + bionic_count + DESCRIPTION_HEIGHT + 5)); int WIDTH = FULL_SCREEN_WIDTH + (TERMX - FULL_SCREEN_WIDTH) / 2; int START_X = (TERMX - WIDTH) / 2; int START_Y = (TERMY - HEIGHT) / 2; WINDOW *wBio = newwin(HEIGHT, WIDTH, START_Y, START_X); // Description window @ the bottom of the bio window int DESCRIPTION_START_Y = START_Y + HEIGHT - DESCRIPTION_HEIGHT - 1; int DESCRIPTION_LINE_Y = DESCRIPTION_START_Y - START_Y - 1; WINDOW *w_description = newwin(DESCRIPTION_HEIGHT, WIDTH - 2, DESCRIPTION_START_Y, START_X + 1); // Title window int TITLE_START_Y = START_Y + 1; int HEADER_LINE_Y = TITLE_HEIGHT + 1; // + lines with text in titlebar, local WINDOW *w_title = newwin(TITLE_HEIGHT, WIDTH - 2, TITLE_START_Y, START_X + 1); int scroll_position = 0; int second_column = 32 + (TERMX - FULL_SCREEN_WIDTH) / 4; // X-coordinate of the list of active bionics input_context ctxt("BIONICS"); ctxt.register_updown(); ctxt.register_action("ANY_INPUT"); ctxt.register_action("TOOGLE_EXAMINE"); ctxt.register_action("REASSIGN"); ctxt.register_action("REMOVE"); ctxt.register_action("HELP_KEYBINDINGS"); bool redraw = true; std::string menu_mode = "activating"; while(true) { // offset for display: bionic with index i is drawn at y=list_start_y+i // drawing the bionics starts with bionic[scroll_position] const int list_start_y = HEADER_LINE_Y + 2 - scroll_position; int max_scroll_position = HEADER_LINE_Y + 2 + bionic_count - ((menu_mode == "examining") ? DESCRIPTION_LINE_Y : (HEIGHT - 1)); if(redraw) { redraw = false; werase(wBio); draw_border(wBio); // Draw line under title mvwhline(wBio, HEADER_LINE_Y, 1, LINE_OXOX, WIDTH - 2); // Draw symbols to connect additional lines to border mvwputch(wBio, HEADER_LINE_Y, 0, BORDER_COLOR, LINE_XXXO); // |- mvwputch(wBio, HEADER_LINE_Y, WIDTH - 1, BORDER_COLOR, LINE_XOXX); // -| // Captions mvwprintz(wBio, HEADER_LINE_Y + 1, 2, c_ltblue, _("Passive:")); mvwprintz(wBio, HEADER_LINE_Y + 1, second_column, c_ltblue, _("Active:")); draw_exam_window(wBio, DESCRIPTION_LINE_Y, menu_mode == "examining"); nc_color type; if (passive.empty()) { mvwprintz(wBio, list_start_y, 2, c_ltgray, _("None")); } else { for (size_t i = scroll_position; i < passive.size(); i++) { if (list_start_y + static_cast<int>(i) == (menu_mode == "examining" ? DESCRIPTION_LINE_Y : HEIGHT - 1)) { break; } if (bionics[passive[i]->id]->power_source) { type = c_ltcyan; } else { type = c_cyan; } mvwprintz(wBio, list_start_y + i, 2, type, "%c %s", passive[i]->invlet, bionics[passive[i]->id]->name.c_str()); } } if (active.empty()) { mvwprintz(wBio, list_start_y, second_column, c_ltgray, _("None")); } else { for (size_t i = scroll_position; i < active.size(); i++) { if (list_start_y + static_cast<int>(i) == (menu_mode == "examining" ? DESCRIPTION_LINE_Y : HEIGHT - 1)) { break; } if (active[i]->powered && !bionics[active[i]->id]->power_source) { type = c_red; } else if (bionics[active[i]->id]->power_source && !active[i]->powered) { type = c_ltcyan; } else if (bionics[active[i]->id]->power_source && active[i]->powered) { type = c_ltgreen; } else { type = c_ltred; } mvwputch(wBio, list_start_y + i, second_column, type, active[i]->invlet); mvwprintz(wBio, list_start_y + i, second_column + 2, type, (active[i]->powered ? _("%s - ON") : _("%s - %d PU / %d turns")), bionics[active[i]->id]->name.c_str(), bionics[active[i]->id]->power_cost, bionics[active[i]->id]->charge_time); } } // Scrollbar if(scroll_position > 0) { mvwputch(wBio, HEADER_LINE_Y + 2, 0, c_ltgreen, '^'); } if(scroll_position < max_scroll_position && max_scroll_position > 0) { mvwputch(wBio, (menu_mode == "examining" ? DESCRIPTION_LINE_Y : HEIGHT - 1) - 1, 0, c_ltgreen, 'v'); } } wrefresh(wBio); show_bionics_titlebar(w_title, this, menu_mode); const std::string action = ctxt.handle_input(); const long ch = ctxt.get_raw_input().get_first_input(); bionic *tmp = NULL; if (menu_mode == "reassigning") { menu_mode = "activating"; tmp = bionic_by_invlet(ch); if(tmp == 0) { // Selected an non-existing bionic (or escape, or ...) continue; } redraw = true; const char newch = popup_getkey(_("%s; enter new letter."), bionics[tmp->id]->name.c_str()); wrefresh(wBio); if(newch == ch || newch == ' ' || newch == KEY_ESCAPE) { continue; } bionic *otmp = bionic_by_invlet(newch); // if there is already a bionic with the new invlet, the invlet // is considered valid. if(otmp == 0 && inv_chars.find(newch) == std::string::npos) { // TODO separate list of letters for bionics popup(_("%c is not a valid inventory letter."), newch); continue; } if(otmp != 0) { std::swap(tmp->invlet, otmp->invlet); } else { tmp->invlet = newch; } // TODO: show a message like when reassigning a key to an item? } else if (action == "DOWN") { if(scroll_position < max_scroll_position) { scroll_position++; redraw = true; } } else if (action == "UP") { if(scroll_position > 0) { scroll_position--; redraw = true; } } else if (action == "REASSIGN") { menu_mode = "reassigning"; } else if (action == "TOOGLE_EXAMINE") { // switches between activation and examination menu_mode = menu_mode == "activating" ? "examining" : "activating"; werase(w_description); draw_exam_window(wBio, DESCRIPTION_LINE_Y, false); redraw = true; } else if (action == "REMOVE") { menu_mode = "removing"; redraw = true; } else if (action == "HELP_KEYBINDINGS") { redraw = true; } else { tmp = bionic_by_invlet(ch); if(tmp == 0) { // entered a key that is not mapped to any bionic, // -> leave screen break; } const std::string &bio_id = tmp->id; const bionic_data &bio_data = *bionics[bio_id]; if (menu_mode == "removing") { uninstall_bionic(bio_id); break; } if (menu_mode == "activating") { if (bio_data.activated) { itype_id weapon_id = weapon.type->id; int b = tmp - &my_bionics[0]; if (tmp->powered) { tmp->powered = false; add_msg(m_neutral, _("%s powered off."), bio_data.name.c_str()); deactivate_bionic(b); } else if (power_level >= bio_data.power_cost || (weapon_id == "bio_claws_weapon" && bio_id == "bio_claws_weapon") || (weapon_id == "bio_blade_weapon" && bio_id == "bio_blade_weapon")) { // this will clear the bionics menu for targeting purposes werase(wBio); wrefresh(wBio); delwin(w_title); delwin(w_description); delwin(wBio); g->draw(); activate_bionic(b); if (bio_id == "bio_cqb") { pick_style(); } } else { popup( _( "You don't have enough power to activate the %s." ), bio_data.name.c_str() ); redraw = true; continue; } // Action done, leave screen break; } else { popup(_("\ You can not activate %s! To read a description of \ %s, press '!', then '%c'."), bio_data.name.c_str(), bio_data.name.c_str(), tmp->invlet); redraw = true; } } if (menu_mode == "examining") { // Describing bionics, not activating them! draw_exam_window(wBio, DESCRIPTION_LINE_Y, true); // Clear the lines first werase(w_description); fold_and_print(w_description, 0, 0, WIDTH - 2, c_ltblue, bio_data.description); wrefresh(w_description); } } } //if we activated a bionic, already killed the windows if(!(menu_mode == "activating")) { werase(wBio); wrefresh(wBio); delwin(w_title); delwin(w_description); delwin(wBio); } }
void player::power_bionics() { int HEIGHT = TERMY; int WIDTH = FULL_SCREEN_WIDTH; int START_X = (TERMX - WIDTH) / 2; int START_Y = (TERMY - HEIGHT) / 2; WINDOW *wBio = newwin(HEIGHT, WIDTH, START_Y, START_X); int DESCRIPTION_WIDTH = WIDTH - 2; // Same width as bionics window minus 2 for the borders int DESCRIPTION_HEIGHT = 5; int DESCRIPTION_START_X = getbegx(wBio) + 1; // +1 to avoid border int DESCRIPTION_START_Y = getmaxy(wBio) - DESCRIPTION_HEIGHT - 1; // At the bottom of the bio window, -1 to avoid border WINDOW *w_description = newwin(DESCRIPTION_HEIGHT, DESCRIPTION_WIDTH, DESCRIPTION_START_Y, DESCRIPTION_START_X); int TITLE_WIDTH = DESCRIPTION_WIDTH; int TITLE_HEIGHT = 2; int TITLE_START_X = DESCRIPTION_START_X; int TITLE_START_Y = START_Y + 1; WINDOW *w_title = newwin(TITLE_HEIGHT, TITLE_WIDTH, TITLE_START_Y, TITLE_START_X); int scroll_position = 0; bool redraw = true; bool reassigning = false; bool activating = true; // examination mode if activating = false and reassigning = false std::vector <bionic *> passive; std::vector <bionic *> active; for (size_t i = 0; i < my_bionics.size(); i++) { if (!bionics[my_bionics[i].id]->activated) { passive.push_back(&my_bionics[i]); } else { active.push_back(&my_bionics[i]); } } int HEADER_LINE_Y = TITLE_START_Y + TITLE_HEIGHT; // + lines with text in titlebar int DESCRIPTION_LINE_Y = DESCRIPTION_START_Y - 1; // maximal number of rows in both columns const int bionic_count = std::max(passive.size(), active.size()); // number of rows with bionics shown (+1 for displaying "Passive:"/"Active:") const int bionic_display_height = DESCRIPTION_LINE_Y - HEADER_LINE_Y - 2; int max_scroll_position = bionic_count - bionic_display_height; int second_column = 32; while(true) { // offset for display: bionic with index i is drawn at y=list_start_y+i // the header ("Passive:"/"Active:") is drawn at y=HEADER_LINE_Y+1 // drawing the bionics starts with bionic[scroll_position] const int list_start_y = HEADER_LINE_Y + 2 - scroll_position; if(redraw) { redraw = false; werase(wBio); draw_border(wBio); draw_exam_window(wBio, DESCRIPTION_LINE_Y, (!reassigning && !activating)); for (int i = 1; i < WIDTH - 1; i++) { mvwputch(wBio, HEADER_LINE_Y, i, BORDER_COLOR, LINE_OXOX); // Draw line under title } // Draw symbols to connect additional lines to border mvwputch(wBio, HEADER_LINE_Y, 0, BORDER_COLOR, LINE_XXXO); // |- mvwputch(wBio, HEADER_LINE_Y, WIDTH - 1, BORDER_COLOR, LINE_XOXX); // -| nc_color type; mvwprintz(wBio, HEADER_LINE_Y + 1, 2, c_ltblue, _("Passive:")); if (passive.size() <= 0) { mvwprintz(wBio, list_start_y, 2, c_ltgray, _("None")); } else { for (size_t i = scroll_position; i < passive.size(); i++) { if (list_start_y + i == ((!activating && !reassigning) ? DESCRIPTION_LINE_Y : HEIGHT - 1)) { break; } if (bionics[passive[i]->id]->power_source) { type = c_ltcyan; } else { type = c_cyan; } mvwputch(wBio, list_start_y + i, 2, type, passive[i]->invlet); mvwprintz(wBio, list_start_y + i, 4, type, bionics[passive[i]->id]->name.c_str()); } } mvwprintz(wBio, HEADER_LINE_Y + 1, second_column, c_ltblue, _("Active:")); if (active.size() <= 0) { mvwprintz(wBio, list_start_y, second_column, c_ltgray, _("None")); } else { for (size_t i = scroll_position; i < active.size(); i++) { if (list_start_y + i == ((!activating && !reassigning) ? DESCRIPTION_LINE_Y : HEIGHT - 1)) { break; } if (active[i]->powered && !bionics[active[i]->id]->power_source) { type = c_red; } else if (bionics[active[i]->id]->power_source && !active[i]->powered) { type = c_ltcyan; } else if (bionics[active[i]->id]->power_source && active[i]->powered) { type = c_ltgreen; } else { type = c_ltred; } mvwputch(wBio, list_start_y + i, second_column, type, active[i]->invlet); mvwprintz(wBio, list_start_y + i, second_column + 2, type, (active[i]->powered ? _("%s - ON") : _("%s - %d PU / %d trns")), bionics[active[i]->id]->name.c_str(), bionics[active[i]->id]->power_cost, bionics[active[i]->id]->charge_time); } } if(scroll_position > 0) { mvwputch(wBio, HEADER_LINE_Y + 2, 0, c_ltgreen, '^'); } if(scroll_position < max_scroll_position && max_scroll_position > 0) { mvwputch(wBio, (!activating && !reassigning) ? ((HEADER_LINE_Y + 2) + bionic_display_height - 1) : (HEIGHT - 2), 0, c_ltgreen, 'v'); } } wrefresh(wBio); show_bionics_titlebar(w_title, this, activating, reassigning); long ch = getch(); bionic *tmp = NULL; if (reassigning) { reassigning = false; tmp = bionic_by_invlet(ch); if(tmp == 0) { // Selected an non-existing bionic (or escape, or ...) continue; } redraw = true; const char newch = popup_getkey(_("%s; enter new letter."), bionics[tmp->id]->name.c_str()); wrefresh(wBio); if(newch == ch || newch == ' ' || newch == KEY_ESCAPE) { continue; } bionic *otmp = bionic_by_invlet(newch); // if there is already a bionic with the new invlet, the invlet // is considered valid. if(otmp == 0 && inv_chars.find(newch) == std::string::npos) { // TODO separate list of letters for bionics popup(_("%c is not a valid inventory letter."), newch); continue; } if(otmp != 0) { std::swap(tmp->invlet, otmp->invlet); } else { tmp->invlet = newch; } // TODO: show a message like when reassigning a key to an item? } else if (ch == KEY_DOWN) { if(scroll_position < max_scroll_position) { scroll_position++; redraw = true; } } else if (ch == KEY_UP) { if(scroll_position > 0) { scroll_position--; redraw = true; } } else if (ch == '=') { reassigning = true; } else if (ch == '!') { activating = !activating; if (!reassigning && !activating) { // examination mode werase(w_description); } draw_exam_window(wBio, DESCRIPTION_LINE_Y, (!reassigning && !activating)); redraw = true; } else { tmp = bionic_by_invlet(ch); if(tmp == 0) { // entered a key that is not mapped to any bionic, // -> leave screen break; } const std::string &bio_id = tmp->id; const bionic_data &bio_data = *bionics[bio_id]; if (activating) { if (bio_data.activated) { itype_id weapon_id = weapon.type->id; if (tmp->powered) { tmp->powered = false; g->add_msg(_("%s powered off."), bio_data.name.c_str()); } else if (power_level >= bio_data.power_cost || (weapon_id == "bio_claws_weapon" && bio_id == "bio_claws_weapon")) { int b = tmp - &my_bionics[0]; activate_bionic(b); } // Action done, leave screen break; } else { popup(_("\ You can not activate %s! To read a description of \ %s, press '!', then '%c'."), bio_data.name.c_str(), bio_data.name.c_str(), tmp->invlet); redraw = true; } } else { // Describing bionics, not activating them! draw_exam_window(wBio, DESCRIPTION_LINE_Y, true); // Clear the lines first werase(w_description); fold_and_print(w_description, 0, 0, WIDTH - 2, c_ltblue, bio_data.description.c_str()); wrefresh(w_description); } } }