void set_symbol(terrain_type *type) { if (!type) return; long ch = popup_getkey("Enter symbol for %s.", type->name.c_str()); if (ch == KEY_ESC) return; type->symbol.symbol = ch; Window w_col(1, 1, 20, 6); w_col.outline(); for (int i = 0; i < c_dkgray; i++) { w_col.putch(i + 1, 1, nc_color(i), c_black, '#'); w_col.putch(i + 1, 3, nc_color(i + 8), c_black, '#'); } w_col.putstr(1, 2, c_white, c_black, "12345678"); w_col.putstr(1, 4, c_white, c_black, "abcdefgh"); w_col.refresh(); ch = getch(); if (ch >= '1' && ch <= '8') type->symbol.fg = nc_color(ch - '1'); if (ch >= 'a' && ch <= 'h') type->symbol.fg = nc_color(ch - 'a' + c_dkgray); type->symbol.bg = c_black; }
bool worldfactory::valid_worldname(std::string name, bool automated) { std::string msg; if (name == "save") { msg = string_format(_("%s is not a valid world name, it is a reserved name"), name.c_str()); } else if (std::find(all_worldnames.begin(), all_worldnames.end(), name) == all_worldnames.end()) { return true; } else { msg = string_format(_("%s is not a valid world name, already exists!"), name.c_str()); } if (!automated) { popup_getkey(msg.c_str()); } return false; }
void game_menus::inv::reassign_letter( player &p, item &it ) { while( true ) { const long invlet = popup_getkey( _( "Enter new letter (press SPACE for none, ESCAPE to cancel)." ) ); if( invlet == KEY_ESCAPE ) { break; } else if( invlet == ' ' ) { p.reassign_item( it, 0 ); break; } else if( inv_chars.valid( invlet ) ) { p.reassign_item( it, invlet ); break; } } }
void input_context::display_help() { inp_mngr.set_timeout(-1); // Shamelessly stolen from help.cpp WINDOW *w_help = newwin(FULL_SCREEN_HEIGHT - 2, FULL_SCREEN_WIDTH - 2, 1 + (int)((TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0), 1 + (int)((TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0)); // has the user changed something? bool changed = false; // keybindings before the user changed anything. input_manager::t_action_contexts old_action_contexts(inp_mngr.action_contexts); // current status: adding/removing/showing keybindings enum { s_remove, s_add, s_add_global, s_show } status = s_show; // copy of registered_actions, but without the ANY_INPUT and COORDINATE, which should not be shown std::vector<std::string> org_registered_actions(registered_actions); std::vector<std::string>::iterator any_input = std::find(org_registered_actions.begin(), org_registered_actions.end(), ANY_INPUT); if (any_input != org_registered_actions.end()) { org_registered_actions.erase(any_input); } std::vector<std::string>::iterator coordinate = std::find(org_registered_actions.begin(), org_registered_actions.end(), COORDINATE); if (coordinate != org_registered_actions.end()) { org_registered_actions.erase(coordinate); } // colors of the keybindings static const nc_color global_key = c_ltgray; static const nc_color local_key = c_ltgreen; static const nc_color unbound_key = c_ltred; // (vertical) scroll offset size_t scroll_offset = 0; // height of the area usable for display of keybindings, excludes headers & borders const size_t display_height = FULL_SCREEN_HEIGHT - 9 - 2; // -2 for the border // width of the legend const size_t legwidth = FULL_SCREEN_WIDTH - 4 - 2; // keybindings help std::ostringstream legend; legend << "<color_" << string_from_color(unbound_key) << ">" << _("Unbound keys") << "</color>\n"; legend << "<color_" << string_from_color(local_key) << ">" << _("Keybinding active only on this screen") << "</color>\n"; legend << "<color_" << string_from_color(global_key) << ">" << _("Keybinding active globally") << "</color>\n"; legend << _("Press - to remove keybinding\nPress + to add local keybinding\nPress = to add global keybinding\n"); input_context ctxt("HELP_KEYBINDINGS"); ctxt.register_action("UP", _("Scroll up")); ctxt.register_action("DOWN", _("Scroll down")); ctxt.register_action("PAGE_DOWN"); ctxt.register_action("PAGE_UP"); ctxt.register_action("REMOVE"); ctxt.register_action("ADD_LOCAL"); ctxt.register_action("ADD_GLOBAL"); ctxt.register_action("QUIT"); ctxt.register_action("ANY_INPUT"); if (category != "HELP_KEYBINDINGS") { // avoiding inception! ctxt.register_action("HELP_KEYBINDINGS"); } std::string hotkeys = ctxt.get_available_single_char_hotkeys(display_help_hotkeys); while(true) { werase(w_help); draw_border(w_help); draw_scrollbar(w_help, scroll_offset, display_height, org_registered_actions.size() - display_height, 8); mvwprintz(w_help, 0, (FULL_SCREEN_WIDTH - utf8_width(_("Keybindings"))) / 2 - 1, c_ltred, " %s ", _("Keybindings")); fold_and_print(w_help, 1, 2, legwidth, c_white, legend.str()); for (size_t i = 0; i + scroll_offset < org_registered_actions.size() && i < display_height; i++) { const std::string &action_id = org_registered_actions[i + scroll_offset]; bool overwrite_default; const action_attributes &attributes = inp_mngr.get_action_attributes(action_id, category, &overwrite_default); char invlet; if (i < hotkeys.size()) { invlet = hotkeys[i]; } else { invlet = ' '; } if (status == s_add_global && overwrite_default) { // We're trying to add a global, but this action has a local // defined, so gray out the invlet. mvwprintz(w_help, i + 8, 2, c_dkgray, "%c ", invlet); } else if (status == s_add || status == s_add_global) { mvwprintz(w_help, i + 8, 2, c_blue, "%c ", invlet); } else if (status == s_remove) { mvwprintz(w_help, i + 8, 2, c_blue, "%c ", invlet); } else { mvwprintz(w_help, i + 8, 2, c_blue, " "); } nc_color col; if (attributes.input_events.empty()) { col = unbound_key; } else if (overwrite_default) { col = local_key; } else { col = global_key; } mvwprintz(w_help, i + 8, 4, col, "%s: ", get_action_name(action_id).c_str()); mvwprintz(w_help, i + 8, 52, col, "%s", get_desc(action_id).c_str()); } wrefresh(w_help); refresh(); // In addition to the modifiable hotkeys, we also check for hardcoded // keys, e.g. '+', '-', '=', in order to prevent the user from // entering an unrecoverable state. const std::string action = ctxt.handle_input(); const long raw_input_char = ctxt.get_raw_input().get_first_input(); if (action == "ADD_LOCAL" || raw_input_char == '+') { status = s_add; } else if (action == "ADD_GLOBAL" || raw_input_char == '=') { status = s_add_global; } else if (action == "REMOVE" || raw_input_char == '-') { status = s_remove; } else if (action == "ANY_INPUT") { const size_t hotkey_index = hotkeys.find_first_of(raw_input_char); if (status == s_show || hotkey_index == std::string::npos ) { continue; } const size_t action_index = hotkey_index + scroll_offset; if( action_index >= org_registered_actions.size() ) { continue; } const std::string &action_id = org_registered_actions[action_index]; // Check if this entry is local or global. bool is_local = false; inp_mngr.get_action_attributes(action_id, category, &is_local); const std::string name = get_action_name(action_id); if (status == s_remove && (!OPTIONS["QUERY_KEYBIND_REMOVAL"] || query_yn(_("Clear keys for %s?"), name.c_str()))) { // If it's global, reset the global actions. std::string category_to_access = category; if (!is_local) { category_to_access = default_context_id; } inp_mngr.remove_input_for_action(action_id, category_to_access); changed = true; } else if (status == s_add_global && is_local) { // Disallow adding global actions to an action that already has a local defined. popup(_("There are already local keybindings defined for this action, please remove them first.")); } else if (status == s_add || status == s_add_global) { const long newbind = popup_getkey(_("New key for %s:"), name.c_str()); const input_event new_event(newbind, CATA_INPUT_KEYBOARD); const std::string conflicts = get_conflicts(new_event); const bool has_conflicts = !conflicts.empty(); bool resolve_conflicts = false; if (has_conflicts) { resolve_conflicts = query_yn( _("This key conflicts with %s. Remove this key from the conflicting command(s), and continue?"), conflicts.c_str()); } if (!has_conflicts || resolve_conflicts) { if (resolve_conflicts) { clear_conflicting_keybindings(new_event); } // We might be adding a local or global action. std::string category_to_access = category; if (status == s_add_global) { category_to_access = default_context_id; } inp_mngr.add_input_for_action(action_id, category_to_access, new_event); changed = true; } } status = s_show; } else if (action == "DOWN") { if (scroll_offset < org_registered_actions.size() - display_height) { scroll_offset++; } } else if (action == "UP") { if (scroll_offset > 0) { scroll_offset--; } } else if (action == "PAGE_DOWN") { if( scroll_offset + display_height < org_registered_actions.size() ) { scroll_offset += std::min(display_height, org_registered_actions.size() - display_height - scroll_offset); } else if( org_registered_actions.size() > display_height ) { scroll_offset = 0; } } else if( action == "PAGE_UP" ) { if( scroll_offset >= display_height ) { scroll_offset -= display_height; } else if( scroll_offset > 0 ) { scroll_offset = 0; } else if( org_registered_actions.size() > display_height ) { scroll_offset = org_registered_actions.size() - display_height; } } else if (action == "QUIT") { if (status != s_show) { status = s_show; } else { break; } } else if (action == "HELP_KEYBINDINGS") { // update available hotkeys in case they've changed hotkeys = ctxt.get_available_single_char_hotkeys(display_help_hotkeys); } } if (changed && query_yn(_("Save changes?"))) { try { inp_mngr.save(); } catch(std::exception &err) { popup(_("saving keybindings failed: %s"), err.what()); } catch(std::string &err) { popup(_("saving keybindings failed: %s"), err.c_str()); } } else if(changed) { inp_mngr.action_contexts.swap(old_action_contexts); } werase(w_help); wrefresh(w_help); delwin(w_help); }
void player::power_bionics() { std::vector <bionic *> passive = filtered_bionics( *my_bionics, TAB_PASSIVE ); std::vector <bionic *> active = filtered_bionics( *my_bionics, TAB_ACTIVE ); bionic *bio_last = NULL; bionic_tab_mode tab_mode = TAB_ACTIVE; //added title_tab_height for the tabbed bionic display int TITLE_HEIGHT = 2; int TITLE_TAB_HEIGHT = 3; // Main window /** Total required height is: * top frame line: + 1 * height of title window: + TITLE_HEIGHT * height of tabs: + TITLE_TAB_HEIGHT * height of the biggest list of active/passive bionics: + bionic_count * bottom frame line: + 1 * TOTAL: TITLE_HEIGHT + TITLE_TAB_HEIGHT + bionic_count + 2 */ const int HEIGHT = std::min( TERMY, std::max( FULL_SCREEN_HEIGHT, TITLE_HEIGHT + TITLE_TAB_HEIGHT + ( int )my_bionics->size() + 2 ) ); const int WIDTH = FULL_SCREEN_WIDTH + ( TERMX - FULL_SCREEN_WIDTH ) / 2; const int START_X = ( TERMX - WIDTH ) / 2; const int START_Y = ( TERMY - HEIGHT ) / 2; //wBio is the entire bionic window catacurses::window wBio = catacurses::newwin( HEIGHT, WIDTH, START_Y, START_X ); const int LIST_HEIGHT = HEIGHT - TITLE_HEIGHT - TITLE_TAB_HEIGHT - 2; const int DESCRIPTION_WIDTH = WIDTH - 2 - 40; const int DESCRIPTION_START_Y = START_Y + TITLE_HEIGHT + TITLE_TAB_HEIGHT + 1; const int DESCRIPTION_START_X = START_X + 1 + 40; //w_description is the description panel that is controlled with ! key catacurses::window w_description = catacurses::newwin( LIST_HEIGHT, DESCRIPTION_WIDTH, DESCRIPTION_START_Y, DESCRIPTION_START_X ); // Title window const int TITLE_START_Y = START_Y + 1; const int HEADER_LINE_Y = TITLE_HEIGHT + TITLE_TAB_HEIGHT + 1; catacurses::window w_title = catacurses::newwin( TITLE_HEIGHT, WIDTH - 2, TITLE_START_Y, START_X + 1 ); const int TAB_START_Y = TITLE_START_Y + 2; //w_tabs is the tab bar for passive and active bionic groups catacurses::window w_tabs = catacurses::newwin( TITLE_TAB_HEIGHT, WIDTH - 2, TAB_START_Y, START_X + 1 ); int scroll_position = 0; int cursor = 0; //generate the tab title string and a count of the bionics owned bionic_menu_mode menu_mode = ACTIVATING; // 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;// - scroll_position; int half_list_view_location = LIST_HEIGHT / 2; int max_scroll_position = std::max( 0, ( int )active.size() ); input_context ctxt( "BIONICS" ); ctxt.register_updown(); ctxt.register_action( "ANY_INPUT" ); ctxt.register_action( "TOGGLE_EXAMINE" ); ctxt.register_action( "REASSIGN" ); ctxt.register_action( "REMOVE" ); ctxt.register_action( "NEXT_TAB" ); ctxt.register_action( "PREV_TAB" ); ctxt.register_action( "CONFIRM" ); ctxt.register_action( "HELP_KEYBINDINGS" ); bool recalc = false; bool redraw = true; for( ;; ) { if( recalc ) { passive = filtered_bionics( *my_bionics, TAB_PASSIVE ); active = filtered_bionics( *my_bionics, TAB_ACTIVE ); if( active.empty() && !passive.empty() ) { tab_mode = TAB_PASSIVE; } if( --cursor < 0 ) { cursor = 0; } if( scroll_position > max_scroll_position && cursor - scroll_position < LIST_HEIGHT - half_list_view_location ) { scroll_position--; } recalc = false; // bionics were modified, so it's necessary to redraw the screen redraw = true; } //track which list we are looking at std::vector<bionic *> *current_bionic_list = ( tab_mode == TAB_ACTIVE ? &active : &passive ); max_scroll_position = std::max( 0, ( int )current_bionic_list->size() - LIST_HEIGHT ); if( redraw ) { redraw = false; werase( wBio ); draw_border( wBio, BORDER_COLOR, _( " BIONICS " ) ); // Draw symbols to connect additional lines to border mvwputch( wBio, HEADER_LINE_Y - 1, 0, BORDER_COLOR, LINE_XXXO ); // |- mvwputch( wBio, HEADER_LINE_Y - 1, WIDTH - 1, BORDER_COLOR, LINE_XOXX ); // -| int max_width = 0; std::vector<std::string>bps; for( int i = 0; i < num_bp; ++i ) { const body_part bp = bp_aBodyPart[i]; const int total = get_total_bionics_slots( bp ); const std::string s = string_format( "%s: %d/%d", body_part_name_as_heading( bp, 1 ).c_str(), total - get_free_bionics_slots( bp ), total ); bps.push_back( s ); max_width = std::max( max_width, utf8_width( s ) ); } const int pos_x = WIDTH - 2 - max_width; if( g->u.has_trait( trait_id( "DEBUG_CBM_SLOTS" ) ) ) { for( int i = 0; i < num_bp; ++i ) { mvwprintz( wBio, i + list_start_y, pos_x, c_light_gray, bps[i] ); } } if( current_bionic_list->empty() ) { std::string msg; switch( tab_mode ) { case TAB_ACTIVE: msg = _( "No activatable bionics installed." ); break; case TAB_PASSIVE: msg = _( "No passive bionics installed." ); break; } fold_and_print( wBio, list_start_y, 2, pos_x - 1, c_light_gray, msg ); } else { for( size_t i = scroll_position; i < current_bionic_list->size(); i++ ) { if( list_start_y + static_cast<int>( i ) - scroll_position == HEIGHT - 1 ) { break; } const bool is_highlighted = cursor == static_cast<int>( i ); const nc_color col = get_bionic_text_color( *( *current_bionic_list )[i], is_highlighted ); const std::string desc = string_format( "%c %s", ( *current_bionic_list )[i]->invlet, build_bionic_powerdesc_string( *( *current_bionic_list )[i] ).c_str() ); trim_and_print( wBio, list_start_y + i - scroll_position, 2, WIDTH - 3, col, desc ); if( is_highlighted && menu_mode != EXAMINING && g->u.has_trait( trait_id( "DEBUG_CBM_SLOTS" ) ) ) { const bionic_id bio_id = ( *current_bionic_list )[i]->id; draw_connectors( wBio, list_start_y + i - scroll_position, utf8_width( desc ) + 3, pos_x - 2, bio_id ); // redraw highlighted (occupied) body parts for( auto &elem : bio_id->occupied_bodyparts ) { const int i = static_cast<int>( elem.first ); mvwprintz( wBio, i + list_start_y, pos_x, c_yellow, bps[i] ); } } } } draw_scrollbar( wBio, cursor, LIST_HEIGHT, current_bionic_list->size(), list_start_y ); } wrefresh( wBio ); draw_bionics_tabs( w_tabs, active.size(), passive.size(), tab_mode ); draw_bionics_titlebar( w_title, this, menu_mode ); if( menu_mode == EXAMINING && !current_bionic_list->empty() ) { draw_description( w_description, *( *current_bionic_list )[cursor] ); } const std::string action = ctxt.handle_input(); const long ch = ctxt.get_raw_input().get_first_input(); bionic *tmp = NULL; bool confirmCheck = false; if( action == "DOWN" ) { redraw = true; if( static_cast<size_t>( cursor ) < current_bionic_list->size() - 1 ) { cursor++; } else { cursor = 0; } if( scroll_position < max_scroll_position && cursor - scroll_position > LIST_HEIGHT - half_list_view_location ) { scroll_position++; } if( scroll_position > 0 && cursor - scroll_position < half_list_view_location ) { scroll_position = std::max( cursor - half_list_view_location, 0 ); } } else if( action == "UP" ) { redraw = true; if( cursor > 0 ) { cursor--; } else { cursor = current_bionic_list->size() - 1; } if( scroll_position > 0 && cursor - scroll_position < half_list_view_location ) { scroll_position--; } if( scroll_position < max_scroll_position && cursor - scroll_position > LIST_HEIGHT - half_list_view_location ) { scroll_position = std::max( std::min<int>( current_bionic_list->size() - LIST_HEIGHT, cursor - half_list_view_location ), 0 ); } } else if( menu_mode == REASSIGNING ) { menu_mode = ACTIVATING; if( action == "CONFIRM" && !current_bionic_list->empty() ) { auto &bio_list = tab_mode == TAB_ACTIVE ? active : passive; tmp = bio_list[cursor]; } else { tmp = bionic_by_invlet( ch ); } if( tmp == nullptr ) { // Selected an non-existing bionic (or Escape, or ...) continue; } redraw = true; const long newch = popup_getkey( _( "%s; enter new letter. Space to clear. Esc to cancel." ), tmp->id->name.c_str() ); wrefresh( wBio ); if( newch == ch || newch == KEY_ESCAPE ) { continue; } if( newch == ' ' ) { tmp->invlet = ' '; continue; } if( !bionic_chars.valid( newch ) ) { popup( _( "Invalid bionic letter. Only those characters are valid:\n\n%s" ), bionic_chars.get_allowed_chars().c_str() ); continue; } bionic *otmp = bionic_by_invlet( newch ); if( otmp != nullptr ) { 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 == "NEXT_TAB" ) { redraw = true; scroll_position = 0; cursor = 0; if( tab_mode == TAB_ACTIVE ) { tab_mode = TAB_PASSIVE; } else { tab_mode = TAB_ACTIVE; } } else if( action == "PREV_TAB" ) { redraw = true; scroll_position = 0; cursor = 0; if( tab_mode == TAB_PASSIVE ) { tab_mode = TAB_ACTIVE; } else { tab_mode = TAB_PASSIVE; } } else if( action == "REASSIGN" ) { menu_mode = REASSIGNING; } else if( action == "TOGGLE_EXAMINE" ) { // switches between activation and examination menu_mode = menu_mode == ACTIVATING ? EXAMINING : ACTIVATING; redraw = true; } else if( action == "REMOVE" ) { menu_mode = REMOVING; redraw = true; } else if( action == "HELP_KEYBINDINGS" ) { redraw = true; } else if( action == "CONFIRM" ) { confirmCheck = true; } else { confirmCheck = true; } //confirmation either occurred by pressing enter where the bionic cursor is, or the hotkey was selected if( confirmCheck ) { auto &bio_list = tab_mode == TAB_ACTIVE ? active : passive; if( action == "CONFIRM" && !current_bionic_list->empty() ) { tmp = bio_list[cursor]; } else { tmp = bionic_by_invlet( ch ); if( tmp && tmp != bio_last ) { // new bionic selected, update cursor and scroll position int temp_cursor = 0; for( temp_cursor = 0; temp_cursor < ( int )bio_list.size(); temp_cursor++ ) { if( bio_list[temp_cursor] == tmp ) { break; } } // if bionic is not found in current list, ignore the attempt to view/activate if( temp_cursor >= ( int )bio_list.size() ) { continue; } //relocate cursor to the bionic that was found cursor = temp_cursor; scroll_position = 0; while( scroll_position < max_scroll_position && cursor - scroll_position > LIST_HEIGHT - half_list_view_location ) { scroll_position++; } } } if( !tmp ) { // entered a key that is not mapped to any bionic, // -> leave screen break; } bio_last = tmp; const bionic_id &bio_id = tmp->id; const bionic_data &bio_data = bio_id.obj(); if( menu_mode == REMOVING ) { recalc = uninstall_bionic( bio_id ); redraw = true; continue; } if( menu_mode == ACTIVATING ) { if( bio_data.activated ) { int b = tmp - &( *my_bionics )[0]; if( tmp->powered ) { deactivate_bionic( b ); } else { activate_bionic( b ); // Clear the menu if we are firing a bionic gun if( tmp->info().gun_bionic ) { break; } } // update message log and the menu g->refresh_all(); redraw = true; if( moves < 0 ) { return; } continue; } else { popup( _( "You can not activate %s!\n" "To read a description of %s, press '!', then '%c'." ), bio_data.name.c_str(), bio_data.name.c_str(), tmp->invlet ); redraw = true; } } else if( menu_mode == EXAMINING ) { // Describing bionics, allow user to jump to description key redraw = true; if( action != "CONFIRM" ) { for( size_t i = 0; i < active.size(); i++ ) { if( active[i] == tmp ) { tab_mode = TAB_ACTIVE; cursor = static_cast<int>( i ); int max_scroll_check = std::max( 0, ( int )active.size() - LIST_HEIGHT ); if( static_cast<int>( i ) > max_scroll_check ) { scroll_position = max_scroll_check; } else { scroll_position = i; } break; } } for( size_t i = 0; i < passive.size(); i++ ) { if( passive[i] == tmp ) { tab_mode = TAB_PASSIVE; cursor = static_cast<int>( i ); int max_scroll_check = std::max( 0, ( int )passive.size() - LIST_HEIGHT ); if( static_cast<int>( i ) > max_scroll_check ) { scroll_position = max_scroll_check; } else { scroll_position = i; } break; } } } } } } }
void player::power_mutations() { std::vector <std::string> passive; std::vector <std::string> active; for( auto &mut : my_mutations ) { if (!mutation_branch::get( mut.first ).activated) { passive.push_back(mut.first); } else { active.push_back(mut.first); } // New mutations are initialized with no key at all, so we have to do this here. if( mut.second.key == ' ' ) { for( const auto &letter : inv_chars ) { if( trait_by_invlet( letter ).empty() ) { mut.second.key = letter; break; } } } } // maximal number of rows in both columns const int mutations_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 mutation captions: + 1 * height of the biggest list of active/passive mutations: + mutations_count * line before mutation description: + 1 * height of description window: + DESCRIPTION_HEIGHT * bottom frame line: + 1 * TOTAL: TITLE_HEIGHT + mutations_count + DESCRIPTION_HEIGHT + 5 */ int HEIGHT = std::min(TERMY, std::max(FULL_SCREEN_HEIGHT, TITLE_HEIGHT + mutations_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 mutations input_context ctxt("MUTATIONS"); ctxt.register_updown(); ctxt.register_action("ANY_INPUT"); ctxt.register_action("TOGGLE_EXAMINE"); ctxt.register_action("REASSIGN"); ctxt.register_action("HELP_KEYBINDINGS"); bool redraw = true; std::string menu_mode = "activating"; while(true) { // offset for display: mutation with index i is drawn at y=list_start_y+i // drawing the mutation starts with mutation[scroll_position] const int list_start_y = HEADER_LINE_Y + 2 - scroll_position; int max_scroll_position = HEADER_LINE_Y + 2 + mutations_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++) { const auto &md = mutation_branch::get( passive[i] ); const auto &td = my_mutations[passive[i]]; if (list_start_y + static_cast<int>(i) == (menu_mode == "examining" ? DESCRIPTION_LINE_Y : HEIGHT - 1)) { break; } type = c_cyan; mvwprintz(wBio, list_start_y + i, 2, type, "%c %s", td.key, md.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++) { const auto &md = mutation_branch::get( active[i] ); const auto &td = my_mutations[active[i]]; if (list_start_y + static_cast<int>(i) == (menu_mode == "examining" ? DESCRIPTION_LINE_Y : HEIGHT - 1)) { break; } if (!td.powered) { type = c_red; }else if (td.powered) { type = c_ltgreen; } else { type = c_ltred; } // TODO: track resource(s) used and specify mvwputch( wBio, list_start_y + i, second_column, type, td.key ); std::stringstream mut_desc; mut_desc << md.name; if ( md.cost > 0 && md.cooldown > 0 ) { mut_desc << string_format( _(" - %d RU / %d turns"), md.cost, md.cooldown ); } else if ( md.cost > 0 ) { mut_desc << string_format( _(" - %d RU"), md.cost ); } else if ( md.cooldown > 0 ) { mut_desc << string_format( _(" - %d turns"), md.cooldown ); } if ( td.powered ) { mut_desc << _(" - Active"); } mvwprintz( wBio, list_start_y + i, second_column + 2, type, mut_desc.str().c_str() ); } } // 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_mutations_titlebar(w_title, this, menu_mode); const std::string action = ctxt.handle_input(); const long ch = ctxt.get_raw_input().get_first_input(); if (menu_mode == "reassigning") { menu_mode = "activating"; const auto mut_id = trait_by_invlet( ch ); if( mut_id.empty() ) { // Selected an non-existing mutation (or escape, or ...) continue; } redraw = true; const char newch = popup_getkey(_("%s; enter new letter."), mutation_branch::get_name( mut_id ).c_str()); wrefresh(wBio); if(newch == ch || newch == ' ' || newch == KEY_ESCAPE) { continue; } const auto other_mut_id = trait_by_invlet( newch ); // if there is already a mutation with the new key, the key // is considered valid. if( other_mut_id.empty() && inv_chars.find(newch) == std::string::npos ) { // TODO separate list of letters for mutations popup(_("%c is not a valid inventory letter."), newch); continue; } if( !other_mut_id.empty() ) { std::swap(my_mutations[mut_id].key, my_mutations[other_mut_id].key); } else { my_mutations[mut_id].key = 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 == "TOGGLE_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 == "HELP_KEYBINDINGS") { redraw = true; } else { const auto mut_id = trait_by_invlet( ch ); if( mut_id.empty() ) { // entered a key that is not mapped to any mutation, // -> leave screen break; } const auto &mut_data = mutation_branch::get( mut_id ); if (menu_mode == "activating") { if (mut_data.activated) { if (my_mutations[mut_id].powered) { add_msg(m_neutral, _("You stop using your %s."), mut_data.name.c_str()); deactivate_mutation( mut_id ); delwin(w_title); delwin(w_description); delwin(wBio); // Action done, leave screen break; } else if( (!mut_data.hunger || hunger <= 400) && (!mut_data.thirst || thirst <= 400) && (!mut_data.fatigue || fatigue <= 400) ) { // this will clear the mutations menu for targeting purposes werase(wBio); wrefresh(wBio); delwin(w_title); delwin(w_description); delwin(wBio); g->draw(); add_msg( m_neutral, _("You activate your %s."), mut_data.name.c_str() ); activate_mutation( mut_id ); // Action done, leave screen break; } else { popup( _( "You don't have enough in you to activate your %s!" ), mut_data.name.c_str() ); redraw = true; continue; } } else { popup(_("\ You cannot activate %s! To read a description of \ %s, press '!', then '%c'."), mut_data.name.c_str(), mut_data.name.c_str(), my_mutations[mut_id].key ); redraw = true; } } if (menu_mode == "examining") { // Describing mutations, 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, mut_data.description); wrefresh(w_description); } } } //if we activated a mutation, already killed the windows if(!(menu_mode == "activating")) { werase(wBio); wrefresh(wBio); delwin(w_title); delwin(w_description); delwin(wBio); } }
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); } } }