Beispiel #1
0
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);
    }
}
Beispiel #2
0
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);
            }
        }
    }