/* Explosion Animation */
void game::draw_explosion(int x, int y, int radius, nc_color col)
{
    timespec ts;    // Timespec for the animation of the explosion
    ts.tv_sec = 0;
    ts.tv_nsec = EXPLOSION_SPEED;
    const int ypos = POSY + (y - (u.posy + u.view_offset_y));
    const int xpos = POSX + (x - (u.posx + u.view_offset_x));
    for (int i = 1; i <= radius; i++) {
        mvwputch(w_terrain, ypos - i, xpos - i, col, '/');
        mvwputch(w_terrain, ypos - i, xpos + i, col, '\\');
        mvwputch(w_terrain, ypos + i, xpos - i, col, '\\');
        mvwputch(w_terrain, ypos + i, xpos + i, col, '/');
        for (int j = 1 - i; j < 0 + i; j++) {
            mvwputch(w_terrain, ypos - i, xpos + j, col, '-');
            mvwputch(w_terrain, ypos + i, xpos + j, col, '-');
            mvwputch(w_terrain, ypos + j, xpos - i, col, '|');
            mvwputch(w_terrain, ypos + j, xpos + i, col, '|');
        }
        wrefresh(w_terrain);
        nanosleep(&ts, NULL);
    }
}
Beispiel #2
0
void monster::draw(WINDOW *w, int plx, int ply, bool inv)
{
 int x = SEEX + posx - plx;
 int y = SEEY + posy - ply;
 nc_color color = type->color;
 
 // see if it's possible to draw a graphical sprite
 if(type->sprite) {
  if(draw_object(w, x, y, type->sprite)) return;
 }
 
 if (friendly != 0 && !inv)
  mvwputch_hi(w, y, x, color, type->sym);
 else if (inv)
  mvwputch_inv(w, y, x, color, type->sym);
 else {
  color = color_with_effects();
  mvwputch(w, y, x, color, type->sym);
 }
}
Beispiel #3
0
void hit_animation(int iX, int iY, nc_color cColor, char cTile, int iTimeout)
{
    WINDOW *w_hit = newwin(1, 1, iY + VIEW_OFFSET_Y, iX + VIEW_OFFSET_X);
    if (w_hit == NULL) {
        return; //we passed in negative values (semi-expected), so let's not segfault
    }
    w_hit_animation = w_hit;

    mvwputch(w_hit, 0, 0, cColor, cTile);
    wrefresh(w_hit);

    if (iTimeout <= 0 || iTimeout > 999) {
        iTimeout = 70;
    }

    timeout(iTimeout);
    getch(); //using this, because holding down a key with nanosleep can get yourself killed
    timeout(-1);
    w_hit_animation = NULL;
}
Beispiel #4
0
/* Bullet Animation */
void game::draw_bullet(player &p, int tx, int ty, int i, std::vector<point> trajectory, char bullet, timespec &ts)
{
    if (u_see(tx, ty)) {
        if (i > 0)
        {
            m.drawsq(w_terrain, u, trajectory[i-1].x, trajectory[i-1].y, false,
                     true, u.posx + u.view_offset_x, u.posy + u.view_offset_y);
        }
        /*
        char bullet = '*';
        if (is_aflame)
         bullet = '#';
        */
        mvwputch(w_terrain, POSY + (ty - (u.posy + u.view_offset_y)),
                 POSX + (tx - (u.posx + u.view_offset_x)), c_red, bullet);
        wrefresh(w_terrain);
        if (&p == &u)
         nanosleep(&ts, NULL);
   }
}
void game::draw_weather(weather_printable wPrint)
{
    if (use_tiles) {
        std::string weather_name;

        switch(wPrint.wtype) {
        // Acid weathers, uses acid droplet tile, fallthrough intended
        case WEATHER_ACID_DRIZZLE:
        case WEATHER_ACID_RAIN:
            weather_name = "weather_acid_drop";
            break;

        // Normal rainy weathers, uses normal raindrop tile, fallthrough intended
        case WEATHER_DRIZZLE:
        case WEATHER_RAINY:
        case WEATHER_THUNDER:
        case WEATHER_LIGHTNING:
            weather_name = "weather_rain_drop";
            break;

        // Snowy weathers, uses snowflake tile, fallthrough intended
        case WEATHER_FLURRIES:
        case WEATHER_SNOW:
        case WEATHER_SNOWSTORM:
            weather_name = "weather_snowflake";
            break;

        default:
            break;
        }

        tilecontext->init_draw_weather(wPrint, weather_name);
    } else {
        for (std::vector<std::pair<int, int> >::iterator weather_iterator = wPrint.vdrops.begin();
             weather_iterator != wPrint.vdrops.end();
             ++weather_iterator) {
            mvwputch(w_terrain, weather_iterator->second, weather_iterator->first, wPrint.colGlyph,
                     wPrint.cGlyph);
        }
    }
}
// need to have a version where there is no player defined, possibly. That way shrapnel works as intended
void game::draw_bullet(player &p, int tx, int ty, int i, std::vector<point> trajectory, char bullet_char, timespec &ts)
{
    if (u_see(tx, ty)) {
        std::string bullet;// = "animation_bullet_normal";
        switch(bullet_char)
        {
            case '*': bullet = "animation_bullet_normal"; break;
            case '#': bullet = "animation_bullet_flame"; break;
            case '`': bullet = "animation_bullet_shrapnel"; break;
        }

        mvwputch(w_terrain, ty + VIEWY - u.posy - u.view_offset_y,
                 tx + VIEWX - u.posx - u.view_offset_x, c_red, bullet_char);
        // pass to tilecontext
        tilecontext->init_draw_bullet(tx, ty, bullet);
        wrefresh(w_terrain);
        if (&p == &u)
         nanosleep(&ts, NULL);
        tilecontext->void_bullet();
   }
}
Beispiel #7
0
static void draw_recipe_subtabs( const catacurses::window &w, std::string tab, std::string subtab,
                                 const recipe_subset &available_recipes, TAB_MODE mode )
{
    werase( w );
    int width = getmaxx( w );
    for( int i = 0; i < width; i++ ) {
        if( i == 0 ) {
            mvwputch( w, 2, i, BORDER_COLOR, LINE_XXXO );
        } else if( i == width ) {
            mvwputch( w, 2, i, BORDER_COLOR, LINE_XOXX );
        } else {
            mvwputch( w, 2, i, BORDER_COLOR, LINE_OXOX );
        }
    }

    for( int i = 0; i < 3; i++ ) {
        mvwputch( w, i,  0, BORDER_COLOR, LINE_XOXO ); // |^
        mvwputch( w, i, width - 1, BORDER_COLOR,  LINE_XOXO ); // ^|
    }

    switch( mode ) {
        case NORMAL: {
            int pos_x = 2;//draw the tabs on each other
            int tab_step = 3;//step between tabs, two for tabs border
            for( const auto stt : craft_subcat_list[tab] ) {
                bool empty = available_recipes.empty_category( tab, stt != "CSC_ALL" ? stt : "" );
                draw_subtab( w, pos_x, normalized_names[stt], subtab == stt, true, empty );
                pos_x += utf8_width( normalized_names[stt] ) + tab_step;
            }
            break;
        }
        case FILTERED:
        case BATCH:
            werase( w );
            for( int i = 0; i < 3; i++ ) {
                mvwputch( w, i,  0, BORDER_COLOR, LINE_XOXO ); // |^
                mvwputch( w, i, width - 1, BORDER_COLOR,  LINE_XOXO ); // ^|
            }
            break;
    }

    wrefresh( w );
}
/* Bullet Animation */
void game::draw_bullet(Creature &p, int tx, int ty, int i, std::vector<point> trajectory,
                       char bullet, timespec &ts)
{
    if (u.sees(tx, ty)) {
        if (i > 0) {
            m.drawsq(w_terrain, u, trajectory[i - 1].x, trajectory[i - 1].y, false,
                     true, u.posx() + u.view_offset_x, u.posy() + u.view_offset_y);
        }
        /*
        char bullet = '*';
        if (is_aflame)
         bullet = '#';
        */
        mvwputch(w_terrain, POSY + (ty - (u.posy() + u.view_offset_y)),
                 POSX + (tx - (u.posx() + u.view_offset_x)), c_red, bullet);
        wrefresh(w_terrain);
        if( p.is_player() && ts.tv_nsec != 0 ) {
            nanosleep(&ts, NULL);
        }
    }
}
/* Monster hit animation */
void game::draw_hit_mon(int x, int y, monster m, bool dead)
{
    if (use_tiles)
    {
        //int iTimeout = 0;
        tilecontext->init_draw_hit(x, y, monster_names[m.type->id]);
        wrefresh(w_terrain);

        timespec tspec;
        tspec.tv_sec = 0;
        tspec.tv_nsec = BULLET_SPEED;

        nanosleep(&tspec, NULL);
        /*
        nc_color cMonColor = m.type->color;
        char sMonSym = m.symbol();
        hit_animation(x,
                      y,
                      red_background(cMonColor), dead?'%':sMonSym);
        */
        /*
        x + VIEWX - u.posx - u.view_offset_x,
                      y + VIEWY - u.posy - u.view_offset_y,
        */
        mvwputch(w_terrain,
                 x + VIEWX - u.posx - u.view_offset_x,
                 y + VIEWY - u.posy - u.view_offset_y,
                 c_white, ' ');
        wrefresh(w_terrain);
    }
    else
    {
        nc_color cMonColor = m.type->color;
        char sMonSym = m.symbol();

        hit_animation(x + VIEWX - u.posx - u.view_offset_x,
                  y + VIEWY - u.posy - u.view_offset_y,
                  red_background(cMonColor), dead?'%':sMonSym);
    }
}
Beispiel #10
0
void inventory_selector::print_column(const itemstack_vector &items, size_t y, size_t w,
                                      size_t selected, size_t current_page_offset) const
{
    nc_color selected_line_color = inCategoryMode ? c_white_red : h_white;
    if ((&items == &this->items) != in_inventory) {
        selected_line_color = inCategoryMode ? c_ltgray_red : h_ltgray;
    }
    int cur_line = 2;
    for (size_t a = 0; a + current_page_offset < items.size() && a < items_per_page; a++, cur_line++) {
        const itemstack_or_category &cur_entry = items[a + current_page_offset];
        if (cur_entry.category == NULL) {
            continue;
        }
        if (cur_entry.it == NULL) {
            const std::string name = trim_to(cur_entry.category->name, w);
            mvwprintz(w_inv, cur_line, y, c_magenta, "%s", name.c_str());
            continue;
        }
        const item &it = *cur_entry.it;
        std::string item_name = it.display_name();
        if (cur_entry.slice != NULL) {
            const size_t count = cur_entry.slice->size();
            if (count > 1) {
                item_name = string_format("%d %s", count, it.display_name(count).c_str());
            }
        }
        nc_color name_color = it.color_in_inventory();
        nc_color invlet_color = c_white;
        if (a + current_page_offset == selected) {
            name_color = selected_line_color;
            invlet_color = selected_line_color;
        }
        item_name = get_drop_icon(dropping.find(cur_entry.item_pos)) + item_name;
        item_name = trim_to(item_name, w - 2); // 2 for the invlet & space
        if (it.invlet != 0) {
            mvwputch(w_inv, cur_line, y, invlet_color, it.invlet);
        }
        mvwprintz(w_inv, cur_line, y + 2, name_color, "%s", item_name.c_str());
    }
}
Beispiel #11
0
void editmap::uber_draw_ter( WINDOW *w, map *m )
{
    point center = target;
    point start = point(center.x - getmaxx(w) / 2, center.y - getmaxy(w) / 2);
    point end = point(center.x + getmaxx(w) / 2, center.y + getmaxy(w) / 2);
    /*
        // pending filter options
        bool draw_furn=true;
        bool draw_ter=true;
        bool draw_trp=true;
        bool draw_fld=true;
        bool draw_veh=true;
    */
    bool draw_itm = true;
    bool game_map = ( ( m == &g->m || w == g->w_terrain ) ? true : false );
    const int msize = SEEX * MAPSIZE;
    for (int x = start.x, sx = 0; x <= end.x; x++, sx++) {
        for (int y = start.y, sy = 0; y <= end.y; y++, sy++) {
            nc_color col = c_dkgray;
            long sym = ( game_map ? '%' : ' ' );
            if ( x >= 0 && x < msize && y >= 0 && y < msize ) {
                if ( game_map ) {
                    int mon_idx = g->mon_at(x, y);
                    int npc_idx = g->npc_at(x, y);
                    if ( mon_idx >= 0 ) {
                        g->zombie(mon_idx).draw(w, center.x, center.y, false);
                    } else if ( npc_idx >= 0 ) {
                        g->active_npc[npc_idx]->draw(w, center.x, center.y, false);
                    } else {
                        m->drawsq(w, g->u, x, y, false, draw_itm, center.x, center.y, false, true);
                    }
                } else {
                    m->drawsq(w, g->u, x, y, false, draw_itm, center.x, center.y, false, true);
                }
            } else {
                mvwputch(w, sy, sx, col, sym);
            }
        }
    }
}
Beispiel #12
0
std::string string_input_popup(std::string title, int max_length, std::string input)
{
 std::string ret = input;

 int startx = title.size() + 2;
 WINDOW *w = newwin(3, 80, (TERMY-3)/2, ((TERMX > 80) ? (TERMX-80)/2 : 0));
 wborder(w, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX,
            LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX );
 for (int i = startx + 1; i < 79; i++)
  mvwputch(w, 1, i, c_ltgray, '_');

 mvwprintz(w, 1, 1, c_ltred, "%s", title.c_str());

 if (input != "")
  mvwprintz(w, 1, startx, c_magenta, "%s", input.c_str());

 int posx = startx + input.size();
 mvwputch(w, 1, posx, h_ltgray, '_');
 do {
  wrefresh(w);
  long ch = getch();
  if (ch == 27) {	// Escape
   werase(w);
   wrefresh(w);
   delwin(w);
   refresh();
   return "";
  } else if (ch == '\n') {
   werase(w);
   wrefresh(w);
   delwin(w);
   refresh();
   return ret;
  } else if ((ch == KEY_BACKSPACE || ch == 127) && posx > startx) {
// Move the cursor back and re-draw it
   ret = ret.substr(0, ret.size() - 1);
   mvwputch(w, 1, posx, c_ltgray, '_');
   posx--;
   mvwputch(w, 1, posx, h_ltgray, '_');
  } else if(ret.size() < max_length || max_length == 0) {
   ret += ch;
   mvwputch(w, 1, posx, c_magenta, ch);
   posx++;
   mvwputch(w, 1, posx, h_ltgray, '_');
  }
 } while (true);
}
void sokoban_game::draw_level(WINDOW *w_sokoban)
{
    const int iOffsetX = (FULL_SCREEN_WIDTH - 2 - mLevelInfo[iCurrentLevel]["MaxLevelX"]) / 2;
    const int iOffsetY = (FULL_SCREEN_HEIGHT - 2 - mLevelInfo[iCurrentLevel]["MaxLevelY"]) / 2;

    for (std::map<int, std::map<int, std::string> >::iterator iterY = mLevel.begin();
         iterY != mLevel.end(); ++iterY) {
        for (std::map<int, std::string>::iterator iterX = (iterY->second).begin();
             iterX != (iterY->second).end(); ++iterX) {
            std::string sTile = iterX->second;

            if (sTile == "#") {
                mvwputch(w_sokoban, iOffsetY + (iterY->first), iOffsetX + (iterX->first), c_white,
                         get_wall_connection(iterY->first, iterX->first));

            } else {
                nc_color cCol = c_white;

                if (sTile == "." || sTile == "*" ||  sTile == "+") {
                    cCol = red_background(c_white);
                }

                if (sTile == ".") {
                    sTile = " ";
                }

                if (sTile == "*") {
                    sTile = "$";
                }

                if (sTile == "+") {
                    sTile = "@";
                }

                mvwprintz(w_sokoban, iOffsetY + (iterY->first), iOffsetX + (iterX->first), cCol, sTile.c_str());
            }
        }
    }
}
Beispiel #14
0
std::string string_input_popup(int max_length, const char *mes, ...)
{
 std::string ret;
 va_list ap;
 va_start(ap, mes);
 char buff[1024];
 vsprintf(buff, mes, ap);
 va_end(ap);
 int startx = strlen(buff) + 2;
 WINDOW* w = newwin(3, 80, 11, 0);
 wborder(w, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX,
            LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX );
 mvwprintz(w, 1, 1, c_ltred, "%s", buff);
 for (int i = startx + 1; i < 79; i++)
  mvwputch(w, 1, i, c_ltgray, '_');
 int posx = startx;
 mvwputch(w, 1, posx, h_ltgray, '_');
 do {
  wrefresh(w);
  long ch = getch();
  if (ch == 27) {	// Escape
   werase(w);
   wrefresh(w);
   delwin(w);
   refresh();
   return "";
  } else if (ch == '\n') {
   werase(w);
   wrefresh(w);
   delwin(w);
   refresh();
   return ret;
  } else if ((ch == KEY_BACKSPACE || ch == 127) && posx > startx) {
// Move the cursor back and re-draw it
   ret = ret.substr(0, ret.size() - 1);
   mvwputch(w, 1, posx, c_ltgray, '_');
   posx--;
   mvwputch(w, 1, posx, h_ltgray, '_');
  } else if(ret.size() < max_length || max_length == 0) {
   ret += ch;
   mvwputch(w, 1, posx, c_magenta, ch);
   posx++;
   mvwputch(w, 1, posx, h_ltgray, '_');
  }
 } while (true);
}
/* Tiles version of Explosion Animation */
void game::draw_explosion(int x, int y, int radius, nc_color col)
{
    timespec ts;    // Timespec for the animation of the explosion
    ts.tv_sec = 0;
    ts.tv_nsec = EXPLOSION_SPEED;
// added offset values to keep from calculating the same value over and over again.
    const int offset_x = VIEWX - u.posx - u.view_offset_x;
    const int offset_y = VIEWY - u.posy - u.view_offset_y;

    for (int i = 1; i <= radius; i++) {
        mvwputch(w_terrain, y - i + offset_y,
                      x - i + offset_x, col, '/');
        mvwputch(w_terrain, y - i + offset_y,
                      x + i + offset_x, col,'\\');
        mvwputch(w_terrain, y + i + offset_y,
                      x - i + offset_x, col,'\\');
        mvwputch(w_terrain, y + i + offset_y,
                      x + i + offset_x, col, '/');
        for (int j = 1 - i; j < 0 + i; j++) {
            mvwputch(w_terrain, y - i + offset_y,
                       x + j + offset_x, col,'-');
            mvwputch(w_terrain, y + i + offset_y,
                       x + j + offset_x, col,'-');
            mvwputch(w_terrain, y + j + offset_y,
                       x - i + offset_x, col,'|');
            mvwputch(w_terrain, y + j + offset_y,
                       x + i + offset_x, col,'|');
        }
        tilecontext->init_explosion(x, y, i);
        //tilecontext->draw_explosion_frame(x, y, radius, offset_x, offset_y);

        wrefresh(w_terrain);
        nanosleep(&ts, NULL);
    }
    tilecontext->void_explosion();
}
Beispiel #16
0
static void draw_recipe_subtabs( WINDOW *w, std::string tab, std::string subtab, TAB_MODE mode )
{
    werase( w );
    int width = getmaxx( w );
    for( int i = 0; i < width; i++ ) {
        if( i == 0 ) {
            mvwputch( w, 2, i, BORDER_COLOR, LINE_XXXO );
        } else if( i == width ) {
            mvwputch( w, 2, i, BORDER_COLOR, LINE_XOXX );
        } else {
            mvwputch( w, 2, i, BORDER_COLOR, LINE_OXOX );
        }
    }

    for( int i = 0; i < 3; i++ ) {
        mvwputch( w, i,  0, BORDER_COLOR, LINE_XOXO ); // |^
        mvwputch( w, i, width - 1, BORDER_COLOR,  LINE_XOXO ); // ^|
    }

    switch( mode ) {
        case NORMAL: {
            int pos_x = 2;//draw the tabs on each other
            int tab_step = 3;//step between tabs, two for tabs border
            for( const auto stt : craft_subcat_list[tab] ) {
                draw_subtab( w, pos_x, normalized_names[stt], subtab == stt );
                pos_x += utf8_width( normalized_names[stt] ) + tab_step;
            }
            break;
        }
        case FILTERED:
        case BATCH:
            werase( w );
            for( int i = 0; i < 3; i++ ) {
                mvwputch( w, i,  0, BORDER_COLOR, LINE_XOXO ); // |^
                mvwputch( w, i, width - 1, BORDER_COLOR,  LINE_XOXO ); // ^|
            }
            break;
    }

    wrefresh( w );
}
// draws footsteps that have been created by monsters moving about
void game::draw_footsteps()
{
    std::queue<point> step_tiles;
    for (int i = 0; i < footsteps.size(); i++) {
        if (!u_see(footsteps_source[i]->posx(),footsteps_source[i]->posy())){
            std::vector<point> unseen_points;
            for (int j = 0; j < footsteps[i].size(); j++){
                if (!u_see(footsteps[i][j].x,footsteps[i][j].y)){
                    unseen_points.push_back(point(footsteps[i][j].x,
                                               footsteps[i][j].y));
                }
            }

            if (use_tiles){
                if (unseen_points.size() > 0){
                    step_tiles.push(unseen_points[rng(0, unseen_points.size()-1)]);
                }
            }else{
                if (unseen_points.size() > 0){
                    point selected = unseen_points[rng(0,unseen_points.size() - 1)];

                    mvwputch(w_terrain,
                            POSY + (selected.y - (u.posy + u.view_offset_y)),
                            POSX + (selected.x - (u.posx + u.view_offset_x)),
                            c_yellow, '?');
                }
            }
        }
    }
    if (use_tiles){
        tilecontext->init_draw_footsteps(step_tiles);
    }
    footsteps.clear();
    footsteps_source.clear();
    wrefresh(w_terrain);
    return;
}
Beispiel #18
0
int worldfactory::show_worldgen_tab_options(WINDOW *win, WORLDPTR world)
{
    const int iTooltipHeight = 4;
    const int iContentHeight = FULL_SCREEN_HEIGHT - 5 - iTooltipHeight;

    const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    WINDOW *w_options = newwin(iContentHeight, FULL_SCREEN_WIDTH - 2, iTooltipHeight + 4 + iOffsetY,
                               1 + iOffsetX);
    WINDOW_PTR w_optionsptr( w_options );

    WINDOW *w_options_tooltip = newwin(iTooltipHeight - 2, FULL_SCREEN_WIDTH - 2, 3 + iOffsetY,
                                       1 + iOffsetX);
    WINDOW_PTR w_options_tooltipptr( w_options_tooltip );

    WINDOW *w_options_header = newwin(1, FULL_SCREEN_WIDTH - 2, iTooltipHeight + 3 + iOffsetY,
                                      1 + iOffsetX);
    WINDOW_PTR w_options_headerptr( w_options_header );

    std::stringstream sTemp;

    std::map<int, bool> mapLines;
    mapLines[4] = true;
    mapLines[60] = true;

    for( auto &mapLine : mapLines ) {
        mvwputch( win, FULL_SCREEN_HEIGHT - 1, mapLine.first + 1, BORDER_COLOR, LINE_XXOX ); // _|_
    }

    for (int i = 0; i < 78; i++) {
        if (mapLines[i]) {
            mvwputch(w_options_header, 0, i, BORDER_COLOR, LINE_OXXX);
        } else {
            mvwputch(w_options_header, 0, i, BORDER_COLOR, LINE_OXOX); // Draw header line
        }
    }

    mvwputch(win, iTooltipHeight + 3,  0, BORDER_COLOR, LINE_XXXO); // |-
    mvwputch(win, iTooltipHeight + 3, 79, BORDER_COLOR, LINE_XOXX); // -|

    wrefresh(win);
    wrefresh(w_options_header);

    input_context ctxt("WORLDGEN_OPTION_DIALOG");
    ctxt.register_cardinal();
    ctxt.register_action("HELP_KEYBINDINGS");
    ctxt.register_action("QUIT");
    ctxt.register_action("NEXT_TAB");
    ctxt.register_action("PREV_TAB");
    int iStartPos = 0;
    int iCurrentLine = 0;

    do {
        for (int i = 0; i < iContentHeight; i++) {
            for (int j = 0; j < 79; j++) {
                if (mapLines[j]) {
                    mvwputch(w_options, i, j, BORDER_COLOR, LINE_XOXO);
                } else {
                    mvwputch(w_options, i, j, c_black, ' ');
                }

                if (i < iTooltipHeight) {
                    mvwputch(w_options_tooltip, i, j, c_black, ' ');
                }
            }
        }

        calcStartPos(iStartPos, iCurrentLine, iContentHeight, mPageItems[iWorldOptPage].size());

        //Draw options
        int iBlankOffset = 0;
        for (int i = iStartPos; i < iStartPos + ((iContentHeight > (int)mPageItems[iWorldOptPage].size()) ?
                (int)mPageItems[iWorldOptPage].size() : iContentHeight); i++) {
            nc_color cLineColor = c_ltgreen;

            if (world->world_options[mPageItems[iWorldOptPage][i]].getMenuText() == "") {
                iBlankOffset++;
                continue;
            }

            sTemp.str("");
            sTemp << i + 1 - iBlankOffset;
            mvwprintz(w_options, i - iStartPos, 1, c_white, sTemp.str().c_str());
            mvwprintz(w_options, i - iStartPos, 5, c_white, "");

            if (iCurrentLine == i) {
                wprintz(w_options, c_yellow, ">> ");
            } else {
                wprintz(w_options, c_yellow, "   ");
            }
            wprintz(w_options, c_white, "%s",
                    (world->world_options[mPageItems[iWorldOptPage][i]].getMenuText()).c_str());

            if (world->world_options[mPageItems[iWorldOptPage][i]].getValue() == "false") {
                cLineColor = c_ltred;
            }

            mvwprintz(w_options, i - iStartPos, 62, (iCurrentLine == i) ? hilite(cLineColor) :
                      cLineColor, "%s", (world->world_options[mPageItems[iWorldOptPage][i]].getValueName()).c_str());
        }

        //Draw Scrollbar
        draw_scrollbar(win, iCurrentLine, iContentHeight,
                       mPageItems[iWorldOptPage].size(), iTooltipHeight + 4, 0, BORDER_COLOR);

        fold_and_print(w_options_tooltip, 0, 0, 78, c_white, "%s #%s",
                       world->world_options[mPageItems[iWorldOptPage][iCurrentLine]].getTooltip().c_str(),
                       world->world_options[mPageItems[iWorldOptPage][iCurrentLine]].getDefaultText().c_str());

        wrefresh(w_options_tooltip);
        wrefresh(w_options);
        refresh();

        const std::string action = ctxt.handle_input();
        if (action == "DOWN") {
            do {
                iCurrentLine++;
                if (iCurrentLine >= (int)mPageItems[iWorldOptPage].size()) {
                    iCurrentLine = 0;
                }
            } while(world->world_options[mPageItems[iWorldOptPage][iCurrentLine]].getMenuText() == "");

        } else if (action == "UP") {
            do {
                iCurrentLine--;
                if (iCurrentLine < 0) {
                    iCurrentLine = mPageItems[iWorldOptPage].size() - 1;
                }
            } while(world->world_options[mPageItems[iWorldOptPage][iCurrentLine]].getMenuText() == "");

        } else if (!mPageItems[iWorldOptPage].empty() && action == "RIGHT") {
            world->world_options[mPageItems[iWorldOptPage][iCurrentLine]].setNext();

        } else if (!mPageItems[iWorldOptPage].empty() && action == "LEFT") {
            world->world_options[mPageItems[iWorldOptPage][iCurrentLine]].setPrev();

        } else if (action == "PREV_TAB") {
            return -1;

        } else if (action == "NEXT_TAB") {
            return 1;

        } else if (action == "QUIT") {
            return -999;
        }

    } while (true);

    return 0;
}
Beispiel #19
0
WORLDPTR worldfactory::pick_world( bool show_prompt )
{
    std::map<std::string, WORLDPTR> worlds = get_all_worlds();
    std::vector<std::string> world_names = all_worldnames;

    // Filter out special worlds (TUTORIAL | DEFENSE) from world_names.
    for (std::vector<std::string>::iterator it = world_names.begin(); it != world_names.end();) {
        if (*it == "TUTORIAL" || *it == "DEFENSE") {
            it = world_names.erase(it);
        } else if (world_need_lua_build(*it)) {
            it = world_names.erase(it);
        } else {
            ++it;
        }
    }
    // If there is only one world to pick from, autoreturn it.
    if (world_names.size() == 1) {
        return worlds[world_names[0]];
    }
    // If there are no worlds to pick from, immediately try to make one.
    else if (world_names.empty()) {
        return make_new_world( show_prompt );
    }
    // If we're skipping prompts, just return the first one.
    else if( !show_prompt ) {
        return worlds[world_names[0]];
    }

    const int iTooltipHeight = 3;
    const int iContentHeight = FULL_SCREEN_HEIGHT - 3 - iTooltipHeight;
    const unsigned int num_pages = world_names.size() / iContentHeight + 1; // at least 1 page
    const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    std::map<int, bool> mapLines;
    mapLines[3] = true;

    std::map<int, std::vector<std::string> > world_pages;
    unsigned int worldnum = 0;
    for (size_t i = 0; i < num_pages; ++i) {
        for (int j = 0; j < iContentHeight && worldnum < world_names.size(); ++j) {
            world_pages[i].push_back(world_names[worldnum++]);
        }
    }
    unsigned int sel = 0, selpage = 0;

    WINDOW *w_worlds_border = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX);
    WINDOW *w_worlds_tooltip = newwin(iTooltipHeight, FULL_SCREEN_WIDTH - 2, 1 + iOffsetY,
                                      1 + iOffsetX);
    WINDOW *w_worlds_header = newwin(1, FULL_SCREEN_WIDTH - 2, 1 + iTooltipHeight + iOffsetY,
                                     1 + iOffsetX);
    WINDOW *w_worlds        = newwin(iContentHeight, FULL_SCREEN_WIDTH - 2,
                                     iTooltipHeight + 2 + iOffsetY, 1 + iOffsetX);

    draw_border(w_worlds_border);
    mvwputch(w_worlds_border, 4, 0, BORDER_COLOR, LINE_XXXO); // |-
    mvwputch(w_worlds_border, 4, FULL_SCREEN_WIDTH - 1, BORDER_COLOR, LINE_XOXX); // -|

    for( auto &mapLine : mapLines ) {
        mvwputch( w_worlds_border, FULL_SCREEN_HEIGHT - 1, mapLine.first + 1, BORDER_COLOR,
                  LINE_XXOX ); // _|_
    }

    center_print(w_worlds_border, 0, c_ltred, _(" WORLD SELECTION "));
    wrefresh(w_worlds_border);

    for (int i = 0; i < 78; i++) {
        if (mapLines[i]) {
            mvwputch(w_worlds_header, 0, i, BORDER_COLOR, LINE_OXXX);
        } else {
            mvwputch(w_worlds_header, 0, i, BORDER_COLOR, LINE_OXOX); // Draw header line
        }
    }

    wrefresh(w_worlds_header);

    input_context ctxt("PICK_WORLD_DIALOG");
    ctxt.register_updown();
    ctxt.register_action("HELP_KEYBINDINGS");
    ctxt.register_action("QUIT");
    ctxt.register_action("NEXT_TAB");
    ctxt.register_action("PREV_TAB");
    ctxt.register_action("CONFIRM");

    std::stringstream sTemp;

    while(true) {
        //Clear the lines
        for (int i = 0; i < iContentHeight; i++) {
            for (int j = 0; j < 79; j++) {
                if (mapLines[j]) {
                    mvwputch(w_worlds, i, j, BORDER_COLOR, LINE_XOXO);
                } else {
                    mvwputch(w_worlds, i, j, c_black, ' ');
                }

                if (i < iTooltipHeight) {
                    mvwputch(w_worlds_tooltip, i, j, c_black, ' ');
                }
            }
        }

        //Draw World Names
        for (size_t i = 0; i < world_pages[selpage].size(); ++i) {
            sTemp.str("");
            sTemp << i + 1;
            mvwprintz(w_worlds, i, 0, c_white, "%s", sTemp.str().c_str());
            mvwprintz(w_worlds, i, 4, c_white, "");

            std::string world_name = (world_pages[selpage])[i];
            size_t saves_num = world_generator->all_worlds[world_name]->world_saves.size();

            if (i == sel) {
                wprintz(w_worlds, c_yellow, ">> ");
            } else {
                wprintz(w_worlds, c_yellow, "   ");
            }

            if (world_need_lua_build(world_name)) {
                wprintz(w_worlds, c_dkgray, "%s (%i)", world_name.c_str(), saves_num);
            } else {
                wprintz(w_worlds, c_white, "%s (%i)", world_name.c_str(), saves_num);
            }
        }

        //Draw Tabs
        mvwprintz(w_worlds_header, 0, 7, c_white, "");

        for (size_t i = 0; i < num_pages; ++i) {
            nc_color tabcolor = (selpage == i) ? hilite(c_white) : c_white;
            if (!world_pages[i].empty()) { //skip empty pages
                wprintz(w_worlds_header, c_white, "[");
                wprintz(w_worlds_header, tabcolor, _("Page %d"), i + 1);
                wprintz(w_worlds_header, c_white, "]");
                wputch(w_worlds_header, BORDER_COLOR, LINE_OXOX);
            }
        }

        wrefresh(w_worlds_header);

        fold_and_print(w_worlds_tooltip, 0, 0, 78, c_white, _("Pick a world to enter game"));
        wrefresh(w_worlds_tooltip);

        wrefresh(w_worlds);

        const std::string action = ctxt.handle_input();

        if (action == "QUIT") {
            break;
        } else if (!world_pages[selpage].empty() && action == "DOWN") {
            sel++;
            if (sel >= world_pages[selpage].size()) {
                sel = 0;
            }
        } else if (!world_pages[selpage].empty() && action == "UP") {
            if (sel == 0) {
                sel = world_pages[selpage].size() - 1;
            } else {
                sel--;
            }
        } else if (action == "NEXT_TAB") {
            sel = 0;
            do { //skip empty pages
                selpage++;
                if (selpage >= world_pages.size()) {
                    selpage = 0;
                }
            } while(world_pages[selpage].empty());
        } else if (action == "PREV_TAB") {
            sel = 0;
            do { //skip empty pages
                if (selpage != 0) {
                    selpage--;
                } else {
                    selpage = world_pages.size() - 1;
                }
            } while(world_pages[selpage].empty());
        } else if (action == "CONFIRM") {
            if (world_need_lua_build(world_pages[selpage][sel])) {
                popup(_("Can't start in world [%s]. Some of mods require Lua support."),
                      world_pages[selpage][sel].c_str());
                continue;
            }
            // we are wanting to get out of this by confirmation, so ask if we want to load the level [y/n prompt] and if yes exit
            if (query_yn(_("Do you want to start the game in world [%s]?"),
                         world_pages[selpage][sel].c_str())) {
                werase(w_worlds);
                werase(w_worlds_border);
                werase(w_worlds_header);
                werase(w_worlds_tooltip);
                return all_worlds[world_pages[selpage][sel]];//sel + selpage * iContentHeight;
            }
        }
    }

    werase(w_worlds);
    werase(w_worlds_border);
    werase(w_worlds_header);
    werase(w_worlds_tooltip);

    return NULL;
}
Beispiel #20
0
void worldfactory::draw_modselection_borders(WINDOW *win, input_context *ctxtp)
{
    // make appropriate lines: X & Y coordinate of starting point, length, horizontal/vertical type
    int xs[] = {1, 1, (FULL_SCREEN_WIDTH / 2) + 2, (FULL_SCREEN_WIDTH / 2) - 4,
                (FULL_SCREEN_WIDTH / 2) + 2
               };
    int ys[] = {FULL_SCREEN_HEIGHT - 8, 4, 4, 3, 3};
    int ls[] = {FULL_SCREEN_WIDTH - 2, (FULL_SCREEN_WIDTH / 2) - 4, (FULL_SCREEN_WIDTH / 2) - 3,
                FULL_SCREEN_HEIGHT - 11, 1
               };
    bool hv[] = {true, true, true, false, false}; // horizontal line = true, vertical line = false

    for (int i = 0; i < 5; ++i) {
        int x = xs[i];
        int y = ys[i];
        int l = ls[i];
        if (hv[i]) {
            for (int j = 0; j < l; ++j) {
                mvwputch(win, y, x + j, BORDER_COLOR, LINE_OXOX); // _
            }
        } else {
            for (int j = 0; j < l; ++j) {
                mvwputch(win, y + j, x, BORDER_COLOR, LINE_XOXO); // |
            }
        }
    }

    // Add in connective characters
    mvwputch(win, 4, 0, BORDER_COLOR, LINE_XXXO);
    mvwputch(win, FULL_SCREEN_HEIGHT - 8, 0, BORDER_COLOR, LINE_XXXO);
    mvwputch(win, 4, FULL_SCREEN_WIDTH / 2 + 2, BORDER_COLOR, LINE_XXXO);

    mvwputch(win, 4, FULL_SCREEN_WIDTH - 1, BORDER_COLOR, LINE_XOXX);
    mvwputch(win, FULL_SCREEN_HEIGHT - 8, FULL_SCREEN_WIDTH - 1, BORDER_COLOR, LINE_XOXX);
    mvwputch(win, 4, FULL_SCREEN_WIDTH / 2 - 4, BORDER_COLOR, LINE_XOXX);

    mvwputch(win, 2, FULL_SCREEN_WIDTH / 2 - 4, BORDER_COLOR, LINE_OXXX); // -.-
    mvwputch(win, 2, FULL_SCREEN_WIDTH / 2 + 2, BORDER_COLOR, LINE_OXXX); // -.-

    mvwputch(win, FULL_SCREEN_HEIGHT - 8, FULL_SCREEN_WIDTH / 2 - 4, BORDER_COLOR, LINE_XXOX); // _|_
    mvwputch(win, FULL_SCREEN_HEIGHT - 8, FULL_SCREEN_WIDTH / 2 + 2, BORDER_COLOR, LINE_XXOX); // _|_

    // Add tips & hints
    fold_and_print(win, FULL_SCREEN_HEIGHT - 7, 2, getmaxx(win) - 4, c_green,
                   _("Press %s to save the list of active mods as default. Press %s for help."),
                   ctxtp->get_desc("SAVE_DEFAULT_MODS").c_str(),
                   ctxtp->get_desc("HELP_KEYBINDINGS").c_str()
                  );
    wrefresh(win);
    refresh();
}
void game::compare(int iCompareX, int iCompareY)
{
 int examx, examy;
 int ch = (int)'.';

 if (iCompareX != -999 && iCompareX != -999) {
  examx = iCompareX;
  examy = iCompareY;
 } else {
  mvwprintw(w_terrain, 0, 0, "Compare where? (Direction button)");
  wrefresh(w_terrain);

  ch = input();
  last_action += ch;
  if (ch == KEY_ESCAPE || ch == 'q')
   return;
  if (ch == '\n' || ch == 'I')
   ch = '.';
  get_direction(this, examx, examy, ch);
  if (examx == -2 || examy == -2) {
   add_msg("Invalid direction.");
   return;
  }
 }
 examx += u.posx;
 examy += u.posy;
 std::vector <item> here = m.i_at(examx, examy);
 std::vector <item> grounditems;
 //Filter out items with the same name (keep only one of them)
 std::map <std::string, bool> dups;
 for (int i = 0; i < here.size(); i++) {
  if (!dups[here[i].tname(this).c_str()]) {
   grounditems.push_back(here[i]);
   dups[here[i].tname(this).c_str()] = true;
  }
 }
 //Only the first 10 Items due to numbering 0-9
 const int groundsize = (grounditems.size() > 10 ? 10 : grounditems.size());
 u.inv.sort();
 u.inv.restack(&u);
 
 invslice stacks = u.inv.slice(0, u.inv.size());

 WINDOW* w_inv = newwin(TERMY-VIEW_OFFSET_Y*2, TERMX-VIEW_OFFSET_X*2, VIEW_OFFSET_Y, VIEW_OFFSET_X);
 int maxitems = TERMY-5-VIEW_OFFSET_Y*2;    // Number of items to show at one time.
 std::vector<int> compare_list; // Count of how many we'll drop from each stack
 bool bFirst = false; // First Item selected
 bool bShowCompare = false;
 char cLastCh;
 compare_list.resize(u.inv.size() + groundsize, 0);
 std::vector<char> weapon_and_armor; // Always single, not counted
 print_inv_statics(this, w_inv, "Compare:", weapon_and_armor);
// Gun, ammo, weapon, armor, food, tool, book, other
 std::vector<int> first = find_firsts(stacks);
 std::vector<int> firsts;
 if (groundsize > 0) {
  firsts.push_back(0);
 }
 for (int i = 0; i < first.size(); i++) {
  firsts.push_back((first[i] >= 0) ? first[i]+groundsize : -1);
 }
 ch = '.';
 int start = 0, cur_it;
 do {
  if (( ch == '<' || ch == KEY_PPAGE ) && start > 0) {
   for (int i = 1; i < maxitems+4; i++)
    mvwprintz(w_inv, i, 0, c_black, "                                             ");
   start -= maxitems;
   if (start < 0)
    start = 0;
   mvwprintw(w_inv, maxitems + 4, 0, "         ");
  }
  if (( ch == '>' || ch == KEY_NPAGE ) && cur_it < u.inv.size() + groundsize) {
   start = cur_it;
   mvwprintw(w_inv, maxitems + 4, 12, "            ");
   for (int i = 1; i < maxitems+4; i++)
    mvwprintz(w_inv, i, 0, c_black, "                                             ");
  }
  int cur_line = 2;
  int iHeaderOffset = (groundsize > 0) ? 0 : 1;

  for (cur_it = start; cur_it < start + maxitems && cur_line < maxitems+3; cur_it++) {
// Clear the current line;
   mvwprintw(w_inv, cur_line, 0, "                                             ");
// Print category header
   for (int i = iHeaderOffset; i < iCategorieNum; i++) {
    if (cur_it == firsts[i-iHeaderOffset]) {
     mvwprintz(w_inv, cur_line, 0, c_magenta, CATEGORIES[i].c_str());
     cur_line++;
    }
   }
   if (cur_it < u.inv.size() + groundsize) {
    char icon = '-';
    if (compare_list[cur_it] == 1)
     icon = '+';
    if (cur_it < groundsize) {
     mvwputch (w_inv, cur_line, 0, c_white, '1'+((cur_it<9) ? cur_it: -1));
     nc_color col = (compare_list[cur_it] == 0 ? c_ltgray : c_white);
     mvwprintz(w_inv, cur_line, 1, col, " %c %s", icon,
               grounditems[cur_it].tname(this).c_str());
    } else {
     item& it = stacks[cur_it-groundsize]->front();
     mvwputch (w_inv, cur_line, 0, c_white, it.invlet);
     nc_color col = (compare_list[cur_it] == 0 ? c_ltgray : c_white);
     mvwprintz(w_inv, cur_line, 1, col, " %c %s", icon,
               it.tname(this).c_str());
     if (stacks[cur_it-groundsize]->size() > 1)
      wprintz(w_inv, col, " [%d]", stacks[cur_it-groundsize]->size());
     if (it.charges > 0)
      wprintz(w_inv, col, " (%d)", it.charges);
     else if (it.contents.size() == 1 &&
              it.contents[0].charges > 0)
      wprintw(w_inv, " (%d)", it.contents[0].charges);
    }
   }
   cur_line++;
  }
  if (start > 0)
   mvwprintw(w_inv, maxitems + 4, 0, "< Go Back");
  if (cur_it < u.inv.size() + groundsize)
   mvwprintw(w_inv, maxitems + 4, 12, "> More items");
  wrefresh(w_inv);
  ch = getch();
  if (u.has_item(ch)) {
   item& it = u.inv.item_by_letter(ch);
   if (it.is_null()) { // Not from inventory
    bool found = false;
    for (int i = 0; i < weapon_and_armor.size() && !found; i++) {
     if (weapon_and_armor[i] == ch) {
      weapon_and_armor.erase(weapon_and_armor.begin() + i);
      found = true;
      bFirst = false;
      print_inv_statics(this, w_inv, "Compare:", weapon_and_armor);
     }
    }
    if (!found) {

     if ( ch == u.weapon.invlet &&
          std::find(unreal_itype_ids.begin(), unreal_itype_ids.end(), u.weapon.type->id) != unreal_itype_ids.end()){
      //Do Bionic stuff here?!
     } else {
      if (!bFirst)
      {
       weapon_and_armor.push_back(ch);
       print_inv_statics(this, w_inv, "Compare:", weapon_and_armor);
       bFirst = true;
       cLastCh = ch;
      } else {
       bShowCompare = true;
      }
     }
    }
   } else {
    int index = -1;
    for (int i = 0; i < stacks.size(); ++i) {
     if (stacks[i]->front().invlet == it.invlet) {
      index = i;
      break;
     }
    }
    if (index == -1) {
     debugmsg("Inventory got out of sync with inventory slice?");
    }
    if (compare_list[index+groundsize] == 1)
    {
     compare_list[index+groundsize] = 0;
     bFirst = false;
    } else {
     if (!bFirst)
     {
      compare_list[index+groundsize] = 1;
      bFirst = true;
      cLastCh = ch;
     } else {
      bShowCompare = true;
     }
    }
   }
  } else if ((ch >= '1' && ch <= '9' && ch-'1' < groundsize) || (ch == '0' && groundsize == 10)) {
   //Ground Items
   int iZero = 0;
   if (ch == '0') {
    iZero = 10;
   }
   if (compare_list[ch-'1'+iZero] == 1)
   {
    compare_list[ch-'1'+iZero] = 0;
    bFirst = false;
   } else {
    if (!bFirst)
    {
     compare_list[ch-'1'+iZero] = 1;
     bFirst = true;
     cLastCh = ch;
    } else {
     bShowCompare = true;
    }
   }
  }
  if (bShowCompare) {
   std::vector<iteminfo> vItemLastCh, vItemCh;
   std::string sItemLastCh, sItemCh;
   if (cLastCh >= '0' && cLastCh <= '9') {
    int iZero = 0;
    if (cLastCh == '0') {
     iZero = 10;
    }

    grounditems[cLastCh-'1'+iZero].info(true, &vItemLastCh);
    sItemLastCh = grounditems[cLastCh-'1'+iZero].tname(this);
   } else {
    u.i_at(cLastCh).info(true, &vItemLastCh);
    sItemLastCh = u.i_at(cLastCh).tname(this);
   }

   if (ch >= '0' && ch <= '9') {
    int iZero = 0;
    if (ch == '0') {
     iZero = 10;
    }

    grounditems[ch-'1'+iZero].info(true, &vItemCh);
    sItemCh = grounditems[ch-'1'+iZero].tname(this);
   } else {
    u.i_at(ch).info(true, &vItemCh);
    sItemCh = u.i_at(ch).tname(this);
   }

   compare_split_screen_popup(0, (TERMX-VIEW_OFFSET_X*2)/2, TERMY-VIEW_OFFSET_Y*2, sItemLastCh, vItemLastCh, vItemCh);
   compare_split_screen_popup((TERMX-VIEW_OFFSET_X*2)/2, (TERMX-VIEW_OFFSET_X*2)/2, TERMY-VIEW_OFFSET_Y*2, sItemCh, vItemCh, vItemLastCh);

   wclear(w_inv);
   print_inv_statics(this, w_inv, "Compare:", weapon_and_armor);
   bShowCompare = false;
  }
 } while (ch != '\n' && ch != KEY_ESCAPE && ch != ' ');
 werase(w_inv);
 delwin(w_inv);
 erase();
 refresh_all();
}
std::vector<item> game::multidrop()
{
 u.inv.sort();
 u.inv.restack(&u);
 WINDOW* w_inv = newwin(((VIEWY < 12) ? 25 : VIEWY*2+1), ((VIEWX < 12) ? 80 : VIEWX*2+56), VIEW_OFFSET_Y, VIEW_OFFSET_X);
 const int maxitems = (VIEWY < 12) ? 20 : VIEWY*2-4;    // Number of items to show at one time.
 std::map<char, int> dropping; // Count of how many we'll drop from each stack
 int count = 0; // The current count
 std::vector<char> weapon_and_armor; // Always single, not counted
 bool warned_about_bionic = false; // Printed add_msg re: dropping bionics
 print_inv_statics(this, w_inv, "Multidrop:", weapon_and_armor);
 int base_weight = u.weight_carried();
 int base_volume = u.volume_carried();

 int ch = (int)'.';
 int start = 0, cur_it;
 invslice stacks = u.inv.slice(0, u.inv.size());
 std::vector<int> firsts = find_firsts(stacks);
 do {
  inventory drop_subset = u.inv.subset(dropping);
  int new_weight = base_weight - drop_subset.weight();
  int new_volume = base_volume - drop_subset.volume();
  for (int i = 0; i < weapon_and_armor.size(); ++i) {
   new_weight -= u.i_at(weapon_and_armor[i]).weight();
  }
  print_inv_weight_vol(this, w_inv, new_weight, new_volume);
  if (( ch == '<' || ch == KEY_PPAGE ) && start > 0) {
   for (int i = 1; i < maxitems+4; i++)
    mvwprintz(w_inv, i, 0, c_black, "                                             ");
   start -= maxitems;
   if (start < 0)
    start = 0;
   mvwprintw(w_inv, maxitems + 4, 0, "         ");
  }
  if (( ch == '>' || ch == KEY_NPAGE ) && cur_it < u.inv.size()) {
   start = cur_it;
   mvwprintw(w_inv, maxitems + 4, 12, "            ");
   for (int i = 1; i < maxitems+4; i++)
    mvwprintz(w_inv, i, 0, c_black, "                                             ");
  }
  int cur_line = 2;
  for (cur_it = start; cur_it < start + maxitems && cur_line < maxitems+3; cur_it++) {
// Clear the current line;
   mvwprintw(w_inv, cur_line, 0, "                                             ");
// Print category header
   for (int i = 1; i < iCategorieNum; i++) {
    if (cur_it == firsts[i-1]) {
     mvwprintz(w_inv, cur_line, 0, c_magenta, CATEGORIES[i].c_str());
     cur_line++;
    }
   }
   if (cur_it < stacks.size()) {
    item& it = stacks[cur_it]->front();
    mvwputch (w_inv, cur_line, 0, c_white, it.invlet);
    char icon = '-';
    if (dropping[it.invlet] >= (it.count_by_charges() ? it.charges : stacks[cur_it]->size()))
     icon = '+';
    else if (dropping[it.invlet] > 0)
     icon = '#';
    nc_color col = (dropping[it.invlet] == 0 ? c_ltgray : c_white);
    mvwprintz(w_inv, cur_line, 1, col, " %c %s", icon,
              it.tname(this).c_str());
    if (stacks[cur_it]->size() > 1)
     wprintz(w_inv, col, " [%d]", stacks[cur_it]->size());
    if (it.charges > 0)
     wprintz(w_inv, col, " (%d)", it.charges);
    else if (it.contents.size() == 1 &&
             it.contents[0].charges > 0)
     wprintw(w_inv, " (%d)", it.contents[0].charges);
   }
   cur_line++;
  }
  if (start > 0)
   mvwprintw(w_inv, maxitems + 4, 0, "< Go Back");
  if (cur_it < u.inv.size())
   mvwprintw(w_inv, maxitems + 4, 12, "> More items");
  wrefresh(w_inv);
  ch = input();
  if (ch >= '0'&& ch <= '9') {
   ch = (char)ch - '0';
   count *= 10;
   count += ch;
  } else if (u.has_item(ch)) {
   item& it = u.inv.item_by_letter(ch);
   if (it.is_null()) { // Not from inventory
    int found = false;
    for (int i = 0; i < weapon_and_armor.size() && !found; i++) {
     if (weapon_and_armor[i] == ch) {
      weapon_and_armor.erase(weapon_and_armor.begin() + i);
      found = true;
      print_inv_statics(this, w_inv, "Multidrop:", weapon_and_armor);
     }
    }
    if (!found) {
     if ( ch == u.weapon.invlet &&
          std::find(unreal_itype_ids.begin(), unreal_itype_ids.end(), u.weapon.type->id) != unreal_itype_ids.end()){
      if (!warned_about_bionic)
       add_msg("You cannot drop your %s.", u.weapon.tname(this).c_str());
      warned_about_bionic = true;
     } else {
      weapon_and_armor.push_back(ch);
      print_inv_statics(this, w_inv, "Multidrop:", weapon_and_armor);
     }
    }
   } else {
    int index = -1;
    for (int i = 0; i < stacks.size(); ++i) {
     if (stacks[i]->front().invlet == it.invlet) {
      index = i;
      break;
     }
    }
    if (index == -1) {
     debugmsg("Inventory got out of sync with inventory slice?");
    }
    if (count == 0) {
    if (it.count_by_charges())
      {
       if (dropping[it.invlet] == 0)
        dropping[it.invlet] = -1;
       else
        dropping[it.invlet] = 0;
      }
    else
      {
       if (dropping[it.invlet] == 0)
        dropping[it.invlet] = stacks[index]->size();
       else
        dropping[it.invlet] = 0;
      }
    }

    else if (count >= stacks[index]->size() && !it.count_by_charges())
       dropping[it.invlet] = stacks[index]->size();
    else
      dropping[it.invlet] = count;

   count = 0;
  }
  }
 } while (ch != '\n' && ch != KEY_ESCAPE && ch != ' ');
 werase(w_inv);
 delwin(w_inv);
 erase();
 refresh_all();

 std::vector<item> ret;

 if (ch != '\n')
  return ret; // Canceled!

 for (std::map<char,int>::iterator it = dropping.begin(); it != dropping.end(); it++) {
  if (it->second == -1)
   ret.push_back( u.inv.remove_item_by_letter( it->first));
  else if (it->second && u.inv.item_by_letter( it->first).count_by_charges()) {
   int charges = u.inv.item_by_letter( it->first).charges;// >= it->second ? : it->second;
   ret.push_back( u.inv.remove_item_by_charges( it->first, it->second > charges ? charges : it->second));
  } else if (it->second) 
   for (int j = it->second; j > 0; j--)
    ret.push_back( u.inv.remove_item_by_letter( it->first));
 }

 for (int i = 0; i < weapon_and_armor.size(); i++)
  ret.push_back(u.i_rem(weapon_and_armor[i]));

 return ret;
}
char game::inv_type(std::string title, item_cat inv_item_type)
{
// this function lists inventory objects by type
// refer to enum item_cat in itype.h for list of categories

 WINDOW* w_inv = newwin(((VIEWY < 12) ? 25 : VIEWY*2+1), ((VIEWX < 12) ? 80 : VIEWX*2+56), VIEW_OFFSET_Y, VIEW_OFFSET_X);
 const int maxitems = (VIEWY < 12) ? 20 : VIEWY*2-4;    // Number of items to show at one time.
 int ch = (int)'.';
 int start = 0, cur_it;
 u.inv.sort();
 u.inv.restack(&u);
 std::vector<char> null_vector;
 print_inv_statics(this, w_inv, title, null_vector);
// Gun, ammo, weapon, armor, food, tool, book, other

// Create the reduced inventory
 inventory reduced_inv = u.inv.filter_by_category(inv_item_type, u);

 invslice slice = reduced_inv.slice(0, reduced_inv.size());
 std::vector<int> firsts = find_firsts(slice);

 do {
  if (( ch == '<' || ch == KEY_PPAGE ) && start > 0) { // Clear lines and shift
   for (int i = 1; i < maxitems+4; i++)
    mvwprintz(w_inv, i, 0, c_black, "                                             ");
   start -= maxitems;
   if (start < 0)
    start = 0;
   mvwprintw(w_inv, maxitems + 4, 0, "         ");
  }
  if (( ch == '>' || ch == KEY_NPAGE ) && cur_it < reduced_inv.size()) { // Clear lines and shift
   start = cur_it;
   mvwprintw(w_inv, maxitems + 4, 12, "            ");
   for (int i = 1; i < maxitems+4; i++)
    mvwprintz(w_inv, i, 0, c_black, "                                             ");
  }
  int cur_line = 2;
  for (cur_it = start; cur_it < start + maxitems && cur_line < maxitems+3; cur_it++) {
// Clear the current line;
   mvwprintw(w_inv, cur_line, 0, "                                             ");

   for (int i = 1; i < iCategorieNum; i++) {
    if (cur_it == firsts[i-1]) {
     mvwprintz(w_inv, cur_line, 0, c_magenta, CATEGORIES[i].c_str());
     cur_line++;
    }
   }

   if (cur_it < slice.size())
   {
    item& it = slice[cur_it]->front();
    mvwputch (w_inv, cur_line, 0, c_white, it.invlet);
    mvwprintz(w_inv, cur_line, 1, it.color_in_inventory(&u), " %s",
              it.tname(this).c_str());
    if (slice[cur_it]->size() > 1)
     wprintw(w_inv, " [%d]", slice[cur_it]->size());
    if (it.charges > 0)
     wprintw(w_inv, " (%d)", it.charges);
    else if (it.contents.size() == 1 &&
             it.contents[0].charges > 0)
     wprintw(w_inv, " (%d)", it.contents[0].charges);
   cur_line++;
   }
//   cur_line++;
  }
  if (start > 0)
   mvwprintw(w_inv, maxitems + 4, 0, "< Go Back");
  if (cur_it < reduced_inv.size())
   mvwprintw(w_inv, maxitems + 4, 12, "> More items");
  wrefresh(w_inv);
  ch = getch();
 } while (ch == '<' || ch == '>' || ch == KEY_NPAGE || ch == KEY_PPAGE );
 werase(w_inv);
 delwin(w_inv);
 erase();
 refresh_all();
 return (char)ch;
}
void game::construction_menu()
{
 int iMaxY = TERMY;
 if (constructions.size()+2 < iMaxY)
  iMaxY = constructions.size()+2;
 if (iMaxY < 25)
  iMaxY = 25;

 WINDOW *w_con = newwin(iMaxY, 80, (TERMY > iMaxY) ? (TERMY-iMaxY)/2 : 0, (TERMX > 80) ? (TERMX-80)/2 : 0);
 wborder(w_con, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX,
                LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX );
 mvwprintz(w_con, 0, 8, c_ltred, " Construction ");

 mvwputch(w_con,  0, 30, c_ltgray, LINE_OXXX);
 mvwputch(w_con, iMaxY-1, 30, c_ltgray, LINE_XXOX);
 for (int i = 1; i < iMaxY-1; i++)
  mvwputch(w_con, i, 30, c_ltgray, LINE_XOXO);

 mvwprintz(w_con,  1, 31, c_white, "Difficulty:");

 wrefresh(w_con);

 bool update_info = true;
 int select = 0;
 int chosen = 0;
 long ch;
 bool exit = false;

 inventory total_inv = crafting_inventory();

 do {
// Erase existing list of constructions
  for (int i = 1; i < iMaxY-1; i++) {
   for (int j = 1; j < 30; j++)
    mvwputch(w_con, i, j, c_black, ' ');
  }
// Determine where in the master list to start printing
  //int offset = select - 11;
  int offset = 0;
  if (select >= iMaxY-2)
   offset = select - iMaxY + 3;
// Print the constructions between offset and max (or how many will fit)
  for (int i = 0; i < iMaxY-2 && (i + offset) < constructions.size(); i++) {
   int current = i + offset;
   nc_color col = (player_can_build(u, total_inv, constructions[current]) ?
                   c_white : c_dkgray);
   // Map menu items to hotkey letters, skipping j, k, l, and q.
   unsigned char hotkey = 97 + current;
   if (hotkey > 122)
    hotkey = hotkey - 58;

   if (current == select)
    col = hilite(col);
   mvwprintz(w_con, 1 + i, 1, col, "%c %s", hotkey, constructions[current]->name.c_str());
  }

  if (update_info) {
   update_info = false;
   constructable* current_con = constructions[select];
// Print difficulty
   int pskill = u.skillLevel("carpentry");
   int diff = current_con->difficulty > 0 ? current_con->difficulty : 0;
   mvwprintz(w_con, 1, 43, (pskill >= diff ? c_white : c_red),
             "%d   ", diff);
// Clear out lines for tools & materials
   for (int i = 2; i < iMaxY-1; i++) {
    for (int j = 31; j < 79; j++)
     mvwputch(w_con, i, j, c_black, ' ');
   }

// Print stages and their requirements
   int posx = 33, posy = 2;
   for (int n = 0; n < current_con->stages.size(); n++) {
     nc_color color_stage = (player_can_build(u, total_inv, current_con, n,
					      false, true) ?
                            c_white : c_dkgray);
    mvwprintz(w_con, posy, 31, color_stage, "Stage %d: %s", n + 1,
              current_con->stages[n].terrain == t_null? "" : terlist[current_con->stages[n].terrain].name.c_str());
    posy++;
// Print tools
    construction_stage stage = current_con->stages[n];
    bool has_tool[10] = {stage.tools[0].empty(),
                         stage.tools[1].empty(),
                         stage.tools[2].empty(),
                         stage.tools[3].empty(),
                         stage.tools[4].empty(),
                         stage.tools[5].empty(),
                         stage.tools[6].empty(),
                         stage.tools[7].empty(),
                         stage.tools[8].empty(),
                         stage.tools[9].empty()};
    posy++;
    posx = 33;
    for (int i = 0; i < 9 && !has_tool[i]; i++) {
     mvwprintz(w_con, posy, posx-2, c_white, ">");
     for (int j = 0; j < stage.tools[i].size(); j++) {
      itype_id tool = stage.tools[i][j].type;
      nc_color col = c_red;
      if (total_inv.has_amount(tool, 1)) {
       has_tool[i] = true;
       col = c_green;
      }
      int length = item_controller->find_template(tool)->name.length();
      if (posx + length > 79) {
       posy++;
       posx = 33;
      }
      mvwprintz(w_con, posy, posx, col, item_controller->find_template(tool)->name.c_str());
      posx += length + 1; // + 1 for an empty space
      if (j < stage.tools[i].size() - 1) { // "OR" if there's more
       if (posx > 77) {
        posy++;
        posx = 33;
       }
       mvwprintz(w_con, posy, posx, c_white, "OR");
       posx += 3;
      }
     }
     posy += 2;
     posx = 33;
    }
// Print components
    posx = 33;
    bool has_component[10] = {stage.components[0].empty(),
                              stage.components[1].empty(),
                              stage.components[2].empty(),
                              stage.components[3].empty(),
                              stage.components[4].empty(),
                              stage.components[5].empty(),
                              stage.components[6].empty(),
                              stage.components[7].empty(),
                              stage.components[8].empty(),
                              stage.components[9].empty()};
    for (int i = 0; i < 10; i++) {
     if (has_component[i])
       continue;
     mvwprintz(w_con, posy, posx-2, c_white, ">");
     for (int j = 0; j < stage.components[i].size() && i < 10; j++) {
      nc_color col = c_red;
      component comp = stage.components[i][j];
      if (( item_controller->find_template(comp.type)->is_ammo() &&
           total_inv.has_charges(comp.type, comp.count)) ||
          (!item_controller->find_template(comp.type)->is_ammo() &&
           total_inv.has_amount(comp.type, comp.count))) {
       has_component[i] = true;
       col = c_green;
      }
      int length = item_controller->find_template(comp.type)->name.length();
      if (posx + length > 79) {
       posy++;
       posx = 33;
      }
      mvwprintz(w_con, posy, posx, col, "%s x%d",
                item_controller->find_template(comp.type)->name.c_str(), comp.count);
      posx += length + 3; // + 2 for " x", + 1 for an empty space
// Add more space for the length of the count
      if (comp.count < 10)
       posx++;
      else if (comp.count < 100)
       posx += 2;
      else
       posx += 3;

      if (j < stage.components[i].size() - 1) { // "OR" if there's more
       if (posx > 77) {
        posy++;
        posx = 33;
       }
       mvwprintz(w_con, posy, posx, c_white, "OR");
       posx += 3;
      }
     }
     posx = 33;
     posy += 2;
    }
   }
   wrefresh(w_con);
  } // Finished updating

  ch = getch();
  switch (ch) {
   case KEY_DOWN:
    update_info = true;
    if (select < constructions.size() - 1)
     select++;
    else
     select = 0;
    break;
   case KEY_UP:
    update_info = true;
    if (select > 0)
     select--;
    else
     select = constructions.size() - 1;
    break;
   case ' ':
   case KEY_ESCAPE:
   case 'q':
   case 'Q':
    exit = true;
    break;
   case '\n':
   default:
    if (ch > 64 && ch < 91) //A-Z
     chosen = ch - 65 + 26;

    else if (ch > 96 && ch < 123) //a-z
     chosen = ch - 97;

    else if (ch == '\n')
     chosen = select;

    if (chosen < constructions.size()) {
     if (player_can_build(u, total_inv, constructions[chosen])) {
      place_construction(constructions[chosen]);
      exit = true;
     } else {
      popup("You can't build that!");
      select = chosen;
      for (int i = 1; i < iMaxY-1; i++)
       mvwputch(w_con, i, 30, c_ltgray, LINE_XOXO);
      update_info = true;
     }
    }
    break;
  }
 } while (!exit);

 for (int i = iMaxY-25; i < iMaxY+1; i++) {
  for (int j = TERRAIN_WINDOW_WIDTH; j < 81; j++)
   mvwputch(w_con, i, j, c_black, ' ');
 }

 wrefresh(w_con);
 refresh_all();
}
Beispiel #25
0
int worldfactory::show_worldgen_tab_modselection(WINDOW *win, WORLDPTR world)
{
    // Use active_mod_order of the world,
    // saves us from writing 'world->active_mod_order' all the time.
    std::vector<std::string> &active_mod_order = world->active_mod_order;
    {
        std::vector<std::string> tmp_mod_order;
        // clear active_mod_order and re-add all the mods, his ensures
        // that changes (like changing dependencies) get updated
        tmp_mod_order.swap(active_mod_order);
        for( auto &elem : tmp_mod_order ) {
            mman_ui->try_add( elem, active_mod_order );
        }
    }

    input_context ctxt("MODMANAGER_DIALOG");
    ctxt.register_updown();
    ctxt.register_action("LEFT", _("Switch to other list"));
    ctxt.register_action("RIGHT", _("Switch to other list"));
    ctxt.register_action("HELP_KEYBINDINGS");
    ctxt.register_action("QUIT");
    ctxt.register_action("NEXT_TAB");
    ctxt.register_action("PREV_TAB");
    ctxt.register_action("CONFIRM", _("Activate / deactive mod"));
    ctxt.register_action("ADD_MOD");
    ctxt.register_action("REMOVE_MOD");
    ctxt.register_action("SAVE_DEFAULT_MODS");

    const int iOffsetX = (TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0;
    const int iOffsetY = (TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0;

    // lots of small windows so that each section can be drawn to independently of the others as necessary
    WINDOW *w_header1, *w_header2, *w_shift, *w_list, *w_active, *w_description;
    w_header1 = newwin(1, FULL_SCREEN_WIDTH / 2 - 5, 3 + iOffsetY, 1 + iOffsetX);
    w_header2 = newwin(1, FULL_SCREEN_WIDTH / 2 - 4, 3 + iOffsetY,
                       FULL_SCREEN_WIDTH / 2 + 3 + iOffsetX);
    w_shift   = newwin(13, 5, 3 + iOffsetY, FULL_SCREEN_WIDTH / 2 - 3 + iOffsetX);
    w_list    = newwin(11, FULL_SCREEN_WIDTH / 2 - 4, 5 + iOffsetY, iOffsetX);
    w_active  = newwin(11, FULL_SCREEN_WIDTH / 2 - 4, 5 + iOffsetY,
                       FULL_SCREEN_WIDTH / 2 + 2 + iOffsetX);
    w_description = newwin(4, FULL_SCREEN_WIDTH - 2, 19 + iOffsetY, 1 + iOffsetX);

    draw_modselection_borders(win, &ctxt);
    std::vector<std::string> headers;
    headers.push_back(_("Mod List"));
    headers.push_back(_("Mod Load Order"));
    std::vector<WINDOW *> header_windows;
    header_windows.push_back(w_header1);
    header_windows.push_back(w_header2);

    int tab_output = 0;
    int last_active_header = 0;
    size_t active_header = 0;
    size_t useable_mod_count = mman_ui->usable_mods.size();
    int startsel[2] = {0, 0};
    int cursel[2] = {0, 0};

    bool redraw_headers = true;
    bool redraw_shift = true;
    bool redraw_description = true;
    bool redraw_list = true;
    bool redraw_active = true;
    bool selection_changed = false;

    while (tab_output == 0) {
        if (redraw_headers) {
            for (size_t i = 0; i < headers.size(); ++i) {
                werase(header_windows[i]);
                const int header_x = (getmaxx(header_windows[i]) - headers[i].size()) / 2;
                mvwprintz(header_windows[i], 0, header_x , c_cyan, "%s", headers[i].c_str());

                if (active_header == i) {
                    mvwputch(header_windows[i], 0, header_x - 3, c_red, '<');
                    mvwputch(header_windows[i], 0, header_x + headers[i].size() + 2, c_red, '>');
                }
                wrefresh(header_windows[i]);
            }
            redraw_list = true;
            redraw_active = true;
            redraw_shift = true;
            redraw_headers = false;
        }
        if (selection_changed) {
            if (active_header == 0) {
                redraw_list = true;
            }
            if (active_header == 1) {
                redraw_shift = true;
                redraw_active = true;
            }
            selection_changed = false;
            redraw_description = true;
        }
        if (redraw_description) {
            werase(w_description);

            MOD_INFORMATION *selmod = NULL;
            if (mman_ui->usable_mods.empty()) {
                // Do nothing, leave selmod == NULL
            } else if (active_header == 0) {
                selmod = mman->mod_map[mman_ui->usable_mods[cursel[0]]];
            } else if (!active_mod_order.empty()) {
                selmod = mman->mod_map[active_mod_order[cursel[1]]];
            }

            if (selmod != NULL) {
                fold_and_print(w_description, 0, 1, getmaxx(w_description) - 1,
                               c_white, mman_ui->get_information(selmod));
            }
            redraw_description = false;
            wrefresh(w_description);
        }
        if (redraw_list) {
            draw_mod_list( w_list, startsel[0], cursel[0], mman_ui->usable_mods, active_header == 0, _("--NO AVAILABLE MODS--") );
        }
        if (redraw_active) {
            draw_mod_list( w_active, startsel[1], cursel[1], active_mod_order, active_header == 1, _("--NO ACTIVE MODS--") );
        }
        if (redraw_shift) {
            werase(w_shift);
            if (active_header == 1) {
                std::stringstream shift_display;
                // get shift information for whatever is visible in the active list
                for (size_t i = startsel[1], c = 0; i < active_mod_order.size() &&
                     (int)c < getmaxy(w_active); ++i, ++c) {
                    if (mman_ui->can_shift_up(i, active_mod_order)) {
                        shift_display << "<color_blue>+</color> ";
                    } else {
                        shift_display << "<color_dkgray>+</color> ";
                    }
                    if (mman_ui->can_shift_down(i, active_mod_order)) {
                        shift_display << "<color_blue>-</color>";
                    } else {
                        shift_display << "<color_dkgray>-</color>";
                    }
                    shift_display << "\n";
                }
                fold_and_print(w_shift, 2, 1, getmaxx(w_shift), c_white, shift_display.str());
            }
            redraw_shift = false;
            wrefresh(w_shift);
        }
        refresh();

        last_active_header = active_header;
        const int next_header = (active_header == 1) ? 0 : 1;
        const int prev_header = (active_header == 0) ? 1 : 0;

        int selection = (active_header == 0) ? cursel[0] : cursel[1];
        int last_selection = selection;
        unsigned int next_selection = selection + 1;
        int prev_selection = selection - 1;
        if (active_header == 0) {
            next_selection = (next_selection >= useable_mod_count) ? 0 : next_selection;
            prev_selection = (prev_selection < 0) ? useable_mod_count - 1 : prev_selection;
        } else {
            next_selection = (next_selection >= active_mod_order.size()) ? 0 : next_selection;
            prev_selection = (prev_selection < 0) ? active_mod_order.size() - 1 : prev_selection;
        }

        const std::string action = ctxt.handle_input();

        if (action == "DOWN") {
            selection = next_selection;
        } else if (action == "UP") {
            selection = prev_selection;
        } else if (action == "RIGHT") {
            active_header = next_header;
        } else if (action == "LEFT") {
            active_header = prev_header;
        } else if (action == "CONFIRM") {
            if (active_header == 0 && !mman_ui->usable_mods.empty()) {
#ifndef LUA
                if (mman->mod_map[mman_ui->usable_mods[cursel[0]]]->need_lua) {
                    popup(_("Can't add mod. This mod requires Lua support."));
                    redraw_active = true;
                    redraw_shift = true;
                    draw_modselection_borders(win, &ctxt);
                    continue;
                }
#endif
                // try-add
                mman_ui->try_add(mman_ui->usable_mods[cursel[0]], active_mod_order);
                redraw_active = true;
                redraw_shift = true;
            } else if (active_header == 1 && !active_mod_order.empty()) {
                // try-rem
                mman_ui->try_rem(cursel[1], active_mod_order);
                redraw_active = true;
                redraw_shift = true;
                if (active_mod_order.empty()) {
                    // switch back to other list, we can't change
                    // anything in the empty active mods list.
                    active_header = 0;
                }
            }
        } else if (action == "ADD_MOD") {
            if (active_header == 1 && active_mod_order.size() > 1) {
                mman_ui->try_shift('+', cursel[1], active_mod_order);
                redraw_active = true;
                redraw_shift = true;
            }
        } else if (action == "REMOVE_MOD") {
            if (active_header == 1 && active_mod_order.size() > 1) {
                mman_ui->try_shift('-', cursel[1], active_mod_order);
                redraw_active = true;
                redraw_shift = true;
            }
        } else if (action == "NEXT_TAB") {
            tab_output = 1;
        } else if (action == "PREV_TAB") {
            tab_output = -1;
        } else if (action == "SAVE_DEFAULT_MODS") {
            if(mman->set_default_mods(active_mod_order)) {
                popup(_("Saved list of active mods as default"));
                draw_modselection_borders(win, &ctxt);
                redraw_headers = true;
            }
        } else if (action == "HELP_KEYBINDINGS") {
            // Redraw all the things!
            redraw_headers = true;
            redraw_shift = true;
            redraw_description = true;
            redraw_list = true;
            redraw_active = true;
            draw_worldgen_tabs( win, 0 );
            draw_modselection_borders( win, &ctxt );
        } else if (action == "QUIT") {
            tab_output = -999;
        }
        // RESOLVE INPUTS
        if (last_active_header != (int)active_header) {
            redraw_headers = true;
            redraw_shift = true;
            redraw_description = true;
        }
        if (last_selection != selection) {
            if (active_header == 0) {
                redraw_list = true;
                cursel[0] = selection;
            } else {
                redraw_active = true;
                redraw_shift = true;
                cursel[1] = selection;
            }
            redraw_description = true;
        }
        if (active_mod_order.empty()) {
            redraw_active = true;
            cursel[1] = 0;
        }

        if (active_header == 1) {
            if (active_mod_order.empty()) {
                cursel[1] = 0;
            } else {
                if (cursel[1] < 0) {
                    cursel[1] = 0;
                } else if (cursel[1] >= (int)active_mod_order.size()) {
                    cursel[1] = active_mod_order.size() - 1;
                }
            }
        }
        // end RESOLVE INPUTS
    }
    werase(w_header1);
    werase(w_header2);
    werase(w_shift);
    werase(w_list);
    werase(w_active);
    werase(w_description);

    delwin(w_header1);
    delwin(w_header2);
    delwin(w_shift);
    delwin(w_list);
    delwin(w_active);
    delwin(w_description);
    return tab_output;
}
Beispiel #26
0
bool player::install_bionics(game *g, it_bionic* type)
{
 if (type == NULL) {
  debugmsg("Tried to install NULL bionic");
  return false;
 }
 std::string bio_name = type->name.substr(5);	// Strip off "CBM: "
 WINDOW* w = newwin(25, 80, 0, 0);

 int pl_skill = int_cur +
   skillLevel("electronics").level() * 4 +
   skillLevel("firstaid").level()    * 3 +
   skillLevel("mechanics").level()   * 2;

 int skint = int(pl_skill / 4);
 int skdec = int((pl_skill * 10) / 4) % 10;

// Header text
 mvwprintz(w, 0,  0, c_white, "Installing bionics:");
 mvwprintz(w, 0, 20, type->color, bio_name.c_str());

// Dividing bars
 for (int i = 0; i < 80; i++) {
  mvwputch(w,  1, i, c_ltgray, LINE_OXOX);
  mvwputch(w, 21, i, c_ltgray, LINE_OXOX);
 }
// Init the list of bionics
 for (unsigned int i = 1; i < type->options.size(); i++) {
  bionic_id id = type->options[i];
  mvwprintz(w, i + 2, 0, (has_bionic(id) ? c_ltred : c_ltblue),
            bionics[id].name.c_str());
 }
// Helper text
 mvwprintz(w, 2, 40, c_white,        "Difficulty of this module: %d",
           type->difficulty);
 mvwprintz(w, 3, 40, c_white,        "Your installation skill:   %d.%d",
           skint, skdec);
 mvwprintz(w, 4, 40, c_white,       "Installation requires high intelligence,");
 mvwprintz(w, 5, 40, c_white,       "and skill in electronics, first aid, and");
 mvwprintz(w, 6, 40, c_white,       "mechanics (in that order of importance).");

 int chance_of_success = int((100 * pl_skill) /
                             (pl_skill + 4 * type->difficulty));

 mvwprintz(w, 8, 40, c_white,        "Chance of success:");

 nc_color col_suc;
 if (chance_of_success >= 95)
  col_suc = c_green;
 else if (chance_of_success >= 80)
  col_suc = c_ltgreen;
 else if (chance_of_success >= 60)
  col_suc = c_yellow;
 else if (chance_of_success >= 35)
  col_suc = c_ltred;
 else
  col_suc = c_red;

 mvwprintz(w, 8, 59, col_suc, "%d%%%%", chance_of_success);

 mvwprintz(w, 10, 40, c_white,       "Failure may result in crippling damage,");
 mvwprintz(w, 11, 40, c_white,       "loss of existing bionics, genetic damage");
 mvwprintz(w, 12, 40, c_white,       "or faulty installation.");
 wrefresh(w);

 if (type->id == itm_bionics_battery) {	// No selection list; just confirm
  mvwprintz(w,  2, 0, h_ltblue, "Battery Level +%d", BATTERY_AMOUNT);
  mvwprintz(w, 22, 0, c_ltblue, "\
Installing this bionic will increase your total battery capacity by %d.\n\
Batteries are necessary for most bionics to function.  They also require a\n\
charge mechanism, which must be installed from another CBM.", BATTERY_AMOUNT);
  char ch;
  wrefresh(w);
  do
   ch = getch();
  while (ch != 'q' && ch != '\n' && ch != KEY_ESCAPE);
  if (ch == '\n') {
   practice("electronics", (100 - chance_of_success) * 1.5);
   practice("firstaid", (100 - chance_of_success) * 1.0);
   practice("mechanics", (100 - chance_of_success) * 0.5);
   int success = chance_of_success - rng(1, 100);
   if (success > 0) {
    g->add_msg("Successfully installed batteries.");
    max_power_level += BATTERY_AMOUNT;
   } else
    bionics_install_failure(g, this, success);
   werase(w);
   delwin(w);
   g->refresh_all();
   return true;
  }
  werase(w);
  delwin(w);
  g->refresh_all();
  return false;
 }
Beispiel #27
0
void draw_tabs(WINDOW *w, int active_tab, ...)
{
 int win_width;
 win_width = getmaxx(w);
 std::vector<std::string> labels;
 va_list ap;
 va_start(ap, active_tab);
 char *tmp;
 while (tmp = (char *)va_arg(ap, char*))
  labels.push_back((std::string)(tmp));
 va_end(ap);

// Draw the line under the tabs
 for (int x = 0; x < win_width; x++)
  mvwputch(w, 2, x, c_white, LINE_OXOX);

 int total_width = 0;
 for (int i = 0; i < labels.size(); i++)
  total_width += labels[i].length() + 6; // "< |four| >"

 if (total_width > win_width) {
  //debugmsg("draw_tabs not given enough space! %s", labels[0]);
  return;
 }

// Extra "buffer" space per each side of each tab
 double buffer_extra = (win_width - total_width) / (labels.size() * 2);
 int buffer = int(buffer_extra);
// Set buffer_extra to (0, 1); the "extra" whitespace that builds up
 buffer_extra = buffer_extra - buffer;
 int xpos = 0;
 double savings = 0;

 for (int i = 0; i < labels.size(); i++) {
  int length = labels[i].length();
  xpos += buffer + 2;
  savings += buffer_extra;
  if (savings > 1) {
   savings--;
   xpos++;
  }
  mvwputch(w, 0, xpos, c_white, LINE_OXXO);
  mvwputch(w, 1, xpos, c_white, LINE_XOXO);
  mvwputch(w, 0, xpos + length + 1, c_white, LINE_OOXX);
  mvwputch(w, 1, xpos + length + 1, c_white, LINE_XOXO);
  if (i == active_tab) {
   mvwputch(w, 1, xpos - 2, h_white, '<');
   mvwputch(w, 1, xpos + length + 3, h_white, '>');
   mvwputch(w, 2, xpos, c_white, LINE_XOOX);
   mvwputch(w, 2, xpos + length + 1, c_white, LINE_XXOO);
   mvwprintz(w, 1, xpos + 1, h_white, labels[i].c_str());
   for (int x = xpos + 1; x <= xpos + length; x++) {
    mvwputch(w, 0, x, c_white, LINE_OXOX);
    mvwputch(w, 2, x, c_black, 'x');
   }
  } else {
   mvwputch(w, 2, xpos, c_white, LINE_XXOX);
   mvwputch(w, 2, xpos + length + 1, c_white, LINE_XXOX);
   mvwprintz(w, 1, xpos + 1, c_white, labels[i].c_str());
   for (int x = xpos + 1; x <= xpos + length; x++)
    mvwputch(w, 0, x, c_white, LINE_OXOX);
  }
  xpos += length + 1 + buffer;
 }
}
Beispiel #28
0
const recipe *select_crafting_recipe( int &batch_size )
{
    if( normalized_names.empty() ) {
        translate_all();
    }

    const int headHeight = 3;
    const int subHeadHeight = 2;
    const int freeWidth = TERMX - FULL_SCREEN_WIDTH;
    bool isWide = ( TERMX > FULL_SCREEN_WIDTH && freeWidth > 15 );

    const int width = isWide ? ( freeWidth > FULL_SCREEN_WIDTH ? FULL_SCREEN_WIDTH * 2 : TERMX ) :
                      FULL_SCREEN_WIDTH;
    const int wStart = ( TERMX - width ) / 2;
    const int tailHeight = isWide ? 3 : 4;
    const int dataLines = TERMY - ( headHeight + subHeadHeight ) - tailHeight;
    const int dataHalfLines = dataLines / 2;
    const int dataHeight = TERMY - ( headHeight + subHeadHeight );
    const int infoWidth = width - FULL_SCREEN_WIDTH - 1;

    const recipe *last_recipe = nullptr;

    catacurses::window w_head = catacurses::newwin( headHeight, width, 0, wStart );
    catacurses::window w_subhead = catacurses::newwin( subHeadHeight, width, 3, wStart );
    catacurses::window w_data = catacurses::newwin( dataHeight, width, headHeight + subHeadHeight,
                                wStart );

    int item_info_x = infoWidth;
    int item_info_y = dataHeight - 3;
    int item_info_width = wStart + width - infoWidth;
    int item_info_height = headHeight + subHeadHeight;

    if( !isWide ) {
        item_info_x = 1;
        item_info_y = 1;
        item_info_width = 1;
        item_info_height = 1;
    }

    catacurses::window w_iteminfo = catacurses::newwin( item_info_y, item_info_x, item_info_height,
                                    item_info_width );

    list_circularizer<std::string> tab( craft_cat_list );
    list_circularizer<std::string> subtab( craft_subcat_list[tab.cur()] );
    std::vector<const recipe *> current;
    std::vector<bool> available;
    const int componentPrintHeight = dataHeight - tailHeight - 1;
    //preserves component color printout between mode rotations
    nc_color rotated_color = c_white;
    int previous_item_line = -1;
    std::string previous_tab;
    std::string previous_subtab;
    item tmp;
    int line = 0;
    int ypos = 0;
    int scroll_pos = 0;
    bool redraw = true;
    bool keepline = false;
    bool done = false;
    bool batch = false;
    bool show_hidden = false;
    int batch_line = 0;
    int display_mode = 0;
    const recipe *chosen = nullptr;
    std::vector<iteminfo> thisItem;
    std::vector<iteminfo> dummy;

    input_context ctxt( "CRAFTING" );
    ctxt.register_cardinal();
    ctxt.register_action( "QUIT" );
    ctxt.register_action( "CONFIRM" );
    ctxt.register_action( "CYCLE_MODE" );
    ctxt.register_action( "SCROLL_UP" );
    ctxt.register_action( "SCROLL_DOWN" );
    ctxt.register_action( "PREV_TAB" );
    ctxt.register_action( "NEXT_TAB" );
    ctxt.register_action( "FILTER" );
    ctxt.register_action( "RESET_FILTER" );
    ctxt.register_action( "TOGGLE_FAVORITE" );
    ctxt.register_action( "HELP_RECIPE" );
    ctxt.register_action( "HELP_KEYBINDINGS" );
    ctxt.register_action( "CYCLE_BATCH" );
    ctxt.register_action( "RELATED_RECIPES" );
    ctxt.register_action( "HIDE_SHOW_RECIPE" );

    const inventory &crafting_inv = g->u.crafting_inventory();
    const std::vector<npc *> helpers = g->u.get_crafting_helpers();
    std::string filterstring;

    const auto &available_recipes = g->u.get_available_recipes( crafting_inv, &helpers );
    std::map<const recipe *, bool> availability_cache;

    do {
        if( redraw ) {
            // When we switch tabs, redraw the header
            redraw = false;
            if( ! keepline ) {
                line = 0;
            } else {
                keepline = false;
            }

            if( display_mode > 2 ) {
                display_mode = 2;
            }

            TAB_MODE m = ( batch ) ? BATCH : ( filterstring.empty() ) ? NORMAL : FILTERED;
            draw_recipe_tabs( w_head, tab.cur(), m );
            draw_recipe_subtabs( w_subhead, tab.cur(), subtab.cur(), available_recipes, m );

            show_hidden = false;
            available.clear();

            if( batch ) {
                current.clear();
                for( int i = 1; i <= 20; i++ ) {
                    current.push_back( chosen );
                    available.push_back( chosen->requirements().can_make_with_inventory( crafting_inv, i ) );
                }
            } else {
                std::vector<const recipe *> picking;
                if( !filterstring.empty() ) {
                    auto qry = trim( filterstring );
                    if( qry.size() > 2 && qry[1] == ':' ) {
                        switch( qry[0] ) {
                            case 't':
                                picking = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::tool );
                                break;

                            case 'c':
                                picking = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::component );
                                break;

                            case 's':
                                picking = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::skill );
                                break;

                            case 'p':
                                picking = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::primary_skill );
                                break;

                            case 'Q':
                                picking = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::quality );
                                break;

                            case 'q':
                                picking = available_recipes.search( qry.substr( 2 ), recipe_subset::search_type::quality_result );
                                break;

                            case 'd':
                                picking = available_recipes.search( qry.substr( 2 ),
                                                                    recipe_subset::search_type::description_result );
                                break;

                            case 'm': {
                                auto &learned = g->u.get_learned_recipes();
                                if( query_is_yes( qry ) ) {
                                    std::set_intersection( available_recipes.begin(), available_recipes.end(), learned.begin(),
                                                           learned.end(), std::back_inserter( picking ) );
                                } else {
                                    std::set_difference( available_recipes.begin(), available_recipes.end(), learned.begin(),
                                                         learned.end(),
                                                         std::back_inserter( picking ) );
                                }
                                break;
                            }

                            case 'h': {
                                std::copy( available_recipes.begin(), available_recipes.end(), std::back_inserter( picking ) );
                                if( query_is_yes( qry ) ) {
                                    show_hidden = true;
                                }
                                break;
                            }

                            default:
                                current.clear();
                        }
                    } else {
                        picking = available_recipes.search( qry );
                    }
                } else if( subtab.cur() == "CSC_*_FAVORITE" ) {
                    picking = available_recipes.favorite();
                } else if( subtab.cur() == "CSC_*_RECENT" ) {
                    picking = available_recipes.recent();
                } else {
                    picking = available_recipes.in_category( tab.cur(), subtab.cur() != "CSC_ALL" ? subtab.cur() : "" );
                }

                current.clear();
                for( auto i : picking ) {
                    if( ( uistate.hidden_recipes.find( i->ident() ) != uistate.hidden_recipes.end() ) == show_hidden ) {
                        current.push_back( i );
                    }
                }
                if( !show_hidden ) {
                    draw_hidden_amount( w_head, 0, picking.size() - current.size() );
                }

                available.reserve( current.size() );
                // cache recipe availability on first display
                for( const auto e : current ) {
                    if( !availability_cache.count( e ) ) {
                        availability_cache.emplace( e, e->requirements().can_make_with_inventory( crafting_inv ) );
                    }
                }

                if( subtab.cur() != "CSC_*_RECENT" ) {
                    std::stable_sort( current.begin(), current.end(), []( const recipe * a, const recipe * b ) {
                        return b->difficulty < a->difficulty;
                    } );

                    std::stable_sort( current.begin(), current.end(), [&]( const recipe * a, const recipe * b ) {
                        return availability_cache[a] && !availability_cache[b];
                    } );
                }

                std::transform( current.begin(), current.end(),
                std::back_inserter( available ), [&]( const recipe * e ) {
                    return availability_cache[e];
                } );
            }

            // current/available have been rebuilt, make sure our cursor is still in range
            if( current.empty() ) {
                line = 0;
            } else {
                line = std::min( line, static_cast<int>( current.size() ) - 1 );
            }
        }

        // Clear the screen of recipe data, and draw it anew
        werase( w_data );

        if( isWide ) {
            werase( w_iteminfo );
        }

        if( isWide ) {
            mvwprintz( w_data, dataLines + 1, 5, c_white,
                       _( "Press <ENTER> to attempt to craft object." ) );
            wprintz( w_data, c_white, "  " );
            if( !filterstring.empty() ) {
                wprintz( w_data, c_white,
                         _( "[E]: Describe, [F]ind, [R]eset, [m]ode, [s]how/hide, Re[L]ated, [*]Favorite, %s [?] keybindings" ),
                         ( batch ) ? _( "cancel [b]atch" ) : _( "[b]atch" ) );
            } else {
                wprintz( w_data, c_white,
                         _( "[E]: Describe, [F]ind, [m]ode, [s]how/hide, Re[L]ated, [*]Favorite, %s [?] keybindings" ),
                         ( batch ) ? _( "cancel [b]atch" ) : _( "[b]atch" ) );
            }
        } else {
            if( !filterstring.empty() ) {
                mvwprintz( w_data, dataLines + 1, 5, c_white,
                           _( "[E]: Describe, [F]ind, [R]eset, [m]ode, [s]how/hide, Re[L]ated, [*]Favorite, [b]atch [?] keybindings" ) );
            } else {
                mvwprintz( w_data, dataLines + 1, 5, c_white,
                           _( "[E]: Describe, [F]ind, [m]ode, [s]how/hide, Re[L]ated, [*]Favorite, [b]atch [?] keybindings" ) );
            }
            mvwprintz( w_data, dataLines + 2, 5, c_white,
                       _( "Press <ENTER> to attempt to craft object." ) );
        }
        // Draw borders
        for( int i = 1; i < width - 1; ++i ) { // _
            mvwputch( w_data, dataHeight - 1, i, BORDER_COLOR, LINE_OXOX );
        }
        for( int i = 0; i < dataHeight - 1; ++i ) { // |
            mvwputch( w_data, i, 0, BORDER_COLOR, LINE_XOXO );
            mvwputch( w_data, i, width - 1, BORDER_COLOR, LINE_XOXO );
        }
        mvwputch( w_data, dataHeight - 1,  0, BORDER_COLOR, LINE_XXOO ); // _|
        mvwputch( w_data, dataHeight - 1, width - 1, BORDER_COLOR, LINE_XOOX ); // |_

        int recmin = 0, recmax = current.size();
        if( recmax > dataLines ) {
            if( line <= recmin + dataHalfLines ) {
                for( int i = recmin; i < recmin + dataLines; ++i ) {
                    std::string tmp_name = current[i]->result_name();
                    if( batch ) {
                        tmp_name = string_format( _( "%2dx %s" ), i + 1, tmp_name.c_str() );
                    }
                    mvwprintz( w_data, i - recmin, 2, c_dark_gray, "" ); // Clear the line
                    if( i == line ) {
                        mvwprintz( w_data, i - recmin, 2, ( available[i] ? h_white : h_dark_gray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    } else {
                        mvwprintz( w_data, i - recmin, 2, ( available[i] ? c_white : c_dark_gray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    }
                }
            } else if( line >= recmax - dataHalfLines ) {
                for( int i = recmax - dataLines; i < recmax; ++i ) {
                    std::string tmp_name = current[i]->result_name();
                    if( batch ) {
                        tmp_name = string_format( _( "%2dx %s" ), i + 1, tmp_name.c_str() );
                    }
                    mvwprintz( w_data, dataLines + i - recmax, 2, c_light_gray, "" ); // Clear the line
                    if( i == line ) {
                        mvwprintz( w_data, dataLines + i - recmax, 2,
                                   ( available[i] ? h_white : h_dark_gray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    } else {
                        mvwprintz( w_data, dataLines + i - recmax, 2,
                                   ( available[i] ? c_white : c_dark_gray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    }
                }
            } else {
                for( int i = line - dataHalfLines; i < line - dataHalfLines + dataLines; ++i ) {
                    std::string tmp_name = current[i]->result_name();
                    if( batch ) {
                        tmp_name = string_format( _( "%2dx %s" ), i + 1, tmp_name.c_str() );
                    }
                    mvwprintz( w_data, dataHalfLines + i - line, 2, c_light_gray, "" ); // Clear the line
                    if( i == line ) {
                        mvwprintz( w_data, dataHalfLines + i - line, 2,
                                   ( available[i] ? h_white : h_dark_gray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    } else {
                        mvwprintz( w_data, dataHalfLines + i - line, 2,
                                   ( available[i] ? c_white : c_dark_gray ),
                                   utf8_truncate( tmp_name, 28 ).c_str() );
                    }
                }
            }
        } else {
            for( size_t i = 0; i < current.size() && i < static_cast<size_t>( dataHeight ) + 1; ++i ) {
                std::string tmp_name = current[i]->result_name();
                if( batch ) {
                    tmp_name = string_format( _( "%2dx %s" ), static_cast<int>( i ) + 1, tmp_name.c_str() );
                }
                if( static_cast<int>( i ) == line ) {
                    mvwprintz( w_data, i, 2, ( available[i] ? h_white : h_dark_gray ),
                               utf8_truncate( tmp_name, 28 ).c_str() );
                } else {
                    mvwprintz( w_data, i, 2, ( available[i] ? c_white : c_dark_gray ),
                               utf8_truncate( tmp_name, 28 ).c_str() );
                }
            }
        }

        if( !current.empty() ) {
            int pane = FULL_SCREEN_WIDTH - 30 - 1;
            int count = batch ? line + 1 : 1; // batch size
            nc_color col = available[ line ] ? c_white : c_light_gray;

            const auto &req = current[ line ]->requirements();

            draw_can_craft_indicator( w_head, 0, *current[line] );
            wrefresh( w_head );

            ypos = 0;

            auto qry = trim( filterstring );
            std::string qry_comps;
            if( qry.compare( 0, 2, "c:" ) == 0 ) {
                qry_comps = qry.substr( 2 );
            }

            std::vector<std::string> component_print_buffer;
            auto tools = req.get_folded_tools_list( pane, col, crafting_inv, count );
            auto comps = req.get_folded_components_list( pane, col, crafting_inv, count, qry_comps );
            component_print_buffer.insert( component_print_buffer.end(), tools.begin(), tools.end() );
            component_print_buffer.insert( component_print_buffer.end(), comps.begin(), comps.end() );

            if( !g->u.knows_recipe( current[line] ) ) {
                component_print_buffer.push_back( _( "Recipe not memorized yet" ) );
                auto books_with_recipe = g->u.get_books_for_recipe( crafting_inv, current[line] );
                std::string enumerated_books =
                    enumerate_as_string( books_with_recipe.begin(), books_with_recipe.end(),
                []( itype_id type_id ) {
                    return item::find_type( type_id )->nname( 1 );
                } );
                const std::string text = string_format( _( "Written in: %s" ), enumerated_books.c_str() );
                std::vector<std::string> folded_lines = foldstring( text, pane );
                component_print_buffer.insert(
                    component_print_buffer.end(), folded_lines.begin(), folded_lines.end() );
            }

            //handle positioning of component list if it needed to be scrolled
            int componentPrintOffset = 0;
            if( display_mode > 2 ) {
                componentPrintOffset = ( display_mode - 2 ) * componentPrintHeight;
            }
            if( component_print_buffer.size() < static_cast<size_t>( componentPrintOffset ) ) {
                componentPrintOffset = 0;
                if( previous_tab != tab.cur() || previous_subtab != subtab.cur() || previous_item_line != line ) {
                    display_mode = 2;
                } else {
                    display_mode = 0;
                }
            }

            //only used to preserve mode position on components when
            //moving to another item and the view is already scrolled
            previous_tab = tab.cur();
            previous_subtab = subtab.cur();
            previous_item_line = line;
            const int xpos = 30;

            if( display_mode == 0 ) {
                const int width = getmaxx( w_data ) - xpos - item_info_x;
                print_colored_text(
                    w_data, ypos++, xpos, col, col,
                    string_format( _( "Primary skill used: <color_cyan>%s</color>" ),
                                   ( !current[line]->skill_used ? _( "N/A" ) :
                                     current[line]->skill_used.obj().name() ) ) );
                auto player_skill = g->u.get_skill_level( current[line]->skill_used );
                std::string difficulty_color =
                    current[ line ]->difficulty > player_skill ? "yellow" : "green";
                print_colored_text(
                    w_data, ypos++, xpos, col, col,
                    string_format( _( "Difficulty: <color_%s>%d</color>" ),
                                   difficulty_color, current[ line ]->difficulty ) );
                std::string skill_level_string =
                    current[line]->skill_used ?
                    string_format( _( "Your skill level: <color_%s>%d</color>" ),
                                   difficulty_color, player_skill ) :
                    _( "Your skill level: <color_yellow>N/A</color>" );
                print_colored_text( w_data, ypos++, xpos, col, col, skill_level_string );
                ypos += fold_and_print( w_data, ypos, xpos, width, col,
                                        _( "Other skills used: %s" ),
                                        current[line]->required_skills_string( &g->u ) );

                const int expected_turns = g->u.expected_time_to_craft( *current[line],
                                           count ) / to_moves<int>( 1_turns );
                ypos += fold_and_print( w_data, ypos, xpos, pane, col,
                                        _( "Time to complete: <color_cyan>%s</color>" ),
                                        to_string( time_duration::from_turns( expected_turns ) ) );

                print_colored_text(
                    w_data, ypos++, xpos, col, col,
                    string_format( _( "Dark craftable? <color_cyan>%s</color>" ),
                                   current[line]->has_flag( "BLIND_EASY" ) ? _( "Easy" ) :
                                   current[line]->has_flag( "BLIND_HARD" ) ? _( "Hard" ) :
                                   _( "Impossible" ) ) );
                ypos += print_items( *current[line], w_data, ypos, xpos, col, batch ? line + 1 : 1 );
            }

            //color needs to be preserved in case part of the previous page was cut off
            nc_color stored_color = col;
            if( display_mode > 2 ) {
                stored_color = rotated_color;
            } else {
                rotated_color = col;
            }
            int components_printed = 0;
            for( size_t i = static_cast<size_t>( componentPrintOffset );
                 i < component_print_buffer.size(); i++ ) {
                if( ypos >= componentPrintHeight ) {
                    break;
                }

                components_printed++;
                print_colored_text( w_data, ypos++, xpos, stored_color, col, component_print_buffer[i] );
            }

            if( ypos >= componentPrintHeight &&
                component_print_buffer.size() > static_cast<size_t>( components_printed ) ) {
                mvwprintz( w_data, ypos++, xpos, col, _( "v (more)" ) );
                rotated_color = stored_color;
            }

            if( isWide ) {
                if( last_recipe != current[line] ) {
                    last_recipe = current[line];
                    tmp = current[line]->create_result();
                }
                tmp.info( true, thisItem, count );
                draw_item_info( w_iteminfo, tmp.tname(), tmp.type_name(), thisItem, dummy,
                                scroll_pos, true, true, true, false, true );
            }
        }

        draw_scrollbar( w_data, line, dataLines, recmax, 0 );
        wrefresh( w_data );

        if( isWide ) {
            wrefresh( w_iteminfo );
        }

        const std::string action = ctxt.handle_input();
        if( action == "CYCLE_MODE" ) {
            display_mode = display_mode + 1;
            if( display_mode <= 0 ) {
                display_mode = 0;
            }
        } else if( action == "LEFT" ) {
            std::string start = subtab.cur();
            do {
                subtab.prev();
            } while( subtab.cur() != start && available_recipes.empty_category( tab.cur(),
                     subtab.cur() != "CSC_ALL" ? subtab.cur() : "" ) );
            redraw = true;
        } else if( action == "SCROLL_UP" ) {
            scroll_pos--;
        } else if( action == "SCROLL_DOWN" ) {
            scroll_pos++;
        } else if( action == "PREV_TAB" ) {
            tab.prev();
            subtab = list_circularizer<std::string>( craft_subcat_list[tab.cur()] );//default ALL
            redraw = true;
        } else if( action == "RIGHT" ) {
            std::string start = subtab.cur();
            do {
                subtab.next();
            } while( subtab.cur() != start && available_recipes.empty_category( tab.cur(),
                     subtab.cur() != "CSC_ALL" ? subtab.cur() : "" ) );
            redraw = true;
        } else if( action == "NEXT_TAB" ) {
            tab.next();
            subtab = list_circularizer<std::string>( craft_subcat_list[tab.cur()] );//default ALL
            redraw = true;
        } else if( action == "DOWN" ) {
            line++;
        } else if( action == "UP" ) {
            line--;
        } else if( action == "CONFIRM" ) {
            if( available.empty() || !available[line] ) {
                popup( _( "You can't do that!" ) );
            } else if( !g->u.check_eligible_containers_for_crafting( *current[line],
                       ( batch ) ? line + 1 : 1 ) ) {
                // popup is already inside check
            } else {
                chosen = current[line];
                batch_size = ( batch ) ? line + 1 : 1;
                done = true;
            }
        } else if( action == "HELP_RECIPE" ) {
            if( current.empty() ) {
                popup( _( "Nothing selected!" ) );
                redraw = true;
                continue;
            }
            tmp = current[line]->create_result();

            full_screen_popup( "%s\n%s", tmp.type_name( 1 ).c_str(),  tmp.info( true ).c_str() );
            redraw = true;
            keepline = true;
        } else if( action == "FILTER" ) {
            struct SearchPrefix {
                char key;
                std::string example;
                std::string description;
            };
            std::vector<SearchPrefix> prefixes = {
                { 'q', _( "metal sawing" ), _( "<color_cyan>quality</color> of resulting item" ) },
                //~ Example result description search term
                { 'd', _( "reach attack" ), _( "<color_cyan>full description</color> of resulting item (slow)" ) },
                { 'c', _( "two by four" ), _( "<color_cyan>component</color> required to craft" ) },
                { 'p', _( "tailoring" ), _( "<color_cyan>primary skill</color> used to craft" ) },
                { 's', _( "cooking" ), _( "<color_cyan>any skill</color> used to craft" ) },
                { 'Q', _( "fine bolt turning" ), _( "<color_cyan>quality</color> required to craft" ) },
                { 't', _( "soldering iron" ), _( "<color_cyan>tool</color> required to craft" ) },
                { 'h', _( "yes" ), _( "recipes which are <color_cyan>hidden</color> or not" ) },
                { 'm', _( "no" ), _( "recipes which are <color_cyan>memorized</color> or not" ) },
            };
            int max_example_length = 0;
            for( const auto &prefix : prefixes ) {
                max_example_length = std::max( max_example_length, utf8_width( prefix.example ) );
            }
            std::string spaces( max_example_length, ' ' );

            std::string description =
                _( "The default is to search result names.  Some single-character prefixes "
                   "can be used with a colon (:) to search in other ways.\n"
                   "\n"
                   "<color_white>Examples:</color>\n" );

            {
                std::string example_name = _( "shirt" );
                auto padding = max_example_length - utf8_width( example_name );
                description += string_format(
                                   _( "  <color_white>%s</color>%.*s    %s\n" ),
                                   example_name, padding, spaces,
                                   _( "<color_cyan>name</color> of resulting item" ) );
            }

            for( const auto &prefix : prefixes ) {
                auto padding = max_example_length - utf8_width( prefix.example );
                description += string_format(
                                   _( "  <color_yellow>%c</color><color_white>:%s</color>%.*s  %s\n" ),
                                   prefix.key, prefix.example, padding, spaces, prefix.description );
            }

            string_input_popup()
            .title( _( "Search:" ) )
            .width( 85 )
            .description( description )
            .desc_color( c_light_gray )
            .edit( filterstring );
            redraw = true;
        } else if( action == "QUIT" ) {
            chosen = nullptr;
            done = true;
        } else if( action == "RESET_FILTER" ) {
            filterstring.clear();
            redraw = true;
        } else if( action == "CYCLE_BATCH" ) {
            if( current.empty() ) {
                popup( _( "Nothing selected!" ) );
                redraw = true;
                continue;
            }
            batch = !batch;
            if( batch ) {
                batch_line = line;
                chosen = current[batch_line];
            } else {
                line = batch_line;
                keepline = true;
            }
            redraw = true;
        } else if( action == "TOGGLE_FAVORITE" ) {
            keepline = true;
            redraw = true;
            if( current.empty() ) {
                popup( _( "Nothing selected!" ) );
                continue;
            }
            if( uistate.favorite_recipes.find( current[line]->ident() ) != uistate.favorite_recipes.end() ) {
                uistate.favorite_recipes.erase( current[line]->ident() );
            } else {
                uistate.favorite_recipes.insert( current[line]->ident() );
            }
        } else if( action == "HIDE_SHOW_RECIPE" ) {
            if( current.empty() ) {
                popup( _( "Nothing selected!" ) );
                redraw = true;
                continue;
            }
            if( show_hidden ) {
                uistate.hidden_recipes.erase( current[line]->ident() );
            } else {
                uistate.hidden_recipes.insert( current[line]->ident() );
            }

            redraw = true;
        } else if( action == "RELATED_RECIPES" ) {
            if( current.empty() ) {
                popup( _( "Nothing selected!" ) );
                redraw = true;
                continue;
            }
            std::string recipe_name = peek_related_recipe( current[ line ], available_recipes );
            if( recipe_name.empty() ) {
                keepline = true;
            } else {
                filterstring = recipe_name;
            }

            redraw = true;
        }
        if( line < 0 ) {
            line = current.size() - 1;
        } else if( line >= static_cast<int>( current.size() ) ) {
            line = 0;
        }
    } while( !done );

    return chosen;
}
Beispiel #29
0
void game::construction_menu()
{
 WINDOW *w_con = newwin(25, 80, 0, 0);
 wborder(w_con, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX,
                LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX );
 mvwprintz(w_con, 0, 1, c_red, _("Construction"));
 mvwputch(w_con,  0, 30, c_white, LINE_OXXX);
 mvwputch(w_con, 24, 30, c_white, LINE_XXOX);
 for (int i = 1; i < 24; i++)
  mvwputch(w_con, i, 30, c_white, LINE_XOXO);

 mvwprintz(w_con,  1, 31, c_white, _("Difficulty:"));

 wrefresh(w_con);

 bool update_info = true;
 int select = 0;
 char ch;

 inventory total_inv;
 total_inv.form_from_map(this, point(u.posx, u.posy), PICKUP_RANGE);
 total_inv.add_stack(u.inv_dump());
 if (u.has_bionic(bio_tools)) {
  item tools(itypes[itm_toolset], turn);
  tools.charges = u.power_level;
  total_inv += tools;
 }

 do {
// Determine where in the master list to start printing
  int offset = select - 11;
  if (offset > constructions.size() - 22)
   offset = constructions.size() - 22;
  if (offset < 0)
   offset = 0;
// Print the constructions between offset and max (or how many will fit)
  for (int i = 0; i < 22 && i + offset < constructions.size(); i++) {
   int current = i + offset;
   nc_color col = (player_can_build(u, total_inv, constructions[current], 0) ?
                   c_white : c_dkgray);
   if (current == select)
    col = hilite(col);
   mvwprintz(w_con, 1 + i, 1, col, constructions[current]->name.c_str());
  }

  if (update_info) {
   update_info = false;
   constructable* current_con = constructions[select];
// Print difficulty
   int pskill = u.sklevel[sk_carpentry], diff = current_con->difficulty;
   mvwprintz(w_con, 1, 43, (pskill >= diff ? c_white : c_red),
             "%d   ", diff);
// Clear out lines for tools & materials
   for (int i = 2; i < 24; i++) {
    for (int j = 31; j < 79; j++)
     mvwputch(w_con, i, j, c_black, 'x');
   }

// Print stages and their requirements
   int posx = 33, posy = 2;
   for (int n = 0; n < current_con->stages.size(); n++) {
    nc_color color_stage = (player_can_build(u, total_inv, current_con, n) ?
                            c_white : c_dkgray);
    mvwprintz(w_con, posy, 31, color_stage, _("Stage %d: %s"), n + 1,
              terlist[current_con->stages[n].terrain].name.c_str());
    posy++;
// Print tools
    construction_stage stage = current_con->stages[n];
    bool has_tool[3] = {stage.tools[0].empty(),
                        stage.tools[1].empty(),
                        stage.tools[2].empty()};
    for (int i = 0; i < 3 && !has_tool[i]; i++) {
     posy++;
     posx = 33;
     for (int j = 0; j < stage.tools[i].size(); j++) {
      itype_id tool = stage.tools[i][j];
      nc_color col = c_red;
      if (total_inv.has_amount(tool, 1)) {
       has_tool[i] = true;
       col = c_green;
      }
      int length = itypes[tool]->name.length();
      if (posx + length > 79) {
       posy++;
       posx = 33;
      }
      mvwprintz(w_con, posy, posx, col, itypes[tool]->name.c_str());
      posx += length + 1; // + 1 for an empty space
      if (j < stage.tools[i].size() - 1) { // "OR" if there's more
       if (posx > 77) {
        posy++;
        posx = 33;
       }
       mvwprintz(w_con, posy, posx, c_white, _("OR"));
       posx += 3;
      }
     }
    }
// Print components
    posy++;
    posx = 33;
    bool has_component[3] = {stage.components[0].empty(),
                             stage.components[1].empty(),
                             stage.components[2].empty()};
    for (int i = 0; i < 3; i++) {
     posx = 33;
     while (has_component[i])
      i++;
     for (int j = 0; j < stage.components[i].size() && i < 3; j++) {
      nc_color col = c_red;
      component comp = stage.components[i][j];
      if (( itypes[comp.type]->is_ammo() &&
           total_inv.has_charges(comp.type, comp.count)) ||
          (!itypes[comp.type]->is_ammo() &&
           total_inv.has_amount(comp.type, comp.count))) {
       has_component[i] = true;
       col = c_green;
      }
      int length = itypes[comp.type]->name.length();
      if (posx + length > 79) {
       posy++;
       posx = 33;
      }
      mvwprintz(w_con, posy, posx, col, "%s x%d",
                itypes[comp.type]->name.c_str(), comp.count);
      posx += length + 3; // + 2 for " x", + 1 for an empty space
// Add more space for the length of the count
      if (comp.count < 10)
       posx++;
      else if (comp.count < 100)
       posx += 2;
      else
       posx += 3;

      if (j < stage.components[i].size() - 1) { // "OR" if there's more
       if (posx > 77) {
        posy++;
        posx = 33;
       }
       mvwprintz(w_con, posy, posx, c_white, _("OR"));
       posx += 3;
      }
     }
     posy++;
    }
   }
   wrefresh(w_con);
  } // Finished updating
 
  ch = input();
  switch (ch) {
   case 'j':
    update_info = true;
    if (select < constructions.size() - 1)
     select++;
    else
     select = 0;
    break;
   case 'k':
    update_info = true;
    if (select > 0)
     select--;
    else
     select = constructions.size() - 1;
    break;
   case '\n':
   case 'l':
    if (player_can_build(u, total_inv, constructions[select], 0)) {
     place_construction(constructions[select]);
     ch = 'q';
    } else {
     popup(_("You can't build that!"));
     for (int i = 1; i < 24; i++)
      mvwputch(w_con, i, 30, c_white, LINE_XOXO);
     update_info = true;
    }
    break;
  }
 } while (ch != 'q' && ch != 'Q' && ch != KEY_ESCAPE);
 refresh_all();
}
Beispiel #30
0
void draw_caravan_borders(WINDOW *w, int current_window)
{
// First, do the borders for the category window
 nc_color col = c_ltgray;
 if (current_window == 0)
  col = c_yellow;

 mvwputch(w, 0, 0, col, LINE_OXXO);
 for (int i = 1; i <= 38; i++) {
  mvwputch(w,  0, i, col, LINE_OXOX);
  mvwputch(w, 11, i, col, LINE_OXOX);
 }
 for (int i = 1; i <= 10; i++) {
  mvwputch(w, i,  0, col, LINE_XOXO);
  mvwputch(w, i, 39, c_yellow, LINE_XOXO); // Shared border, always yellow
 }
 mvwputch(w, 11,  0, col, LINE_XXXO);

// These are shared with the items window, and so are always "on"
 mvwputch(w,  0, 39, c_yellow, LINE_OXXX);
 mvwputch(w, 11, 39, c_yellow, LINE_XOXX);

 col = (current_window == 1 ? c_yellow : c_ltgray);
// Next, draw the borders for the item description window--always "off" & gray
 for (int i = 12; i <= 23; i++) {
  mvwputch(w, i,  0, c_ltgray, LINE_XOXO);
  mvwputch(w, i, 39, col,      LINE_XOXO);
 }
 for (int i = 1; i <= 38; i++)
  mvwputch(w, 24, i, c_ltgray, LINE_OXOX);

 mvwputch(w, 24,  0, c_ltgray, LINE_XXOO);
 mvwputch(w, 24, 39, c_ltgray, LINE_XXOX);

// Finally, draw the item section borders
 for (int i = 40; i <= 78; i++) {
  mvwputch(w,  0, i, col, LINE_OXOX);
  mvwputch(w, 24, i, col, LINE_OXOX);
 }
 for (int i = 1; i <= 23; i++)
  mvwputch(w, i, 79, col, LINE_XOXO);

 mvwputch(w, 24, 39, col, LINE_XXOX);
 mvwputch(w,  0, 79, col, LINE_OOXX);
 mvwputch(w, 24, 79, col, LINE_XOOX);

// Quick reminded about help.
 mvwprintz(w, 24, 2, c_red, "Press ? for help.");
 wrefresh(w);
}