void exit_handler(int s) { if (s != 2 || query_yn(_("Really Quit? All unsaved changes will be lost."))) { erase(); // Clear screen int ret; #if (defined _WIN32 || defined WINDOWS) ret = system("cls"); // Tell the terminal to clear itself ret = system("color 07"); #else ret = system("clear"); // Tell the terminal to clear itself #endif if (ret != 0) { DebugLog( D_ERROR, DC_ALL ) << "system(\"clear\"): error returned: " << ret; } deinitDebug(); int exit_status = 0; if( g != NULL ) { if( g->game_error() ) { exit_status = 1; } delete g; } endwin(); exit( exit_status ); } }
void exit_handler(int s) { if (s != 2 || query_yn(_("Really Quit? All unsaved changes will be lost."))) { erase(); // Clear screen endwin(); // End ncurses int ret; #if (defined _WIN32 || defined WINDOWS) ret = system("cls"); // Tell the terminal to clear itself ret = system("color 07"); #else ret = system("clear"); // Tell the terminal to clear itself #endif if (ret != 0) { DebugLog() << "main.cpp:exit_handler(): system(\"clear\"): error returned\n"; } if(g != NULL) { if(g->game_error()) { delete g; exit(1); } else { delete g; exit(0); } } exit(0); } }
void exit_handler(int s) { bool bExit = false; if (s == 2) { if (query_yn("Really Quit? All unsaved changes will be lost.")) { bExit = true; } } else if (s == -999) { bExit = true; } else { //query_yn(g, "Signal received: %d", s); bExit = true; } if (bExit) { erase(); // Clear screen endwin(); // End ncurses #if (defined _WIN32 || defined WINDOWS) system("cls"); // Tell the terminal to clear itself system("color 07"); #else system("clear"); // Tell the terminal to clear itself #endif exit(0); } }
void zone_manager::add( const std::string &name, const zone_type_id &type, const bool invert, const bool enabled, const tripoint &start, const tripoint &end, std::shared_ptr<zone_options> options ) { zone_data new_zone = zone_data( name, type, invert, enabled, start, end, options ); //the start is a vehicle tile with cargo space if( const cata::optional<vpart_reference> vp = g->m.veh_at( g->m.getlocal( start ) ).part_with_feature( "CARGO", false ) ) { // TODO:Allow for loot zones on vehicles to be larger than 1x1 if( start == end && query_yn( _( "Bind this zone to the cargo part here?" ) ) ) { // TODO: refactor zone options for proper validation code if( type == zone_type_id( "FARM_PLOT" ) ) { popup( _( "You cannot add that type of zone to a vehicle." ), PF_NONE ); return; } create_vehicle_loot_zone( vp->vehicle(), vp->mount(), new_zone ); return; } } //Create a regular zone zones.push_back( new_zone ); cache_data(); }
void trapfunc::sinkhole(int x, int y) { (void)x; (void)y; // unused g->add_msg(_("You step into a sinkhole, and start to sink down!")); g->u.add_memorial_log(pgettext("memorial_male", "Stepped into a sinkhole."), pgettext("memorial_female", "Stepped into a sinkhole.")); if (g->u.has_amount("rope_30", 1) && query_yn(_("There is a sinkhole here. Throw your rope out to try to catch something?"))) { int throwroll = rng(g->u.skillLevel("throw"), g->u.skillLevel("throw") + g->u.str_cur + g->u.dex_cur); if (throwroll >= 12) { g->add_msg(_("The rope catches something!")); if (rng(g->u.skillLevel("unarmed"), g->u.skillLevel("unarmed") + g->u.str_cur) > 6) { // Determine safe places for the character to get pulled to std::vector<point> safe; for (int i = g->u.posx - 1; i <= g->u.posx + 1; i++) { for (int j = g->u.posy - 1; j <= g->u.posy + 1; j++) { if (g->m.move_cost(i, j) > 0 && g->m.tr_at(i, j) != tr_pit) safe.push_back(point(i, j)); } } if (safe.empty()) { g->add_msg(_("There's nowhere to pull yourself to, and you sink!")); g->u.use_amount("rope_30", 1); g->m.spawn_item(g->u.posx + rng(-1, 1), g->u.posy + rng(-1, 1), "rope_30"); g->m.ter_set(g->u.posx, g->u.posy, t_hole); g->vertical_move(-1, true); } else { g->add_msg(_("You pull yourself to safety! The sinkhole collapses.")); int index = rng(0, safe.size() - 1); g->m.ter_set(g->u.posx, g->u.posy, t_hole); g->u.posx = safe[index].x; g->u.posy = safe[index].y; g->update_map(g->u.posx, g->u.posy); } } else { g->add_msg(_("You're not strong enough to pull yourself out...")); g->u.moves -= 100; g->u.use_amount("rope_30", 1); g->m.spawn_item(g->u.posx + rng(-1, 1), g->u.posy + rng(-1, 1), "rope_30"); g->m.ter_set(g->u.posx, g->u.posy, t_hole); g->vertical_move(-1, true); } } else { g->add_msg(_("Your throw misses completely, and you sink!")); if (one_in((g->u.str_cur + g->u.dex_cur) / 3)) { g->u.use_amount("rope_30", 1); g->m.spawn_item(g->u.posx + rng(-1, 1), g->u.posy + rng(-1, 1), "rope_30"); } g->m.ter_set(g->u.posx, g->u.posy, t_hole); g->vertical_move(-1, true); } } else { g->add_msg(_("You sink into the sinkhole!")); g->m.ter_set(g->u.posx, g->u.posy, t_hole); g->vertical_move(-1, true); } }
bool player::install_bionics(it_bionic *type) { if (type == NULL) { debugmsg("Tried to install NULL bionic"); return false; } if (bionics.count(type->id) == 0) { popup("invalid / unknown bionic id %s", type->id.c_str()); return false; } if (has_bionic(type->id)) { if (!(type->id == "bio_power_storage" || type->id == "bio_power_storage_mkII")) { popup(_("You have already installed this bionic.")); return false; } } int chance_of_success = bionic_manip_cos(int_cur, skillLevel("electronics"), skillLevel("firstaid"), skillLevel("mechanics"), type->difficulty); if (!query_yn( _("WARNING: %i percent chance of genetic damage, blood loss, or damage to existing bionics! Install anyway?"), 100 - chance_of_success)) { return false; } int pow_up = 0; if (type->id == "bio_power_storage" || type->id == "bio_power_storage_mkII") { pow_up = BATTERY_AMOUNT; if (type->id == "bio_power_storage_mkII") { pow_up = 250; } } practice( "electronics", int((100 - chance_of_success) * 1.5) ); practice( "firstaid", int((100 - chance_of_success) * 1.0) ); practice( "mechanics", int((100 - chance_of_success) * 0.5) ); int success = chance_of_success - rng(1, 100); if (success > 0) { add_memorial_log(pgettext("memorial_male", "Installed bionic: %s."), pgettext("memorial_female", "Installed bionic: %s."), bionics[type->id]->name.c_str()); if (pow_up) { max_power_level += pow_up; add_msg_if_player(m_good, _("Increased storage capacity by %i"), pow_up); } else { add_msg(m_good, _("Successfully installed %s."), bionics[type->id]->name.c_str()); add_bionic(type->id); } } else { add_memorial_log(pgettext("memorial_male", "Installed bionic: %s."), pgettext("memorial_female", "Installed bionic: %s."), bionics[type->id]->name.c_str()); bionics_install_failure(this, type, success); } g->refresh_all(); return true; }
void trapfunc::sinkhole(game *g, int x, int y) { g->add_msg("You step into a sinkhole, and start to sink down!"); if (g->u.has_amount(itm_rope_30, 1) && query_yn("Throw your rope to try to catch soemthing?")) { int throwroll = rng(g->u.sklevel[sk_throw], g->u.sklevel[sk_throw] + g->u.str_cur + g->u.dex_cur); if (throwroll >= 12) { g->add_msg("The rope catches something!"); if (rng(g->u.sklevel[sk_unarmed], g->u.sklevel[sk_unarmed] + g->u.str_cur) > 6) { // Determine safe places for the character to get pulled to std::vector<point> safe; for (int i = g->u.posx - 1; i <= g->u.posx + 1; i++) { for (int j = g->u.posx - 1; j <= g->u.posx + 1; j++) { if (g->m.move_cost(i, j) > 0 && g->m.tr_at(i, j) != tr_pit) safe.push_back(point(i, j)); } } if (safe.size() == 0) { g->add_msg("There's nowhere to pull yourself to, and you sink!"); g->u.use_amount(itm_rope_30, 1); g->m.add_item(g->u.posx + rng(-1, 1), g->u.posy + rng(-1, 1), g->itypes[itm_rope_30], g->turn); g->m.tr_at(g->u.posx, g->u.posy) = tr_pit; g->vertical_move(-1, true); } else { g->add_msg("You pull yourself to safety! The sinkhole collapses."); int index = rng(0, safe.size() - 1); g->u.posx = safe[index].x; g->u.posy = safe[index].y; g->update_map(g->u.posx, g->u.posy); g->m.tr_at(g->u.posx, g->u.posy) = tr_pit; } } else { g->add_msg("You're not strong enough to pull yourself out..."); g->u.moves -= 100; g->u.use_amount(itm_rope_30, 1); g->m.add_item(g->u.posx + rng(-1, 1), g->u.posy + rng(-1, 1), g->itypes[itm_rope_30], g->turn); g->vertical_move(-1, true); } } else { g->add_msg("Your throw misses completely, and you sink!"); if (one_in((g->u.str_cur + g->u.dex_cur) / 3)) { g->u.use_amount(itm_rope_30, 1); g->m.add_item(g->u.posx + rng(-1, 1), g->u.posy + rng(-1, 1), g->itypes[itm_rope_30], g->turn); } g->m.tr_at(g->u.posx, g->u.posy) = tr_pit; g->vertical_move(-1, true); } } else { g->add_msg("You sink into the sinkhole!"); g->vertical_move(-1, true); } }
WORLDPTR worldfactory::make_new_world() { // Window variables 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; // World to return after generating WORLDPTR retworld = new WORLD(); // set up window WINDOW *wf_win = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX); // prepare tab display order std::vector<worldgen_display> tabs; std::vector<std::string> tab_strings; tabs.push_back(&worldfactory::show_worldgen_tab_options); tabs.push_back(&worldfactory::show_worldgen_tab_confirm); tab_strings.push_back(_("World Gen Options")); tab_strings.push_back(_("CONFIRMATION")); int curtab = 0; int lasttab; // give placement memory to menus, sorta. const int numtabs = tabs.size(); while (curtab >= 0 && curtab < numtabs) { lasttab = curtab; draw_worldgen_tabs(wf_win, curtab, tab_strings); curtab += (world_generator->*tabs[curtab])(wf_win, retworld); if (curtab < 0) { if (!query_yn(_("Do you want to abort World Generation?"))) { curtab = lasttab; } } } if (curtab < 0) { delete retworld; return NULL; } // add world to world list all_worlds[retworld->world_name] = retworld; all_worldnames.push_back(retworld->world_name); std::stringstream path; path << SAVE_DIR << PATH_SEPARATOR << retworld->world_name; retworld->world_path = path.str(); if (!save_world(retworld)) { std::string worldname = retworld->world_name; std::vector<std::string>::iterator it = std::find(all_worldnames.begin(), all_worldnames.end(), worldname); all_worldnames.erase(it); delete all_worlds[worldname]; delete retworld; all_worlds.erase(worldname); return NULL; } return retworld; }
void auto_pickup::add_rule(const std::string &sRule) { vRules[CHARACTER].push_back(cRules(sRule, true, false)); merge_vector(); create_rules(); if (!OPTIONS["AUTO_PICKUP"] && query_yn(_("Autopickup is not enabled in the options. Enable it now?")) ) { OPTIONS["AUTO_PICKUP"].setNext(); get_options().save(); } }
void addPickupRule(std::string sRule) { vAutoPickupRules[2].push_back(cPickupRules(sRule, true, false)); merge_vector(); createPickupRules(); if (!OPTIONS["AUTO_PICKUP"] && query_yn(_("Autopickup is not enabled in the options. Enable it now?")) ) { OPTIONS["AUTO_PICKUP"].setNext(); save_options(true); } }
void safemode::add_rule( const std::string &rule_in, const Creature::Attitude attitude_in, const int proximity_in, const rule_state state_in ) { character_rules.push_back( rules_class( rule_in, true, ( state_in == RULE_WHITELISTED ), attitude_in, proximity_in ) ); create_rules(); if( !get_option<bool>( "SAFEMODE" ) && query_yn( _( "Safe Mode is not enabled in the options. Enable it now?" ) ) ) { get_options().get_option( "SAFEMODE" ).setNext(); get_options().save(); } }
bool craft_command::query_continue( const std::vector<comp_selection<item_comp>> &missing_items, const std::vector<comp_selection<tool_comp>> &missing_tools ) { std::stringstream ss; ss << _( "Some components used previously are missing. Continue?" ); if( !missing_items.empty() ) { ss << std::endl << _( "Item(s): " ); component_list_string( ss, missing_items ); } if( !missing_tools.empty() ) { ss << std::endl << _( "Tool(s): " ); component_list_string( ss, missing_tools ); } return query_yn( ss.str() ); }
void construct::done_digormine_stair( const tripoint &p, bool dig ) { tripoint const abs_pos = p; tripoint const pos_sm = ms_to_sm_copy( abs_pos ); tinymap tmpmap; tmpmap.load( pos_sm.x, pos_sm.y, pos_sm.z - 1, false ); tripoint const local_tmp = tmpmap.getlocal( abs_pos ); bool dig_muts = g->u.has_trait( "PAINRESIST_TROGLO" ) || g->u.has_trait( "STOCKY_TROGLO" ); int no_mut_penalty = dig_muts ? 10 : 0; int mine_penalty = dig ? 0 : 10; g->u.mod_hunger( 5 + mine_penalty + no_mut_penalty ); g->u.mod_thirst( 5 + mine_penalty + no_mut_penalty ); g->u.mod_fatigue( 10 + mine_penalty + no_mut_penalty ); if( tmpmap.ter( local_tmp ) == t_lava ) { if( !( query_yn( _( "The rock feels much warmer than normal. Proceed?" ) ) ) ) { g->m.ter_set( p, t_pit ); // You dug down a bit before detecting the problem unroll_digging( dig ? 8 : 12 ); } else { add_msg( m_warning, _( "You just tunneled into lava!" ) ); g->u.add_memorial_log( pgettext( "memorial_male", "Dug a shaft into lava." ), pgettext( "memorial_female", "Dug a shaft into lava." ) ); g->m.ter_set( p, t_hole ); } return; } bool impassable = tmpmap.impassable( local_tmp ); if( !impassable ) { add_msg( _( "You dig into a preexisting space, and improvise a ladder." ) ); } else if( dig ) { add_msg( _( "You dig a stairway, adding sturdy timbers and a rope for safety." ) ); } else { add_msg( _( "You drill out a passage, heading deeper underground." ) ); } g->m.ter_set( p, t_stairs_down ); // There's the top half // Again, need to use submap-local coordinates. tmpmap.ter_set( local_tmp, impassable ? t_stairs_up : t_ladder_up ); // and there's the bottom half. // And save to the center coordinate of the current active map. tmpmap.save(); }
void exit_handler(int s) { const int old_timeout = inp_mngr.get_timeout(); inp_mngr.reset_timeout(); if (s != 2 || query_yn(_("Really Quit? All unsaved changes will be lost."))) { erase(); // Clear screen deinitDebug(); int exit_status = 0; if( g != NULL ) { delete g; } endwin(); exit( exit_status ); } inp_mngr.set_timeout( old_timeout ); }
void exit_handler(int s) { if (s != 2 || query_yn(_("Really Quit? All unsaved changes will be lost."))) { erase(); // Clear screen deinitDebug(); int exit_status = 0; if( g != NULL ) { if( g->game_error() ) { exit_status = 1; } delete g; } endwin(); exit( exit_status ); } }
tripoint start_location::find_player_initial_location() const { const bool using_existing_initial_overmap = overmap_buffer.has( 0, 0 ); // The coordinates of an overmap that is known to *not* exist. We can regenerate this // as often we like. point non_existing_omt = point( 0, 0 ); if( using_existing_initial_overmap ) { // arbitrary, should be large enough to include all overmaps ever created const int radius = 32; for( const point omp : closest_points_first( radius, point( 0, 0 ) ) ) { const overmap *omap = overmap_buffer.get_existing( omp.x, omp.y ); if( omap == nullptr ) { if( non_existing_omt == point( 0, 0 ) ) { non_existing_omt = omp; } continue; } const tripoint omtstart = omap->find_random_omt( target() ); if( omtstart != overmap::invalid_tripoint ) { return omtstart + point( omp.x * OMAPX, omp.y * OMAPY ); } } } while( true ) { popup_nowait( _( "Please wait as we build your world" ) ); const overmap &initial_overmap = overmap_buffer.get( non_existing_omt.x, non_existing_omt.y ); const tripoint omtstart = initial_overmap.find_random_omt( target() ); if( omtstart != overmap::invalid_tripoint ) { return omtstart + point( non_existing_omt.x * OMAPX, non_existing_omt.y * OMAPY ); } if( !query_yn( _( "The game could not create a world with a suitable starting location.\n\n" "Depending on the world options, the starting location may never appear. If the problem persists, you can try another starting location, or change the world options.\n\n" "Try again?" ) ) ) { return overmap::invalid_tripoint; } overmap_buffer.clear(); } }
bool player::disassemble( item &obj, int pos, bool ground, bool interactive ) { // check sufficient tools for disassembly std::string err; if( !can_disassemble( obj, crafting_inventory(), &err ) ) { if( interactive ) { add_msg_if_player( m_info, "%s", err.c_str() ); } return false; } const auto &r = recipe_dictionary::get_uncraft( obj.typeId() ); // last chance to back out if( interactive && get_option<bool>( "QUERY_DISASSEMBLE" ) ) { const auto components( r.disassembly_requirements().get_components() ); std::ostringstream list; for( const auto &elem : components ) { list << "- " << elem.front().to_string() << std::endl; } if( !query_yn( _( "Disassembling the %s may yield:\n%s\nReally disassemble?" ), obj.tname().c_str(), list.str().c_str() ) ) { return false; } } if( activity.id() != activity_id( "ACT_DISASSEMBLE" ) ) { assign_activity( activity_id( "ACT_DISASSEMBLE" ), r.time ); } else if( activity.moves_left <= 0 ) { activity.moves_left = r.time; } activity.values.push_back( pos ); activity.coords.push_back( ground ? this->pos() : tripoint_min ); activity.str_values.push_back( r.result ); return true; }
void exit_handler(int s) { if (s != 2 || query_yn(_("Really Quit? All unsaved changes will be lost."))) { erase(); // Clear screen endwin(); // End ncurses #if (defined _WIN32 || defined WINDOWS) system("cls"); // Tell the terminal to clear itself system("color 07"); #else system("clear"); // Tell the terminal to clear itself #endif if(g != NULL) { if(g->game_error()) { delete g; exit(1); } else { delete g; exit(0); } } exit(0); } }
bool player::feed_reactor_with( item &it ) { if( !can_feed_reactor_with( it ) ) { return false; } const auto iter = plut_charges.find( it.typeId() ); const int max_amount = iter != plut_charges.end() ? iter->second : 0; const int amount = std::min( get_acquirable_energy( it, rechargeable_cbm::reactor ), max_amount ); if( amount >= PLUTONIUM_CHARGES * 10 && !query_yn( _( "Thats a LOT of plutonium. Are you sure you want that much?" ) ) ) { return false; } add_msg_player_or_npc( _( "You add your %s to your reactor's tank." ), _( "<npcname> pours %s into their reactor's tank." ), it.tname().c_str() ); tank_plut += amount; // @todo Encapsulate it.charges -= 1; mod_moves( -250 ); return true; }
WORLDPTR worldfactory::make_new_world( bool show_prompt ) { // World to return after generating WORLDPTR retworld = new WORLD(); if( show_prompt ) { // Window variables 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; // set up window WINDOW *wf_win = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX); WINDOW_PTR wf_winptr( wf_win ); int curtab = 0; int lasttab; // give placement memory to menus, sorta. const int numtabs = tabs.size(); while (curtab >= 0 && curtab < numtabs) { lasttab = curtab; draw_worldgen_tabs(wf_win, curtab); curtab += (world_generator->*tabs[curtab])(wf_win, retworld); if (curtab < 0) { if (!query_yn(_("Do you want to abort World Generation?"))) { curtab = lasttab; } } } if (curtab < 0) { delete retworld; return NULL; } } else { // 'Play NOW' #ifndef LUA // Silently remove all Lua mods setted by default. std::vector<std::string>::iterator mod_it; for (mod_it = retworld->active_mod_order.begin(); mod_it != retworld->active_mod_order.end();) { MOD_INFORMATION *minfo = mman->mod_map[*mod_it]; if ( minfo->need_lua ) { mod_it = retworld->active_mod_order.erase(mod_it); } else { mod_it++; } } #endif } // add world to world list all_worlds[retworld->world_name] = retworld; all_worldnames.push_back(retworld->world_name); std::stringstream path; path << FILENAMES["savedir"] << retworld->world_name; retworld->world_path = path.str(); //debugmsg("worldpath: %s", path.str().c_str()); if (!save_world(retworld)) { std::string worldname = retworld->world_name; std::vector<std::string>::iterator it = std::find(all_worldnames.begin(), all_worldnames.end(), worldname); all_worldnames.erase(it); if (all_worlds[worldname] != retworld) { delete retworld; } delete all_worlds[worldname]; all_worlds.erase(worldname); return NULL; } return retworld; }
void game::show_options() { std::map<std::string, cOpt> OPTIONS_OLD = OPTIONS; const int iTooltipHeight = 3; const int iContentHeight = FULL_SCREEN_HEIGHT-3-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; std::map<int, bool> mapLines; mapLines[3] = true; mapLines[60] = true; //mapLines[68] = true; WINDOW* w_options_border = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX); WINDOW* w_options_tooltip = newwin(iTooltipHeight, FULL_SCREEN_WIDTH - 2, 1 + iOffsetY, 1 + iOffsetX); WINDOW* w_options_header = newwin(1, FULL_SCREEN_WIDTH - 2, 1 + iTooltipHeight + iOffsetY, 1 + iOffsetX); WINDOW* w_options = newwin(iContentHeight, FULL_SCREEN_WIDTH - 2, iTooltipHeight + 2 + iOffsetY, 1 + iOffsetX); wborder(w_options_border, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX); mvwputch(w_options_border, 4, 0, c_ltgray, LINE_XXXO); // |- mvwputch(w_options_border, 4, 79, c_ltgray, LINE_XOXX); // -| for (std::map<int, bool>::iterator iter = mapLines.begin(); iter != mapLines.end(); ++iter) { mvwputch(w_options_border, FULL_SCREEN_HEIGHT-1, iter->first + 1, c_ltgray, LINE_XXOX); // _|_ } mvwprintz(w_options_border, 0, 36, c_ltred, _(" OPTIONS ")); wrefresh(w_options_border); for (int i = 0; i < 78; i++) { if (mapLines[i]) { mvwputch(w_options_header, 0, i, c_ltgray, LINE_OXXX); } else { mvwputch(w_options_header, 0, i, c_ltgray, LINE_OXOX); // Draw header line } } //mvwprintz(w_options_header, 3, 0, c_white, "#"); //mvwprintz(w_options_header, 3, 7, c_white, _("Option")); //mvwprintz(w_options_header, 3, 52, c_white, _("Value")); wrefresh(w_options_header); int iCurrentPage = 0; int iCurrentLine = 0; int iStartPos = 0; bool bStuffChanged = false; char ch = ' '; std::stringstream sTemp; do { //Clear the lines for (int i = 0; i < iContentHeight; i++) { for (int j = 0; j < 79; j++) { if (mapLines[j]) { mvwputch(w_options, i, j, c_ltgray, LINE_XOXO); } else { mvwputch(w_options, i, j, c_black, ' '); } if (i < iTooltipHeight) { mvwputch(w_options_tooltip, i, j, c_black, ' '); } } } if (mPageItems[iCurrentPage].size() > iContentHeight) { iStartPos = iCurrentLine - (iContentHeight - 1) / 2; if (iStartPos < 0) { iStartPos = 0; } else if (iStartPos + iContentHeight > mPageItems[iCurrentPage].size()) { iStartPos = mPageItems[iCurrentPage].size() - iContentHeight; } } //Draw options for (int i = iStartPos; i < mPageItems[iCurrentPage].size(); i++) { if (i >= iStartPos && i < iStartPos + ((iContentHeight > mPageItems[iCurrentPage].size()) ? mPageItems[iCurrentPage].size() : iContentHeight)) { nc_color cLineColor = c_ltgreen; sTemp.str(""); sTemp << i + 1; mvwprintz(w_options, i - iStartPos, 0, c_white, sTemp.str().c_str()); mvwprintz(w_options, i - iStartPos, 4, c_white, ""); if (iCurrentLine == i) { wprintz(w_options, c_yellow, ">> "); } else { wprintz(w_options, c_yellow, " "); } wprintz(w_options, c_white, "%s", (OPTIONS[mPageItems[iCurrentPage][i]].getMenuText()).c_str()); if (OPTIONS[mPageItems[iCurrentPage][i]].getValue() == "False") { cLineColor = c_ltred; } mvwprintz(w_options, i - iStartPos, 62, (iCurrentLine == i) ? hilite(cLineColor) : cLineColor, "%s", (OPTIONS[mPageItems[iCurrentPage][i]].getValue()).c_str()); } } //Draw Tabs mvwprintz(w_options_header, 0, 7, c_white, ""); for (int i = 0; i < vPages.size(); i++) { if (mPageItems[i].size() > 0) { //skip empty pages wprintz(w_options_header, c_white, "["); wprintz(w_options_header, (iCurrentPage == i) ? hilite(c_white) : c_white, vPages[i].c_str()); wprintz(w_options_header, c_white, "]"); wputch(w_options_header, c_white, LINE_OXOX); } } wrefresh(w_options_header); fold_and_print(w_options_tooltip, 0, 0, 78, c_white, "%s", (OPTIONS[mPageItems[iCurrentPage][iCurrentLine]].getTooltip() + " #Default: " + OPTIONS[mPageItems[iCurrentPage][iCurrentLine]].getDefaultText()).c_str()); wrefresh(w_options_tooltip); wrefresh(w_options); ch = input(); if (mPageItems[iCurrentPage].size() > 0 || ch == '\t') { switch(ch) { case 'j': //move down iCurrentLine++; if (iCurrentLine >= mPageItems[iCurrentPage].size()) { iCurrentLine = 0; } break; case 'k': //move up iCurrentLine--; if (iCurrentLine < 0) { iCurrentLine = mPageItems[iCurrentPage].size()-1; } break; case 'l': //set to prev value OPTIONS[mPageItems[iCurrentPage][iCurrentLine]].setNext(); bStuffChanged = true; break; case 'h': //set to next value OPTIONS[mPageItems[iCurrentPage][iCurrentLine]].setPrev(); bStuffChanged = true; break; case '>': case '\t': //Switch to next Page iCurrentLine = 0; do { //skip empty pages iCurrentPage++; if (iCurrentPage >= vPages.size()) { iCurrentPage = 0; } } while(mPageItems[iCurrentPage].size() == 0); break; case '<': iCurrentLine = 0; do { //skip empty pages iCurrentPage--; if (iCurrentPage < 0) { iCurrentPage = vPages.size()-1; } } while(mPageItems[iCurrentPage].size() == 0); break; } } } while(ch != 'q' && ch != 'Q' && ch != KEY_ESCAPE); if (bStuffChanged) { if(query_yn(_("Save changes?"))) { save_options(); } else { OPTIONS = OPTIONS_OLD; } } werase(w_options); werase(w_options_border); werase(w_options_header); werase(w_options_tooltip); }
int worldfactory::show_worldgen_tab_confirm(WINDOW *win, WORLDPTR world) { const int iTooltipHeight = 1; const int iContentHeight = FULL_SCREEN_HEIGHT - 3 - 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; const char* line_of_32_underscores = "________________________________"; WINDOW *w_confirmation = newwin(iContentHeight, FULL_SCREEN_WIDTH - 2, iTooltipHeight + 2 + iOffsetY, 1 + iOffsetX); WINDOW_PTR w_confirmationptr( w_confirmation ); unsigned namebar_y = 1; unsigned namebar_x = 3 + utf8_width(_("World Name:")); int line = 1; bool noname = false; input_context ctxt("WORLDGEN_CONFIRM_DIALOG"); ctxt.register_action("HELP_KEYBINDINGS"); ctxt.register_action("QUIT"); ctxt.register_action("ANY_INPUT"); ctxt.register_action("NEXT_TAB"); ctxt.register_action("PREV_TAB"); ctxt.register_action("PICK_RANDOM_WORLDNAME"); std::string worldname = world->world_name; do { mvwprintz(w_confirmation, namebar_y, 2, c_white, _("World Name:")); mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, line_of_32_underscores); fold_and_print(w_confirmation, 3, 2, 76, c_ltgray, _("Press <color_yellow>%s</color> to pick a random name for your world."), ctxt.get_desc("PICK_RANDOM_WORLDNAME").c_str()); fold_and_print(w_confirmation, FULL_SCREEN_HEIGHT / 2 - 2, 2, 76, c_ltgray, _("\ Press <color_yellow>%s</color> when you are satisfied with the world as it is and are ready \ to continue, or <color_yellow>%s</color> to go back and review your world."), ctxt.get_desc("NEXT_TAB").c_str(), ctxt.get_desc("PREV_TAB").c_str()); if (!noname) { mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, "%s", worldname.c_str()); if (line == 1) { wprintz(w_confirmation, h_ltgray, "_"); } } if (noname) { mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, line_of_32_underscores); noname = false; } wrefresh(win); wrefresh(w_confirmation); refresh(); const std::string action = ctxt.handle_input(); if (action == "NEXT_TAB") { #ifndef LUA MOD_INFORMATION *temp = NULL; for (std::string &mod : world->active_mod_order) { temp = mman->mod_map[mod]; if ( temp->need_lua ) { popup(_("Mod '%s' requires Lua support."), temp->name.c_str()); return -2; // Move back to modselect tab. } } #endif if (worldname.empty()) { mvwprintz(w_confirmation, namebar_y, namebar_x, h_ltgray, _("_______NO NAME ENTERED!!!!______")); noname = true; wrefresh(w_confirmation); if (!query_yn(_("Are you SURE you're finished? World name will be randomly generated."))) { continue; } else { world->world_name = pick_random_name(); if (!valid_worldname(world->world_name)) { continue; } return 1; } } else if (query_yn(_("Are you SURE you're finished?")) && valid_worldname(worldname)) { world->world_name = worldname; return 1; } else { continue; } } else if (action == "PREV_TAB") { world->world_name = worldname; return -1; } else if (action == "PICK_RANDOM_WORLDNAME") { mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, line_of_32_underscores); world->world_name = worldname = pick_random_name(); } else if (action == "QUIT") { // Cache the current name just in case they say No to the exit query. world->world_name = worldname; return -999; } else if (action == "ANY_INPUT") { const input_event ev = ctxt.get_raw_input(); const long ch = ev.get_first_input(); switch (line) { case 1: { utf8_wrapper wrap(worldname); utf8_wrapper newtext( ev.text ); if( ch == KEY_BACKSPACE ) { if (!wrap.empty()) { wrap.erase(wrap.length() - 1, 1); worldname = wrap.str(); } } else if(ch == KEY_F(2)) { std::string tmp = get_input_string_from_file(); int tmplen = utf8_width( tmp ); if(tmplen > 0 && tmplen + utf8_width(worldname) < 30) { worldname.append(tmp); } } else if( !newtext.empty() && is_char_allowed( newtext.at( 0 ) ) ) { // No empty string, no slash, no backslash, no control sequence wrap.append( newtext ); worldname = wrap.str(); } mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, line_of_32_underscores); mvwprintz(w_confirmation, namebar_y, namebar_x, c_ltgray, "%s", worldname.c_str()); wprintz(w_confirmation, h_ltgray, "_"); } break; } } } while (true); return 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; }
void defense_game::caravan(game *g) { std::vector<itype_id> items[NUM_CARAVAN_CATEGORIES]; std::vector<int> item_count[NUM_CARAVAN_CATEGORIES]; // Init the items for each category for (int i = 0; i < NUM_CARAVAN_CATEGORIES; i++) { items[i] = caravan_items( caravan_category(i) ); for (int j = 0; j < items[i].size(); j++) { if (current_wave == 0 || !one_in(4)) item_count[i].push_back(0); // Init counts to 0 for each item else { // Remove the item items[i].erase( items[i].begin() + j); j--; } } } int total_price = 0; WINDOW *w = newwin(25, 80, 0, 0); int offset = 0, item_selected = 0, category_selected = 0; int current_window = 0; draw_caravan_borders(w, current_window); draw_caravan_categories(w, category_selected, total_price, g->u.cash); bool done = false; bool cancel = false; while (!done) { char ch = input(); switch (ch) { case '?': popup_top("\ CARAVAN:\n\ Start by selecting a category using your favorite up/down keys.\n\ Switch between category selection and item selecting by pressing Tab.\n\ Pick an item with the up/down keys, press + to buy 1 more, - to buy 1 less.\n\ Press Enter to buy everything in your cart, Esc to buy nothing."); draw_caravan_categories(w, category_selected, total_price, g->u.cash); draw_caravan_items(w, g, &(items[category_selected]), &(item_count[category_selected]), offset, item_selected); draw_caravan_borders(w, current_window); break; case 'j': if (current_window == 0) { // Categories category_selected++; if (category_selected == NUM_CARAVAN_CATEGORIES) category_selected = CARAVAN_CART; draw_caravan_categories(w, category_selected, total_price, g->u.cash); offset = 0; item_selected = 0; draw_caravan_items(w, g, &(items[category_selected]), &(item_count[category_selected]), offset, item_selected); draw_caravan_borders(w, current_window); } else if (items[category_selected].size() > 0) { // Items if (item_selected < items[category_selected].size() - 1) item_selected++; else { item_selected = 0; offset = 0; } if (item_selected > offset + 22) offset++; draw_caravan_items(w, g, &(items[category_selected]), &(item_count[category_selected]), offset, item_selected); draw_caravan_borders(w, current_window); } break; case 'k': if (current_window == 0) { // Categories if (category_selected == 0) category_selected = NUM_CARAVAN_CATEGORIES - 1; else category_selected--; if (category_selected == NUM_CARAVAN_CATEGORIES) category_selected = CARAVAN_CART; draw_caravan_categories(w, category_selected, total_price, g->u.cash); offset = 0; item_selected = 0; draw_caravan_items(w, g, &(items[category_selected]), &(item_count[category_selected]), offset, item_selected); draw_caravan_borders(w, current_window); } else if (items[category_selected].size() > 0) { // Items if (item_selected > 0) item_selected--; else { item_selected = items[category_selected].size() - 1; offset = item_selected - 22; if (offset < 0) offset = 0; } if (item_selected < offset) offset--; draw_caravan_items(w, g, &(items[category_selected]), &(item_count[category_selected]), offset, item_selected); draw_caravan_borders(w, current_window); } break; case '+': case 'l': if (current_window == 1 && items[category_selected].size() > 0) { item_count[category_selected][item_selected]++; itype_id tmp_itm = items[category_selected][item_selected]; total_price += caravan_price(g->u, g->itypes[tmp_itm]->price); if (category_selected == CARAVAN_CART) { // Find the item in its category for (int i = 1; i < NUM_CARAVAN_CATEGORIES; i++) { for (int j = 0; j < items[i].size(); j++) { if (items[i][j] == tmp_itm) item_count[i][j]++; } } } else { // Add / increase the item in the shopping cart bool found_item = false; for (int i = 0; i < items[0].size() && !found_item; i++) { if (items[0][i] == tmp_itm) { found_item = true; item_count[0][i]++; } } if (!found_item) { items[0].push_back(items[category_selected][item_selected]); item_count[0].push_back(1); } } draw_caravan_categories(w, category_selected, total_price, g->u.cash); draw_caravan_items(w, g, &(items[category_selected]), &(item_count[category_selected]), offset, item_selected); draw_caravan_borders(w, current_window); } break; case '-': case 'h': if (current_window == 1 && items[category_selected].size() > 0 && item_count[category_selected][item_selected] > 0) { item_count[category_selected][item_selected]--; itype_id tmp_itm = items[category_selected][item_selected]; total_price -= caravan_price(g->u, g->itypes[tmp_itm]->price); if (category_selected == CARAVAN_CART) { // Find the item in its category for (int i = 1; i < NUM_CARAVAN_CATEGORIES; i++) { for (int j = 0; j < items[i].size(); j++) { if (items[i][j] == tmp_itm) item_count[i][j]--; } } } else { // Decrease / remove the item in the shopping cart bool found_item = false; for (int i = 0; i < items[0].size() && !found_item; i++) { if (items[0][i] == tmp_itm) { found_item = true; item_count[0][i]--; if (item_count[0][i] == 0) { item_count[0].erase(item_count[0].begin() + i); items[0].erase(items[0].begin() + i); } } } } draw_caravan_categories(w, category_selected, total_price, g->u.cash); draw_caravan_items(w, g, &(items[category_selected]), &(item_count[category_selected]), offset, item_selected); draw_caravan_borders(w, current_window); } break; case '\t': current_window = (current_window + 1) % 2; draw_caravan_borders(w, current_window); break; case KEY_ESCAPE: if (query_yn("Really buy nothing?")) { cancel = true; done = true; } else { draw_caravan_categories(w, category_selected, total_price, g->u.cash); draw_caravan_items(w, g, &(items[category_selected]), &(item_count[category_selected]), offset, item_selected); draw_caravan_borders(w, current_window); } break; case '\n': if (total_price > g->u.cash) popup("You can't afford those items!"); else if ((items[0].empty() && query_yn("Really buy nothing?")) || (!items[0].empty() && query_yn("Buy %d items, leaving you with $%d?", items[0].size(), g->u.cash - total_price))) done = true; if (!done) { // We canceled, so redraw everything draw_caravan_categories(w, category_selected, total_price, g->u.cash); draw_caravan_items(w, g, &(items[category_selected]), &(item_count[category_selected]), offset, item_selected); draw_caravan_borders(w, current_window); } break; } // switch (ch) } // while (!done) if (!cancel) { g->u.cash -= total_price; bool dropped_some = false; for (int i = 0; i < items[0].size(); i++) { item tmp(g->itypes[ items[0][i] ], g->turn); tmp = tmp.in_its_container(&(g->itypes)); for (int j = 0; j < item_count[0][i]; j++) { if (g->u.volume_carried() + tmp.volume() <= g->u.volume_capacity() && g->u.weight_carried() + tmp.weight() <= g->u.weight_capacity() && g->u.inv.size() < inv_chars.size()) g->u.i_add(tmp); else { // Could fit it in the inventory! dropped_some = true; g->m.add_item(g->u.posx, g->u.posy, tmp); } } } if (dropped_some) g->add_msg("You drop some items."); } }
void game::show_options() { int iMaxX = (VIEWX < 12) ? 80 : (VIEWX*2)+56; int iMaxY = (VIEWY < 12) ? 25 : (VIEWY*2)+1; WINDOW* w_options_border = newwin(25, 80, (iMaxY > 25) ? (iMaxY-25)/2 : 0, (iMaxX > 80) ? (iMaxX-80)/2 : 0); WINDOW* w_options = newwin(23, 78, 1 + (int)((iMaxY > 25) ? (iMaxY-25)/2 : 0), 1 + (int)((iMaxX > 80) ? (iMaxX-80)/2 : 0)); int offset = 1; int line = 0; char ch = ' '; bool changed_options = false; bool needs_refresh = true; do { wborder(w_options_border, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX); mvwprintz(w_options_border, 0, 36, c_ltred, " OPTIONS "); wrefresh(w_options_border); // TODO: change instructions if (needs_refresh) { werase(w_options); mvwprintz(w_options, 0, 40, c_white, "Use up/down keys to scroll through"); mvwprintz(w_options, 1, 40, c_white, "available options."); mvwprintz(w_options, 2, 40, c_white, "Use left/right keys to toggle."); mvwprintz(w_options, 3, 40, c_white, "Press ESC or q to return. "); // highlight options for option descriptions std::string tmp = option_desc(option_key(offset + line)); std::string out; size_t pos; int displayline = 5; do { pos = tmp.find_first_of('\n'); out = tmp.substr(0, pos); mvwprintz(w_options, displayline, 40, c_white, out.c_str()); tmp = tmp.substr(pos + 1); displayline++; } while (pos != std::string::npos && displayline < 12); needs_refresh = false; } // Clear the lines for (int i = 0; i < 25; i++) mvwprintz(w_options, i, 0, c_black, " "); int valid_option_count = 0; // display options for (int i = 0; i < 25 && offset + i < NUM_OPTION_KEYS; i++) { valid_option_count++; mvwprintz(w_options, i, 0, c_white, "%s: ", option_name( option_key(offset + i) ).c_str()); if (option_is_bool(option_key(offset + i))) { bool on = OPTIONS[ option_key(offset + i) ]; if (i == line) mvwprintz(w_options, i, 30, hilite(c_ltcyan), (on ? "True" : "False")); else mvwprintz(w_options, i, 30, (on ? c_ltgreen : c_ltred), (on ? "True" : "False")); } else { char option_val = OPTIONS[ option_key(offset + i) ]; if (i == line) mvwprintz(w_options, i, 30, hilite(c_ltcyan), "%d", option_val ); else mvwprintz(w_options, i, 30, c_ltgreen, "%d", option_val ); } } wrefresh(w_options); refresh(); ch = input(); needs_refresh = true; refresh(); switch (ch) { // move up and down case 'j': line++; if (line == NUM_OPTION_KEYS - 1) line = 0; break; case 'k': line--; if (line < 0) line = NUM_OPTION_KEYS - 2; break; // toggle options with left/right keys case 'h': if (option_is_bool(option_key(offset + line))) OPTIONS[ option_key(offset + line) ] = !(OPTIONS[ option_key(offset + line) ]); else { OPTIONS[ option_key(offset + line) ]--; if ((OPTIONS[ option_key(offset + line) ]) < 0 ) OPTIONS[ option_key(offset + line) ] = option_max_options(option_key(offset + line)) - 1; } changed_options = true; break; case 'l': if (option_is_bool(option_key(offset + line))) OPTIONS[ option_key(offset + line) ] = !(OPTIONS[ option_key(offset + line) ]); else { OPTIONS[ option_key(offset + line) ]++; if ((OPTIONS[ option_key(offset + line) ]) >= option_max_options(option_key(offset + line))) OPTIONS[ option_key(offset + line) ] = 0; } changed_options = true; break; } } while (ch != 'q' && ch != 'Q' && ch != KEY_ESCAPE); if (changed_options && query_yn(this->VIEWX, this->VIEWY, "Save changes?")) save_options(); werase(w_options); }
bool Player::create_new_character() { Window w_newch(0, 0, 80, 24); cuss::interface i_newch; if (!i_newch.load_from_file(CUSS_DIR + "/i_newchar_stats.cuss")) { return false; } New_char_screen cur_screen = NCS_STATS; Stat_selected cur_stat = STATSEL_STR; int* stat_value = &(stats.strength); /* We need to set up a list of traits which does NOT include the placeholder / * marker "traits" like TRAIT_MAX_GOOD and TRAIT_MAX_NEUTRAL etc. */ std::vector<Trait_id> selectable_traits; for (int i = 1; i < TRAIT_MAX_BAD; i++) { if (i != TRAIT_MAX_GOOD && i != TRAIT_MAX_NEUTRAL) { selectable_traits.push_back( Trait_id(i) ); } } std::vector<std::string> traits_list = get_trait_list (this); std::vector<std::string> profession_list = get_profession_list(this); name = ""; int points = 4; int num_traits = 0; i_newch.ref_data("num_points", &points); i_newch.ref_data("num_strength", &stats.strength); i_newch.ref_data("num_dexterity", &stats.dexterity); i_newch.ref_data("num_perception", &stats.perception); i_newch.ref_data("num_intelligence", &stats.intelligence); i_newch.set_data("text_description", get_stat_description(cur_stat)); i_newch.set_data("text_strength", "<c=ltblue>Strength<c=/>"); i_newch.set_data("text_dexterity", "<c=ltgray>Dexterity<c=/>"); i_newch.set_data("text_perception", "<c=ltgray>Perception<c=/>"); i_newch.set_data("text_intelligence", "<c=ltgray>Intelligence<c=/>"); bool done = false; while (!done) { // We'll exit this function via keypresses, always // Always set num_points! i_newch.draw(&w_newch); w_newch.refresh(); long ch = getch(); bool changed_screen = false; if (ch == '<') { cur_screen = New_char_screen( cur_screen - 1 ); if (cur_screen == NCS_CANCEL) { if (query_yn("Cancel character creation?")) { return false; } cur_screen = NCS_STATS; } else { changed_screen = true; } } else if (ch == '>') { cur_screen = New_char_screen( cur_screen + 1 ); if (cur_screen == NCS_DONE) { std::string reason_for_fail; if (points > 0) { reason_for_fail += "\nYou have unspent points!"; } if (profession == NULL) { reason_for_fail += "\nYou didn't choose a profession!"; } if (name.empty()) { reason_for_fail += "\nYour name is blank!"; } if (!reason_for_fail.empty()) { popup("Wait, you can't start the game yet!%s", reason_for_fail.c_str()); } else if (query_yn("Complete character and start the game?")) { done = true; } cur_screen = NCS_DESCRIPTION; } else { changed_screen = true; } } else { // We should be doing this with cuss keybindings, but... that gets complex. // Maybe one day I'll update cuss to be more friendly. switch (cur_screen) { case NCS_STATS: { bool changed_stat = false; switch (ch) { case '2': case 'j': case KEY_DOWN: if (cur_stat == STATSEL_INT) { cur_stat = STATSEL_STR; } else { cur_stat = Stat_selected( cur_stat + 1 ); } changed_stat = true; break; case '8': case 'k': case KEY_UP: if (cur_stat == STATSEL_STR) { cur_stat = STATSEL_INT; } else { cur_stat = Stat_selected( cur_stat - 1 ); } changed_stat = true; break; case '4': case 'h': case KEY_LEFT: if (*stat_value > 4) { if (*stat_value > 16) { points++; // Stats above 16 cost 2 points, so get extra back } points++; (*stat_value)--; } break; case '6': case 'l': case KEY_RIGHT: { int point_req = (*stat_value >= 16 ? 2 : 1); if (*stat_value < 20 && points >= point_req) { points -= point_req; (*stat_value)++; } } break; } // switch (ch) if (changed_stat) { // Update stat_value i_newch.set_data("text_strength", "<c=ltgray>Strength<c=/>"); i_newch.set_data("text_dexterity", "<c=ltgray>Dexterity<c=/>"); i_newch.set_data("text_perception", "<c=ltgray>Perception<c=/>"); i_newch.set_data("text_intelligence","<c=ltgray>Intelligence<c=/>"); i_newch.set_data("text_description", get_stat_description(cur_stat)); switch (cur_stat) { case STATSEL_STR: stat_value = &(stats.strength); i_newch.set_data("text_strength", "<c=ltblue>Strength<c=/>"); break; case STATSEL_DEX: stat_value = &(stats.dexterity); i_newch.set_data("text_dexterity", "<c=ltblue>Dexterity<c=/>"); break; case STATSEL_PER: stat_value = &(stats.perception); i_newch.set_data("text_perception", "<c=ltblue>Perception<c=/>"); break; case STATSEL_INT: stat_value = &(stats.intelligence); i_newch.set_data("text_intelligence", "<c=ltblue>Intelligence<c=/>"); break; } } } break; case NCS_TRAITS: { switch (ch) { case '2': case 'j': case KEY_DOWN: { i_newch.add_data("list_traits", 1); int sel = i_newch.get_int("list_traits"); Trait_id cur_trait = selectable_traits[sel]; i_newch.set_data("num_cost", abs(trait_cost(cur_trait))); if (trait_cost(cur_trait) >= 0) { i_newch.set_data("text_cost", "<c=yellow>Cost:<c=/>"); } else { i_newch.set_data("text_cost", "<c=yellow>Earns:<c=/>"); } if (trait_cost(cur_trait) > points) { i_newch.set_data("num_cost", c_red); } else { i_newch.set_data("num_cost", c_white); } i_newch.set_data("text_description", trait_description(cur_trait)); } break; case '8': case 'k': case KEY_UP: { i_newch.add_data("list_traits", -1); int sel = i_newch.get_int("list_traits"); Trait_id cur_trait = selectable_traits[sel]; i_newch.set_data("num_cost", abs(trait_cost(cur_trait))); if (trait_cost(cur_trait) >= 0) { i_newch.set_data("text_cost", "<c=yellow>Cost:<c=/>"); } else { i_newch.set_data("text_cost", "<c=yellow>Earns:<c=/>"); } if (trait_cost(cur_trait) > points) { i_newch.set_data("num_cost", c_red); } else { i_newch.set_data("num_cost", c_white); } i_newch.set_data("text_description", trait_description(cur_trait)); } break; case '\n': case ' ': { int sel = i_newch.get_int("list_traits"); Trait_id cur_trait = selectable_traits[sel]; if (has_trait(cur_trait)) { traits[cur_trait] = false; points += trait_cost(cur_trait); num_traits--; traits_list = get_trait_list(this); } else if (points >= trait_cost(cur_trait) && num_traits < 5){ traits[cur_trait] = true; points -= trait_cost(cur_trait); num_traits++; traits_list = get_trait_list(this); } i_newch.set_data("num_traits_left", 5 - num_traits); if (num_traits >= 5) { i_newch.set_data("num_traits_left", c_red); } } break; } // switch (ch) } break; case NCS_PROFESSION: { switch (ch) { case '2': case 'j': case KEY_DOWN: { i_newch.add_data("list_professions", 1); std::string prof_name = i_newch.get_str("list_professions"); prof_name = remove_color_tags(prof_name); Profession* cur_prof = PROFESSIONS.lookup_name(prof_name); if (!cur_prof) { debugmsg("No such profession as '%s'!", prof_name.c_str()); return false; } i_newch.set_data("text_description", cur_prof->description); } break; case '8': case 'k': case KEY_UP: { i_newch.add_data("list_professions", -1); std::string prof_name = i_newch.get_str("list_professions"); prof_name = remove_color_tags(prof_name); Profession* cur_prof = PROFESSIONS.lookup_name(prof_name); if (!cur_prof) { debugmsg("No such profession as '%s'!", prof_name.c_str()); return false; } i_newch.set_data("text_description", cur_prof->description); } break; case '\n': case ' ': { std::string prof_name = i_newch.get_str("list_professions"); prof_name = remove_color_tags(prof_name); Profession* cur_prof = PROFESSIONS.lookup_name(prof_name); if (!cur_prof) { debugmsg("No such profession as '%s'!", prof_name.c_str()); return false; } set_profession(cur_prof); profession_list = get_profession_list(this); } break; } // switch (ch) } break; case NCS_DESCRIPTION: { if (ch == '/') { male = !male; if (male) { i_newch.set_data("text_male", "<c=yellow>Male<c=/>"); i_newch.set_data("text_female", "<c=dkgray>Female<c=/>"); } else { i_newch.set_data("text_male", "<c=dkgray>Male<c=/>"); i_newch.set_data("text_female", "<c=yellow>Female<c=/>"); } } else { /* Let the interface handle name entry; this includes cursor movement, * backspace, etc. The only downside is that this allows entry of "invalid" * name characters like "'&^%$#@ etc. Bad? */ cuss::element* entry = i_newch.find_by_name("entry_name"); entry->handle_keypress(ch); } } break; } // switch (cur_screen) } // key pressed isn't '<' or '>' if (changed_screen) { std::string filename = CUSS_DIR + "/i_newchar_"; switch (cur_screen) { case NCS_STATS: filename += "stats.cuss"; break; case NCS_TRAITS: filename += "traits.cuss"; break; case NCS_PROFESSION: filename += "profession.cuss"; break; case NCS_DESCRIPTION: filename += "description.cuss"; break; } if (!i_newch.load_from_file(filename)) { return false; } i_newch.ref_data("num_points", &points); switch (cur_screen) { case NCS_STATS: cur_stat = STATSEL_STR; i_newch.set_data("text_strength", "<c=ltblue>Strength<c=/>"); i_newch.set_data("text_dexterity", "<c=ltgray>Dexterity<c=/>"); i_newch.set_data("text_perception", "<c=ltgray>Perception<c=/>"); i_newch.set_data("text_intelligence", "<c=ltgray>Intelligence<c=/>"); i_newch.ref_data("num_strength", &stats.strength); i_newch.ref_data("num_dexterity", &stats.dexterity); i_newch.ref_data("num_perception", &stats.perception); i_newch.ref_data("num_intelligence", &stats.intelligence); i_newch.set_data("text_description", get_stat_description(cur_stat)); break; case NCS_TRAITS: { i_newch.select("list_traits"); i_newch.ref_data("list_traits", &traits_list); int sel = i_newch.get_int("list_traits"); Trait_id cur_trait = selectable_traits[sel]; i_newch.set_data("text_description", trait_description(cur_trait)); i_newch.set_data("num_cost", abs(trait_cost(cur_trait))); if (trait_cost(cur_trait) >= 0) { i_newch.set_data("text_cost", "<c=yellow>Cost:<c=/>"); } else { i_newch.set_data("text_cost", "<c=yellow>Earns:<c=/>"); } if (trait_cost(cur_trait) > points) { i_newch.set_data("num_cost", c_red); } else { i_newch.set_data("num_cost", c_white); } i_newch.set_data("num_traits_left", 5 - num_traits); if (num_traits >= 5) { i_newch.set_data("num_traits_left", c_red); } } break; case NCS_PROFESSION: { i_newch.select("list_professions"); i_newch.ref_data("list_professions", &profession_list); std::string prof_name = i_newch.get_str("list_professions"); prof_name = remove_color_tags(prof_name); Profession* cur_prof = PROFESSIONS.lookup_name(prof_name); if (!cur_prof) { debugmsg("No such profession as '%s'!", prof_name.c_str()); return false; } i_newch.set_data("text_description", cur_prof->description); } break; case NCS_DESCRIPTION: i_newch.ref_data("entry_name", &name); if (male) { i_newch.set_data("text_male", "<c=yellow>Male<c=/>"); i_newch.set_data("text_female", "<c=dkgray>Female<c=/>"); } else { i_newch.set_data("text_male", "<c=dkgray>Male<c=/>"); i_newch.set_data("text_female", "<c=yellow>Female<c=/>"); } break; } // switch (cur_screen) } // if (changed_screen) } // Now set up our skills and equipment based on our profession if (!profession) { debugmsg("Character creation finished without a profession!"); return false; } std::vector<Item_type_chance> prof_items = profession->items.item_types; for (int i = 0; i < prof_items.size(); i++) { int count = prof_items[i].number; Item tmp_it(prof_items[i].item); for (int i = 0; i < count; i++) { if (tmp_it.get_item_class() == ITEM_CLASS_CLOTHING) { items_worn.push_back(tmp_it); } else { inventory.push_back(tmp_it); } } } skills = profession->skills; // The "Durable" trait needs to be set up here. if (has_trait(TRAIT_DURABLE)) { for (int i = 0; i < HP_PART_MAX; i++) { current_hp[i] = 115; max_hp[i] = 115; } } // Myopic characters get free glasses if (has_trait(TRAIT_MYOPIC)) { Item_type* glasses = ITEM_TYPES.lookup_name("glasses"); if (!glasses) { debugmsg("No item 'glasses' exists - required for the Myopic trait!"); return false; } Item tmp_it(glasses); items_worn.push_back(tmp_it); } return true; }
// Why put this in a Big Switch? Why not let bionics have pointers to // functions, much like monsters and items? // // Well, because like diseases, which are also in a Big Switch, bionics don't // share functions.... void player::activate_bionic(int b, game *g) { bionic bio = my_bionics[b]; int power_cost = bionics[bio.id].power_cost; if (weapon.type->id == itm_bio_claws && bio.id == bio_claws) power_cost = 0; if (power_level < power_cost) { if (my_bionics[b].powered) { g->add_msg("Your %s powers down.", bionics[bio.id].name.c_str()); my_bionics[b].powered = false; } else g->add_msg("You cannot power your %s", bionics[bio.id].name.c_str()); return; } if (my_bionics[b].powered && my_bionics[b].charge > 0) { // Already-on units just lose a bit of charge my_bionics[b].charge--; } else { // Not-on units, or those with zero charge, have to pay the power cost if (bionics[bio.id].charge_time > 0) { my_bionics[b].powered = true; my_bionics[b].charge = bionics[bio.id].charge_time; } power_level -= power_cost; } std::string junk; std::vector<point> traj; std::vector<std::string> good; std::vector<std::string> bad; WINDOW* w; int dirx, diry, t, index; unsigned int l; item tmp_item; switch (bio.id) { case bio_painkiller: pkill += 6; pain -= 2; if (pkill > pain) pkill = pain; break; case bio_nanobots: healall(4); break; case bio_resonator: g->sound(posx, posy, 30, "VRRRRMP!"); for (int i = posx - 1; i <= posx + 1; i++) { for (int j = posy - 1; j <= posy + 1; j++) { g->m.bash(i, j, 40, junk); g->m.bash(i, j, 40, junk); // Multibash effect, so that doors &c will fall g->m.bash(i, j, 40, junk); if (g->m.is_destructable(i, j) && rng(1, 10) >= 4) g->m.ter(i, j) = t_rubble; } } break; case bio_time_freeze: moves += 100 * power_level; power_level = 0; g->add_msg("Your speed suddenly increases!"); if (one_in(3)) { g->add_msg("Your muscles tear with the strain."); hurt(g, bp_arms, 0, rng(5, 10)); hurt(g, bp_arms, 1, rng(5, 10)); hurt(g, bp_legs, 0, rng(7, 12)); hurt(g, bp_legs, 1, rng(7, 12)); hurt(g, bp_torso, 0, rng(5, 15)); } if (one_in(5)) add_disease(DI_TELEGLOW, rng(50, 400), g); break; case bio_teleport: g->teleport(); add_disease(DI_TELEGLOW, 300, g); break; // TODO: More stuff here (and bio_blood_filter) case bio_blood_anal: w = newwin(20, 40, 3, 10); wborder(w, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX ); if (has_disease(DI_FUNGUS)) bad.push_back("Fungal Parasite"); if (has_disease(DI_DERMATIK)) bad.push_back("Insect Parasite"); if (has_disease(DI_POISON)) bad.push_back("Poison"); if (radiation > 0) bad.push_back("Irradiated"); if (has_disease(DI_PKILL1)) good.push_back("Minor Painkiller"); if (has_disease(DI_PKILL2)) good.push_back("Moderate Painkiller"); if (has_disease(DI_PKILL3)) good.push_back("Heavy Painkiller"); if (has_disease(DI_PKILL_L)) good.push_back("Slow-Release Painkiller"); if (has_disease(DI_DRUNK)) good.push_back("Alcohol"); if (has_disease(DI_CIG)) good.push_back("Nicotine"); if (has_disease(DI_HIGH)) good.push_back("Intoxicant: Other"); if (has_disease(DI_TOOK_PROZAC)) good.push_back("Prozac"); if (has_disease(DI_TOOK_FLUMED)) good.push_back("Antihistamines"); if (has_disease(DI_ADRENALINE)) good.push_back("Adrenaline Spike"); if (good.size() == 0 && bad.size() == 0) mvwprintz(w, 1, 1, c_white, "No effects."); else { for (unsigned int line = 1; line < 39 && line <= good.size() + bad.size(); line++) { if (line <= bad.size()) mvwprintz(w, line, 1, c_red, bad[line - 1].c_str()); else mvwprintz(w, line, 1, c_green, good[line - 1 - bad.size()].c_str()); } } wrefresh(w); refresh(); getch(); delwin(w); break; case bio_blood_filter: rem_disease(DI_FUNGUS); rem_disease(DI_POISON); rem_disease(DI_PKILL1); rem_disease(DI_PKILL2); rem_disease(DI_PKILL3); rem_disease(DI_PKILL_L); rem_disease(DI_DRUNK); rem_disease(DI_CIG); rem_disease(DI_HIGH); rem_disease(DI_TOOK_PROZAC); rem_disease(DI_TOOK_FLUMED); rem_disease(DI_ADRENALINE); break; case bio_evap: if (query_yn("Drink directly? Otherwise you will need a container.")) { tmp_item = item(g->itypes[itm_water], 0); thirst -= 50; if (has_trait(PF_GOURMAND) && thirst < -60) { g->add_msg("You can't finish it all!"); thirst = -60; } else if (!has_trait(PF_GOURMAND) && thirst < -20) { g->add_msg("You can't finish it all!"); thirst = -20; } } else { t = g->inv("Choose a container:"); if (i_at(t).type == 0) { g->add_msg("You don't have that item!"); power_level += bionics[bio_evap].power_cost; } else if (!i_at(t).is_container()) { g->add_msg("That %s isn't a container!", i_at(t).tname().c_str()); power_level += bionics[bio_evap].power_cost; } else { it_container *cont = dynamic_cast<it_container*>(i_at(t).type); if (i_at(t).volume_contained() + 1 > cont->contains) { g->add_msg("There's no space left in your %s.", i_at(t).tname().c_str()); power_level += bionics[bio_evap].power_cost; } else if (!(cont->flags & con_wtight)) { g->add_msg("Your %s isn't watertight!", i_at(t).tname().c_str()); power_level += bionics[bio_evap].power_cost; } else { g->add_msg("You pour water into your %s.", i_at(t).tname().c_str()); i_at(t).put_in(item(g->itypes[itm_water], 0)); } } } break; case bio_lighter: g->draw(); mvprintw(0, 0, "Torch in which direction?"); get_direction(g, dirx, diry, input()); if (dirx == -2) { g->add_msg("Invalid direction."); power_level += bionics[bio_lighter].power_cost; return; } dirx += posx; diry += posy; if (!g->m.add_field(g, dirx, diry, fd_fire, 1)) // Unsuccessful. g->add_msg("You can't light a fire there."); break; case bio_claws: if (weapon.type->id == itm_bio_claws) { g->add_msg("You withdraw your claws."); weapon = ret_null; } else if (weapon.type->id != 0) { g->add_msg("Your claws extend, forcing you to drop your %s.", weapon.tname().c_str()); g->m.add_item(posx, posy, weapon); weapon = item(g->itypes[itm_bio_claws], 0); weapon.invlet = '#'; } else { g->add_msg("Your claws extend!"); weapon = item(g->itypes[itm_bio_claws], 0); weapon.invlet = '#'; } break; case bio_blaster: tmp_item = weapon; weapon = item(g->itypes[itm_bio_blaster], 0); weapon.curammo = dynamic_cast<it_ammo*>(g->itypes[itm_bio_fusion]); weapon.charges = 1; g->refresh_all(); g->plfire(false); weapon = tmp_item; break; case bio_laser: tmp_item = weapon; weapon = item(g->itypes[itm_v29], 0); weapon.curammo = dynamic_cast<it_ammo*>(g->itypes[itm_laser_pack]); weapon.charges = 1; g->refresh_all(); g->plfire(false); weapon = tmp_item; break; case bio_emp: g->draw(); mvprintw(0, 0, "Fire EMP in which direction?"); get_direction(g, dirx, diry, input()); if (dirx == -2) { g->add_msg("Invalid direction."); power_level += bionics[bio_emp].power_cost; return; } dirx += posx; diry += posy; g->emp_blast(dirx, diry); break; case bio_hydraulics: g->add_msg("Your muscles hiss as hydraulic strength fills them!"); break; case bio_water_extractor: for (unsigned int i = 0; i < g->m.i_at(posx, posy).size(); i++) { item tmp = g->m.i_at(posx, posy)[i]; if (tmp.type->id == itm_corpse && query_yn("Extract water from the %s", tmp.tname().c_str())) { i = g->m.i_at(posx, posy).size() + 1; // Loop is finished t = g->inv("Choose a container:"); if (i_at(t).type == 0) { g->add_msg("You don't have that item!"); power_level += bionics[bio_water_extractor].power_cost; } else if (!i_at(t).is_container()) { g->add_msg("That %s isn't a container!", i_at(t).tname().c_str()); power_level += bionics[bio_water_extractor].power_cost; } else { it_container *cont = dynamic_cast<it_container*>(i_at(t).type); if (i_at(t).volume_contained() + 1 > cont->contains) { g->add_msg("There's no space left in your %s.", i_at(t).tname().c_str()); power_level += bionics[bio_water_extractor].power_cost; } else { g->add_msg("You pour water into your %s.", i_at(t).tname().c_str()); i_at(t).put_in(item(g->itypes[itm_water], 0)); } } } if (i == g->m.i_at(posx, posy).size() - 1) // We never chose a corpse power_level += bionics[bio_water_extractor].power_cost; } break; case bio_magnet: for (int i = posx - 10; i <= posx + 10; i++) { for (int j = posy - 10; j <= posy + 10; j++) { if (g->m.i_at(i, j).size() > 0) { if (g->m.sees(i, j, posx, posy, -1, t)) traj = line_to(i, j, posx, posy, t); else traj = line_to(i, j, posx, posy, 0); } traj.insert(traj.begin(), point(i, j)); for (unsigned int k = 0; k < g->m.i_at(i, j).size(); k++) { if (g->m.i_at(i, j)[k].made_of(IRON) || g->m.i_at(i, j)[k].made_of(STEEL)){ tmp_item = g->m.i_at(i, j)[k]; g->m.i_rem(i, j, k); for (l = 0; l < traj.size(); l++) { index = g->mon_at(traj[l].x, traj[l].y); if (index != -1) { if (g->z[index].hurt(tmp_item.weight() * 2)) g->kill_mon(index, true); g->m.add_item(traj[l].x, traj[l].y, tmp_item); l = traj.size() + 1; } else if (l > 0 && g->m.move_cost(traj[l].x, traj[l].y) == 0) { g->m.bash(traj[l].x, traj[l].y, tmp_item.weight() * 2, junk); g->sound(traj[l].x, traj[l].y, 12, junk); if (g->m.move_cost(traj[l].x, traj[l].y) == 0) { g->m.add_item(traj[l - 1].x, traj[l - 1].y, tmp_item); l = traj.size() + 1; } } } if (l == traj.size()) g->m.add_item(posx, posy, tmp_item); } } } } break; case bio_lockpick: g->draw(); mvprintw(0, 0, "Unlock in which direction?"); get_direction(g, dirx, diry, input()); if (dirx == -2) { g->add_msg("Invalid direction."); power_level += bionics[bio_lockpick].power_cost; return; } dirx += posx; diry += posy; if (g->m.ter(dirx, diry) == t_door_locked) { moves -= 40; g->add_msg("You unlock the door."); g->m.ter(dirx, diry) = t_door_c; } else g->add_msg("You can't unlock that %s.", g->m.tername(dirx, diry).c_str()); break; // Unused enums added for completeness. default: break; } }
void game::show_options() { WINDOW* w_options_border = newwin(25, 80, (TERMY > 25) ? (TERMY-25)/2 : 0, (TERMX > 80) ? (TERMX-80)/2 : 0); WINDOW* w_options = newwin(23, 78, 1 + ((TERMY > 25) ? (TERMY-25)/2 : 0), 1 + ((TERMX > 80) ? (TERMX-80)/2 : 0)); int offset = 1; const int MAX_LINE = 22; int line = 0; char ch = ' '; bool changed_options = false; bool needs_refresh = true; wborder(w_options_border, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX); mvwprintz(w_options_border, 0, 36, c_ltred, " OPTIONS "); wrefresh(w_options_border); do { // TODO: change instructions if(needs_refresh) { werase(w_options); mvwprintz(w_options, 0, 40, c_white, "Use up/down keys to scroll through"); mvwprintz(w_options, 1, 40, c_white, "available options."); mvwprintz(w_options, 2, 40, c_white, "Use left/right keys to toggle."); mvwprintz(w_options, 3, 40, c_white, "Press ESC or q to return. "); // highlight options for option descriptions std::string tmp = option_desc(option_key(offset + line)); std::string out; size_t pos; int displayline = 5; do { pos = tmp.find_first_of('\n'); out = tmp.substr(0, pos); mvwprintz(w_options, displayline, 40, c_white, out.c_str()); tmp = tmp.substr(pos + 1); displayline++; } while(pos != std::string::npos && displayline < 12); needs_refresh = false; } // Clear the lines for(int i = 0; i < 25; i++) { mvwprintz(w_options, i, 0, c_black, " "); } int valid_option_count = 0; // display options for(int i = 0; i < 26 && offset + i < NUM_OPTION_KEYS; i++) { valid_option_count++; mvwprintz(w_options, i, 0, c_white, "%s: ", option_name(option_key(offset + i)).c_str()); if(option_is_bool(option_key(offset + i))) { bool on = OPTIONS[ option_key(offset + i) ]; if(i == line) { mvwprintz(w_options, i, 30, hilite(c_ltcyan), (on ? "True" : "False")); } else { mvwprintz(w_options, i, 30, (on ? c_ltgreen : c_ltred), (on ? "True" : "False")); } } else { char option_val = OPTIONS[ option_key(offset + i) ]; if(i == line) { mvwprintz(w_options, i, 30, hilite(c_ltcyan), "%d", option_val); } else { mvwprintz(w_options, i, 30, c_ltgreen, "%d", option_val); } } } wrefresh(w_options); ch = input(); needs_refresh = true; switch(ch) { // move up and down case 'j': line++; if(line > MAX_LINE/2 && offset + 1 < NUM_OPTION_KEYS - MAX_LINE) { ++offset; --line; } if(line > MAX_LINE) { line = 0; offset = 1; } break; case 'k': line--; if(line < MAX_LINE/2 && offset > 1) { --offset; ++line; } if(line < 0) { line = MAX_LINE; offset = NUM_OPTION_KEYS - MAX_LINE - 1; } break; // toggle options with left/right keys case 'h': if(option_is_bool(option_key(offset + line))) { OPTIONS[ option_key(offset + line) ] = !(OPTIONS[ option_key(offset + line) ]); } else { OPTIONS[ option_key(offset + line) ]--; if((OPTIONS[ option_key(offset + line) ]) < option_min_options(option_key(offset + line))) { OPTIONS[ option_key(offset + line) ] = option_max_options(option_key(offset + line)) - 1; } } changed_options = true; break; case 'l': if(option_is_bool(option_key(offset + line))) { OPTIONS[ option_key(offset + line) ] = !(OPTIONS[ option_key(offset + line) ]); } else { OPTIONS[ option_key(offset + line) ]++; if((OPTIONS[ option_key(offset + line) ]) >= option_max_options(option_key(offset + line))) { OPTIONS[ option_key(offset + line) ] = option_min_options(option_key(offset + line)); } } changed_options = true; break; } if(changed_options && OPTIONS[OPT_SEASON_LENGTH] < 1) { OPTIONS[OPT_SEASON_LENGTH]=option_max_options(OPT_SEASON_LENGTH)-1; } } while(ch != 'q' && ch != 'Q' && ch != KEY_ESCAPE); if(changed_options && query_yn("Save changes?")) { save_options(); trigdist=(OPTIONS[OPT_CIRCLEDIST] ? true : false); } werase(w_options); }
void show_auto_pickup() { save_reset_changes(false); const int iHeaderHeight = 4; const int iContentHeight = FULL_SCREEN_HEIGHT-2-iHeaderHeight; 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; mapLines[50] = true; mapLines[54] = true; const int iTotalCols = mapLines.size()-1; WINDOW* w_auto_pickup_options = newwin(FULL_SCREEN_HEIGHT/2, FULL_SCREEN_WIDTH/2, iOffsetY + (FULL_SCREEN_HEIGHT/2)/2, iOffsetX + (FULL_SCREEN_WIDTH/2)/2); WINDOW* w_auto_pickup_help = newwin((FULL_SCREEN_HEIGHT/2)-2, FULL_SCREEN_WIDTH * 3/4, 8 + iOffsetY + (FULL_SCREEN_HEIGHT/2)/2, iOffsetX + 19/2); WINDOW* w_auto_pickup_border = newwin(FULL_SCREEN_HEIGHT, FULL_SCREEN_WIDTH, iOffsetY, iOffsetX); WINDOW* w_auto_pickup_header = newwin(iHeaderHeight, FULL_SCREEN_WIDTH - 2, 1 + iOffsetY, 1 + iOffsetX); WINDOW* w_auto_pickup = newwin(iContentHeight, FULL_SCREEN_WIDTH - 2, iHeaderHeight + 1 + iOffsetY, 1 + iOffsetX); wborder(w_auto_pickup_border, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX); mvwputch(w_auto_pickup_border, 3, 0, c_ltgray, LINE_XXXO); // |- mvwputch(w_auto_pickup_border, 3, 79, c_ltgray, LINE_XOXX); // -| for (std::map<int, bool>::iterator iter = mapLines.begin(); iter != mapLines.end(); ++iter) { mvwputch(w_auto_pickup_border, FULL_SCREEN_HEIGHT-1, iter->first + 1, c_ltgray, LINE_XXOX); // _|_ } mvwprintz(w_auto_pickup_border, 0, 29, c_ltred, _(" AUTO PICKUP MANAGER ")); wrefresh(w_auto_pickup_border); int tmpx = 0; tmpx += shortcut_print(w_auto_pickup_header, 0, tmpx, c_white, c_ltgreen, _("<A>dd"))+2; tmpx += shortcut_print(w_auto_pickup_header, 0, tmpx, c_white, c_ltgreen, _("<R>emove"))+2; tmpx += shortcut_print(w_auto_pickup_header, 0, tmpx, c_white, c_ltgreen, _("<C>opy"))+2; tmpx += shortcut_print(w_auto_pickup_header, 0, tmpx, c_white, c_ltgreen, _("<M>ove"))+2; tmpx += shortcut_print(w_auto_pickup_header, 0, tmpx, c_white, c_ltgreen, _("<E>nable"))+2; tmpx += shortcut_print(w_auto_pickup_header, 0, tmpx, c_white, c_ltgreen, _("<D>isable"))+2; shortcut_print(w_auto_pickup_header, 0, tmpx, c_white, c_ltgreen, _("<T>est")); tmpx = 0; tmpx += shortcut_print(w_auto_pickup_header, 1, tmpx, c_white, c_ltgreen, _("<+-> Move up/down"))+2; tmpx += shortcut_print(w_auto_pickup_header, 1, tmpx, c_white, c_ltgreen, _("<Enter>-Edit"))+2; shortcut_print(w_auto_pickup_header, 1, tmpx, c_white, c_ltgreen, _("<Tab>-Switch Page")); for (int i = 0; i < 78; i++) { if (mapLines[i]) { mvwputch(w_auto_pickup_header, 2, i, c_ltgray, LINE_OXXX); mvwputch(w_auto_pickup_header, 3, i, c_ltgray, LINE_XOXO); } else { mvwputch(w_auto_pickup_header, 2, i, c_ltgray, LINE_OXOX); // Draw line under header } } mvwprintz(w_auto_pickup_header, 3, 0, c_white, "#"); mvwprintz(w_auto_pickup_header, 3, 7, c_white, _("Rules")); mvwprintz(w_auto_pickup_header, 3, 51, c_white, _("I/E")); wrefresh(w_auto_pickup_header); int iCurrentPage = 1; int iCurrentLine = 0; int iCurrentCol = 1; int iStartPos = 0; bool bStuffChanged = false; char ch = ' '; std::stringstream sTemp; do { int locx = 17; locx += shortcut_print(w_auto_pickup_header, 2, locx, c_white, (iCurrentPage == 1) ? hilite(c_white) : c_white, _("[<Global>]"))+1; shortcut_print(w_auto_pickup_header, 2, locx, c_white, (iCurrentPage == 2) ? hilite(c_white) : c_white, _("[<Character>]")); wrefresh(w_auto_pickup_header); // Clear the lines for (int i = 0; i < iContentHeight; i++) { for (int j = 0; j < 79; j++) { if (mapLines[j]) { mvwputch(w_auto_pickup, i, j, c_ltgray, LINE_XOXO); } else { mvwputch(w_auto_pickup, i, j, c_black, ' '); } } } if (iCurrentPage == 1 || iCurrentPage == 2) { if (iCurrentPage == 2 && g->u.name == "") { vAutoPickupRules[2].clear(); mvwprintz(w_auto_pickup, 8, 15, c_white, _("Please load a character first to use this page!")); } //Draw Scrollbar draw_scrollbar(w_auto_pickup_border, iCurrentLine, iContentHeight, vAutoPickupRules[iCurrentPage].size(), 5); calcStartPos(iStartPos, iCurrentLine, iContentHeight, vAutoPickupRules[iCurrentPage].size()); // display auto pickup for (int i = iStartPos; i < vAutoPickupRules[iCurrentPage].size(); i++) { if (i >= iStartPos && i < iStartPos + ((iContentHeight > vAutoPickupRules[iCurrentPage].size()) ? vAutoPickupRules[iCurrentPage].size() : iContentHeight)) { nc_color cLineColor = (vAutoPickupRules[iCurrentPage][i].bActive) ? c_white : c_ltgray; sTemp.str(""); sTemp << i + 1; mvwprintz(w_auto_pickup, i - iStartPos, 0, cLineColor, sTemp.str().c_str()); mvwprintz(w_auto_pickup, i - iStartPos, 4, cLineColor, ""); if (iCurrentLine == i) { wprintz(w_auto_pickup, c_yellow, ">> "); } else { wprintz(w_auto_pickup, c_yellow, " "); } wprintz(w_auto_pickup, (iCurrentLine == i && iCurrentCol == 1) ? hilite(cLineColor) : cLineColor, "%s", ((vAutoPickupRules[iCurrentPage][i].sRule == "") ? _("<empty rule>") : vAutoPickupRules[iCurrentPage][i].sRule).c_str()); mvwprintz(w_auto_pickup, i - iStartPos, 52, (iCurrentLine == i && iCurrentCol == 2) ? hilite(cLineColor) : cLineColor, "%s", ((vAutoPickupRules[iCurrentPage][i].bExclude) ? rm_prefix(_("<Exclude>E")).c_str() : rm_prefix(_("<Include>I")).c_str())); } } wrefresh(w_auto_pickup); } else if (iCurrentPage == 3) { wborder(w_auto_pickup_options, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX); mvwprintz(w_auto_pickup_options, 5, 10, c_white, _("Under construction!")); wrefresh(w_auto_pickup); wrefresh(w_auto_pickup_options); } ch = (char)input(); if (iCurrentPage == 3) { switch(ch) { case '\t': //Switch to next Page iCurrentPage++; if (iCurrentPage > 3) { iCurrentPage = 1; iCurrentLine = 0; } break; } } else if (iCurrentPage == 1 || iCurrentPage == 2) { if (iCurrentPage == 2 && g->u.name == "" && ch != '\t') { //Only allow loaded games to use the char sheet } else if (vAutoPickupRules[iCurrentPage].size() > 0 || ch == 'a' || ch == '\t') { switch(ch) { case 'j': //move down iCurrentLine++; iCurrentCol = 1; if (iCurrentLine >= vAutoPickupRules[iCurrentPage].size()) { iCurrentLine = 0; } break; case 'k': //move up iCurrentLine--; iCurrentCol = 1; if (iCurrentLine < 0) { iCurrentLine = vAutoPickupRules[iCurrentPage].size()-1; } break; case 'a': //add new rule case 'A': bStuffChanged = true; vAutoPickupRules[iCurrentPage].push_back(cPickupRules("", true, false)); iCurrentLine = vAutoPickupRules[iCurrentPage].size()-1; break; case 'r': //remove rule case 'R': bStuffChanged = true; vAutoPickupRules[iCurrentPage].erase(vAutoPickupRules[iCurrentPage].begin() + iCurrentLine); if (iCurrentLine > vAutoPickupRules[iCurrentPage].size()-1) { iCurrentLine--; } break; case 'c': //copy rule case 'C': bStuffChanged = true; vAutoPickupRules[iCurrentPage].push_back(cPickupRules(vAutoPickupRules[iCurrentPage][iCurrentLine].sRule, vAutoPickupRules[iCurrentPage][iCurrentLine].bActive, vAutoPickupRules[iCurrentPage][iCurrentLine].bExclude)); iCurrentLine = vAutoPickupRules[iCurrentPage].size()-1; break; case 'm': //move rule global <-> character case 'M': if ((iCurrentPage == 1 && g->u.name != "") || iCurrentPage == 2) { bStuffChanged = true; //copy over vAutoPickupRules[(iCurrentPage == 1) ? 2 : 1].push_back(cPickupRules(vAutoPickupRules[iCurrentPage][iCurrentLine].sRule, vAutoPickupRules[iCurrentPage][iCurrentLine].bActive, vAutoPickupRules[iCurrentPage][iCurrentLine].bExclude)); //remove old vAutoPickupRules[iCurrentPage].erase(vAutoPickupRules[iCurrentPage].begin() + iCurrentLine); iCurrentLine = vAutoPickupRules[(iCurrentPage == 1) ? 2 : 1].size()-1; iCurrentPage = (iCurrentPage == 1) ? 2 : 1; } break; case '\t': //Switch to next Page iCurrentPage++; if (iCurrentPage > 2) { iCurrentPage = 1; iCurrentLine = 0; } break; case '\n': //Edit Col in current line bStuffChanged = true; if (iCurrentCol == 1) { fold_and_print(w_auto_pickup_help, 1, 1, 999, c_white, _( "* is used as a Wildcard. A few Examples:\n" "\n" "wood arrow matches the itemname exactly\n" "wood ar* matches items beginning with wood ar\n" "*rrow matches items ending with rrow\n" "*avy fle*fi*arrow multible * are allowed\n" "heAVY*woOD*arrOW case insesitive search\n" "") ); wborder(w_auto_pickup_help, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX); wrefresh(w_auto_pickup_help); vAutoPickupRules[iCurrentPage][iCurrentLine].sRule = trim_rule(string_input_popup(_("Pickup Rule:"), 30, vAutoPickupRules[iCurrentPage][iCurrentLine].sRule)); } else if (iCurrentCol == 2) { vAutoPickupRules[iCurrentPage][iCurrentLine].bExclude = !vAutoPickupRules[iCurrentPage][iCurrentLine].bExclude; } break; case 'e': //enable rule case 'E': bStuffChanged = true; vAutoPickupRules[iCurrentPage][iCurrentLine].bActive = true; break; case 'd': //disable rule case 'D': bStuffChanged = true; vAutoPickupRules[iCurrentPage][iCurrentLine].bActive = false; break; case 'h': //move left iCurrentCol--; if (iCurrentCol < 1) { iCurrentCol = iTotalCols; } break; case 'l': //move right iCurrentCol++; if (iCurrentCol > iTotalCols) { iCurrentCol = 1; } break; case '+': //move rule up bStuffChanged = true; if (iCurrentLine < vAutoPickupRules[iCurrentPage].size()-1) { std::swap(vAutoPickupRules[iCurrentPage][iCurrentLine], vAutoPickupRules[iCurrentPage][iCurrentLine+1]); iCurrentLine++; iCurrentCol = 1; } break; case '-': //move rule down bStuffChanged = true; if (iCurrentLine > 0) { std::swap(vAutoPickupRules[iCurrentPage][iCurrentLine], vAutoPickupRules[iCurrentPage][iCurrentLine-1]); iCurrentLine--; iCurrentCol = 1; } break; case 't': //test rule case 'T': test_pattern(iCurrentPage, iCurrentLine); break; } } } } while(ch != 'q' && ch != 'Q' && ch != KEY_ESCAPE); if (bStuffChanged) { if(query_yn(_("Save changes?"))) { save_auto_pickup(false); if (g->u.name != "") { save_auto_pickup(true); } } else { save_reset_changes(true); } } werase(w_auto_pickup); werase(w_auto_pickup_border); werase(w_auto_pickup_header); werase(w_auto_pickup_options); werase(w_auto_pickup_help); }
void input_context::display_help() { inp_mngr.set_timeout(-1); // Shamelessly stolen from help.cpp WINDOW *w_help = newwin(FULL_SCREEN_HEIGHT - 2, FULL_SCREEN_WIDTH - 2, 1 + (int)((TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0), 1 + (int)((TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0)); // has the user changed something? bool changed = false; // keybindings before the user changed anything. input_manager::t_action_contexts old_action_contexts(inp_mngr.action_contexts); // current status: adding/removing/showing keybindings enum { s_remove, s_add, s_add_global, s_show } status = s_show; // copy of registered_actions, but without the ANY_INPUT and COORDINATE, which should not be shown std::vector<std::string> org_registered_actions(registered_actions); std::vector<std::string>::iterator any_input = std::find(org_registered_actions.begin(), org_registered_actions.end(), ANY_INPUT); if (any_input != org_registered_actions.end()) { org_registered_actions.erase(any_input); } std::vector<std::string>::iterator coordinate = std::find(org_registered_actions.begin(), org_registered_actions.end(), COORDINATE); if (coordinate != org_registered_actions.end()) { org_registered_actions.erase(coordinate); } // colors of the keybindings static const nc_color global_key = c_ltgray; static const nc_color local_key = c_ltgreen; static const nc_color unbound_key = c_ltred; // (vertical) scroll offset size_t scroll_offset = 0; // height of the area usable for display of keybindings, excludes headers & borders const size_t display_height = FULL_SCREEN_HEIGHT - 9 - 2; // -2 for the border // width of the legend const size_t legwidth = FULL_SCREEN_WIDTH - 4 - 2; // keybindings help std::ostringstream legend; legend << "<color_" << string_from_color(unbound_key) << ">" << _("Unbound keys") << "</color>\n"; legend << "<color_" << string_from_color(local_key) << ">" << _("Keybinding active only on this screen") << "</color>\n"; legend << "<color_" << string_from_color(global_key) << ">" << _("Keybinding active globally") << "</color>\n"; legend << _("Press - to remove keybinding\nPress + to add local keybinding\nPress = to add global keybinding\n"); input_context ctxt("HELP_KEYBINDINGS"); ctxt.register_action("UP", _("Scroll up")); ctxt.register_action("DOWN", _("Scroll down")); ctxt.register_action("PAGE_DOWN"); ctxt.register_action("PAGE_UP"); ctxt.register_action("REMOVE"); ctxt.register_action("ADD_LOCAL"); ctxt.register_action("ADD_GLOBAL"); ctxt.register_action("QUIT"); ctxt.register_action("ANY_INPUT"); if (category != "HELP_KEYBINDINGS") { // avoiding inception! ctxt.register_action("HELP_KEYBINDINGS"); } std::string hotkeys = ctxt.get_available_single_char_hotkeys(display_help_hotkeys); while(true) { werase(w_help); draw_border(w_help); draw_scrollbar(w_help, scroll_offset, display_height, org_registered_actions.size() - display_height, 8); mvwprintz(w_help, 0, (FULL_SCREEN_WIDTH - utf8_width(_("Keybindings"))) / 2 - 1, c_ltred, " %s ", _("Keybindings")); fold_and_print(w_help, 1, 2, legwidth, c_white, legend.str()); for (size_t i = 0; i + scroll_offset < org_registered_actions.size() && i < display_height; i++) { const std::string &action_id = org_registered_actions[i + scroll_offset]; bool overwrite_default; const action_attributes &attributes = inp_mngr.get_action_attributes(action_id, category, &overwrite_default); char invlet; if (i < hotkeys.size()) { invlet = hotkeys[i]; } else { invlet = ' '; } if (status == s_add_global && overwrite_default) { // We're trying to add a global, but this action has a local // defined, so gray out the invlet. mvwprintz(w_help, i + 8, 2, c_dkgray, "%c ", invlet); } else if (status == s_add || status == s_add_global) { mvwprintz(w_help, i + 8, 2, c_blue, "%c ", invlet); } else if (status == s_remove) { mvwprintz(w_help, i + 8, 2, c_blue, "%c ", invlet); } else { mvwprintz(w_help, i + 8, 2, c_blue, " "); } nc_color col; if (attributes.input_events.empty()) { col = unbound_key; } else if (overwrite_default) { col = local_key; } else { col = global_key; } mvwprintz(w_help, i + 8, 4, col, "%s: ", get_action_name(action_id).c_str()); mvwprintz(w_help, i + 8, 52, col, "%s", get_desc(action_id).c_str()); } wrefresh(w_help); refresh(); // In addition to the modifiable hotkeys, we also check for hardcoded // keys, e.g. '+', '-', '=', in order to prevent the user from // entering an unrecoverable state. const std::string action = ctxt.handle_input(); const long raw_input_char = ctxt.get_raw_input().get_first_input(); if (action == "ADD_LOCAL" || raw_input_char == '+') { status = s_add; } else if (action == "ADD_GLOBAL" || raw_input_char == '=') { status = s_add_global; } else if (action == "REMOVE" || raw_input_char == '-') { status = s_remove; } else if (action == "ANY_INPUT") { const size_t hotkey_index = hotkeys.find_first_of(raw_input_char); if (status == s_show || hotkey_index == std::string::npos ) { continue; } const size_t action_index = hotkey_index + scroll_offset; if( action_index >= org_registered_actions.size() ) { continue; } const std::string &action_id = org_registered_actions[action_index]; // Check if this entry is local or global. bool is_local = false; inp_mngr.get_action_attributes(action_id, category, &is_local); const std::string name = get_action_name(action_id); if (status == s_remove && (!OPTIONS["QUERY_KEYBIND_REMOVAL"] || query_yn(_("Clear keys for %s?"), name.c_str()))) { // If it's global, reset the global actions. std::string category_to_access = category; if (!is_local) { category_to_access = default_context_id; } inp_mngr.remove_input_for_action(action_id, category_to_access); changed = true; } else if (status == s_add_global && is_local) { // Disallow adding global actions to an action that already has a local defined. popup(_("There are already local keybindings defined for this action, please remove them first.")); } else if (status == s_add || status == s_add_global) { const long newbind = popup_getkey(_("New key for %s:"), name.c_str()); const input_event new_event(newbind, CATA_INPUT_KEYBOARD); const std::string conflicts = get_conflicts(new_event); const bool has_conflicts = !conflicts.empty(); bool resolve_conflicts = false; if (has_conflicts) { resolve_conflicts = query_yn( _("This key conflicts with %s. Remove this key from the conflicting command(s), and continue?"), conflicts.c_str()); } if (!has_conflicts || resolve_conflicts) { if (resolve_conflicts) { clear_conflicting_keybindings(new_event); } // We might be adding a local or global action. std::string category_to_access = category; if (status == s_add_global) { category_to_access = default_context_id; } inp_mngr.add_input_for_action(action_id, category_to_access, new_event); changed = true; } } status = s_show; } else if (action == "DOWN") { if (scroll_offset < org_registered_actions.size() - display_height) { scroll_offset++; } } else if (action == "UP") { if (scroll_offset > 0) { scroll_offset--; } } else if (action == "PAGE_DOWN") { if( scroll_offset + display_height < org_registered_actions.size() ) { scroll_offset += std::min(display_height, org_registered_actions.size() - display_height - scroll_offset); } else if( org_registered_actions.size() > display_height ) { scroll_offset = 0; } } else if( action == "PAGE_UP" ) { if( scroll_offset >= display_height ) { scroll_offset -= display_height; } else if( scroll_offset > 0 ) { scroll_offset = 0; } else if( org_registered_actions.size() > display_height ) { scroll_offset = org_registered_actions.size() - display_height; } } else if (action == "QUIT") { if (status != s_show) { status = s_show; } else { break; } } else if (action == "HELP_KEYBINDINGS") { // update available hotkeys in case they've changed hotkeys = ctxt.get_available_single_char_hotkeys(display_help_hotkeys); } } if (changed && query_yn(_("Save changes?"))) { try { inp_mngr.save(); } catch(std::exception &err) { popup(_("saving keybindings failed: %s"), err.what()); } catch(std::string &err) { popup(_("saving keybindings failed: %s"), err.c_str()); } } else if(changed) { inp_mngr.action_contexts.swap(old_action_contexts); } werase(w_help); wrefresh(w_help); delwin(w_help); }