From 782fc417aa391d89618bce7c548dc5337ea6628f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jianxiang=20Wang=20=28=E7=8E=8B=E5=81=A5=E7=BF=94=29?= Date: Thu, 19 Sep 2019 18:20:58 +0800 Subject: [PATCH] Refactor base camp code to make it more sane, and fix translation issues (#34058) * Fix basecamp translation * Hide scrollbar when all camp mission info fits in the window * Fix camp mission descriptions untranslated * Make camp mission direction code sane, and allow translating the direction text * Fix comments and clang-tidy warnings * Make VS happy --- doc/TRANSLATING.md | 4 + lang/extract_json_strings.py | 2 + src/artifact.cpp | 30 ++- src/basecamp.cpp | 73 ++++-- src/basecamp.h | 81 +++++-- src/faction.cpp | 3 +- src/faction_camp.cpp | 457 +++++++++++++++++------------------ src/faction_camp.h | 24 +- src/item.cpp | 8 +- src/item_factory.cpp | 4 +- src/itype.h | 2 +- src/mission_companion.cpp | 82 +++---- src/mission_companion.h | 10 +- src/recipe.cpp | 2 +- src/recipe.h | 7 +- src/recipe_groups.cpp | 32 +-- src/recipe_groups.h | 7 +- src/savegame_json.cpp | 11 +- 18 files changed, 441 insertions(+), 398 deletions(-) diff --git a/doc/TRANSLATING.md b/doc/TRANSLATING.md index 32ca92bb6fdd5..337a7b31c9db3 100644 --- a/doc/TRANSLATING.md +++ b/doc/TRANSLATING.md @@ -261,6 +261,10 @@ new syntax "name" would be a `dict`, which may break unmigrated script. | Spell messages and monster spell messages | Martial art names and descriptions | Mission names and descriptions +| Recipe blueprint names +| Recipe group recipe descriptions +| Item descriptions +| Recipe descriptions ### Recommendations diff --git a/lang/extract_json_strings.py b/lang/extract_json_strings.py index 6aad178446f5b..347a0d5ff867f 100755 --- a/lang/extract_json_strings.py +++ b/lang/extract_json_strings.py @@ -509,6 +509,8 @@ def extract_recipes(item): writestr(outfile, arr[2]) if "description" in item: writestr(outfile, item["description"]) + if "blueprint_name" in item: + writestr(outfile, item["blueprint_name"]) def extract_recipe_group(item): diff --git a/src/artifact.cpp b/src/artifact.cpp index 9dc150d4477c0..f7a2d590da5d2 100644 --- a/src/artifact.cpp +++ b/src/artifact.cpp @@ -710,9 +710,10 @@ std::string new_artifact() def.create_name( newname.str() ); } } - def.description = string_format( - _( "This is the %s.\nIt is the only one of its kind.\nIt may have unknown powers; try activating them." ), - def.nname( 1 ) ); + def.description = no_translation( + string_format( + _( "This is the %s.\nIt is the only one of its kind.\nIt may have unknown powers; try activating them." ), + def.nname( 1 ) ) ); // Finally, pick some powers art_effect_passive passive_tmp = AEP_NULL; @@ -887,7 +888,7 @@ std::string new_artifact() } } - def.description = description.str(); + def.description = no_translation( description.str() ); // Finally, pick some effects int num_good = 0; @@ -939,8 +940,9 @@ std::string new_natural_artifact( artifact_natural_property prop ) def.m_to_hit = 0; def.create_name( _( property_data.name ), _( shape_data.name ) ); - def.description = string_format( pgettext( "artifact description", "This %1$s %2$s." ), - _( shape_data.desc ), _( property_data.desc ) ); + def.description = no_translation( + string_format( pgettext( "artifact description", "This %1$s %2$s." ), + _( shape_data.desc ), _( property_data.desc ) ) ); // Three possibilities: good passive + bad passive, good active + bad active, // and bad passive + good active @@ -1054,7 +1056,9 @@ std::string architects_cube() def.item_tags.insert( weapon.tag ); } // Add an extra weapon perhaps? - def.description = _( "The architect's cube." ); + // Most artifact descriptions are generated and stored using `no_translation`, + // also do it here for consistency + def.description = no_translation( _( "The architect's cube." ) ); def.artifact->effects_carried.push_back( AEP_SUPER_CLAIRVOYANCE ); item_controller->add_item_type( static_cast( def ) ); return def.get_id(); @@ -1129,7 +1133,7 @@ void it_artifact_tool::deserialize( JsonObject &jo ) { id = jo.get_string( "id" ); name = jo.get_string( "name" ); - description = jo.get_string( "description" ); + description = no_translation( jo.get_string( "description" ) ); if( jo.has_int( "sym" ) ) { sym = std::string( 1, jo.get_int( "sym" ) ); } else { @@ -1244,7 +1248,7 @@ void it_artifact_armor::deserialize( JsonObject &jo ) { id = jo.get_string( "id" ); name = jo.get_string( "name" ); - description = jo.get_string( "description" ); + description = no_translation( jo.get_string( "description" ) ); if( jo.has_int( "sym" ) ) { sym = std::string( 1, jo.get_int( "sym" ) ); } else { @@ -1336,7 +1340,9 @@ void it_artifact_tool::serialize( JsonOut &json ) const // generic data json.member( "id", id ); json.member( "name", name ); - json.member( "description", description ); + // Artifact descriptions are always constructed using `no_translation`, + // so `translated()` here only retrieves the underlying string + json.member( "description", description.translated() ); json.member( "sym", sym ); json.member( "color", color ); json.member( "price", price ); @@ -1390,7 +1396,9 @@ void it_artifact_armor::serialize( JsonOut &json ) const // generic data json.member( "id", id ); json.member( "name", name ); - json.member( "description", description ); + // Artifact descriptions are always constructed using `no_translation`, + // so `translated()` here only retrieves the underlying string + json.member( "description", description.translated() ); json.member( "sym", sym ); json.member( "color", color ); json.member( "price", price ); diff --git a/src/basecamp.cpp b/src/basecamp.cpp index bf6e047382513..62eb6ac781445 100644 --- a/src/basecamp.cpp +++ b/src/basecamp.cpp @@ -34,6 +34,30 @@ #include "flat_set.h" #include "line.h" + +const std::map base_camps::all_directions = { + // direction, direction id, tab order, direction abbreviation with bracket, direction tab title + { base_camps::base_dir, { "[B]", base_camps::TAB_MAIN, to_translation( "base camp: base", "[B]" ), to_translation( "base camp: base", " MAIN " ) } }, + { point_north, { "[N]", base_camps::TAB_N, to_translation( "base camp: north", "[N]" ), to_translation( "base camp: north", " [N] " ) } }, + { point_north_east, { "[NE]", base_camps::TAB_NE, to_translation( "base camp: northeast", "[NE]" ), to_translation( "base camp: northeast", " [NE] " ) } }, + { point_east, { "[E]", base_camps::TAB_E, to_translation( "base camp: east", "[E]" ), to_translation( "base camp: east", " [E] " ) } }, + { point_south_east, { "[SE]", base_camps::TAB_SE, to_translation( "base camp: southeast", "[SE]" ), to_translation( "base camp: southeast", " [SE] " ) } }, + { point_south, { "[S]", base_camps::TAB_S, to_translation( "base camp: south", "[S]" ), to_translation( "base camp: south", " [S] " ) } }, + { point_south_west, { "[SW]", base_camps::TAB_SW, to_translation( "base camp: southwest", "[SW]" ), to_translation( "base camp: southwest", " [SW] " ) } }, + { point_west, { "[W]", base_camps::TAB_W, to_translation( "base camp: west", "[W]" ), to_translation( "base camp: west", " [W] " ) } }, + { point_north_west, { "[NW]", base_camps::TAB_NW, to_translation( "base camp: northwest", "[NW]" ), to_translation( "base camp: northwest", " [NW] " ) } }, +}; + +point base_camps::direction_from_id( const std::string &id ) +{ + for( const auto &dir : all_directions ) { + if( dir.second.id == id ) { + return dir.first; + } + } + return base_dir; +} + std::string base_camps::faction_encode_short( const std::string &type ) { return prefix + type + "_"; @@ -87,9 +111,9 @@ basecamp::basecamp( const std::string &name_, const tripoint &omt_pos_ ): name( } basecamp::basecamp( const std::string &name_, const tripoint &bb_pos_, - const std::vector &directions_, - const std::map &expansions_ ): - directions( directions_ ), name( name_ ), bb_pos( bb_pos_ ), expansions( expansions_ ) + const std::vector &directions_, + const std::map &expansions_ ) + : directions( directions_ ), name( name_ ), bb_pos( bb_pos_ ), expansions( expansions_ ) { } @@ -119,7 +143,7 @@ void basecamp::add_expansion( const std::string &terrain, const tripoint &new_po return; } - const std::string dir = talk_function::om_simple_dir( omt_pos, new_pos ); + const point dir = talk_function::om_simple_dir( omt_pos, new_pos ); expansions[ dir ] = parse_expansion( terrain, new_pos ); bool by_radio = rl_dist( g->u.global_omt_location(), omt_pos ) > 2; resources_updated = false; @@ -129,7 +153,7 @@ void basecamp::add_expansion( const std::string &terrain, const tripoint &new_po } void basecamp::add_expansion( const std::string &bldg, const tripoint &new_pos, - const std::string &dir ) + const point &dir ) { expansion_data e; e.type = base_camps::faction_decode( bldg ); @@ -157,12 +181,12 @@ void basecamp::define_camp( npc &p, const std::string &camp_type ) e.type = base_camps::faction_decode( camp_type ); e.cur_level = -1; e.pos = omt_pos; - expansions[ base_camps::base_dir ] = e; + expansions[base_camps::base_dir] = e; omt_ref = oter_id( "faction_base_camp_0" ); update_provides( base_camps::faction_encode_abs( e, 0 ), - expansions[ base_camps::base_dir ] ); + expansions[base_camps::base_dir] ); } else { - expansions[ base_camps::base_dir ] = parse_expansion( om_cur, omt_pos ); + expansions[base_camps::base_dir] = parse_expansion( om_cur, omt_pos ); } } @@ -195,7 +219,7 @@ std::string basecamp::om_upgrade_description( const std::string &bldg, bool trun // upgrade levels // legacy next upgrade -std::string basecamp::next_upgrade( const std::string &dir, const int offset ) const +std::string basecamp::next_upgrade( const point &dir, const int offset ) const { const auto &e = expansions.find( dir ); if( e == expansions.end() ) { @@ -228,16 +252,17 @@ bool basecamp::has_provides( const std::string &req, const expansion_data &e_dat return false; } -bool basecamp::has_provides( const std::string &req, const std::string &dir, int level ) const +bool basecamp::has_provides( const std::string &req, const cata::optional dir, + int level ) const { - if( dir == "all" ) { + if( !dir ) { for( const auto &e : expansions ) { if( has_provides( req, e.second, level ) ) { return true; } } } else { - const auto &e = expansions.find( dir ); + const auto &e = expansions.find( *dir ); if( e != expansions.end() ) { return has_provides( req, e->second, level ); } @@ -250,7 +275,7 @@ bool basecamp::can_expand() return has_provides( "bed", base_camps::base_dir, directions.size() * 2 ); } -std::vector basecamp::available_upgrades( const std::string &dir ) +std::vector basecamp::available_upgrades( const point &dir ) { std::vector ret_data; auto e = expansions.find( dir ); @@ -312,23 +337,26 @@ std::vector basecamp::available_upgrades( const std::string &d } // recipes and craft support functions -std::map basecamp::recipe_deck( const std::string &dir ) const +std::map basecamp::recipe_deck( const point &dir ) const { - std::map recipes = recipe_group::get_recipes_by_bldg( dir ); - if( !recipes.empty() ) { - return recipes; - } + std::map recipes; const auto &e = expansions.find( dir ); if( e == expansions.end() ) { return recipes; } for( const auto &provides : e->second.provides ) { const auto &test_s = recipe_group::get_recipes_by_id( provides.first ); - recipes.insert( test_s.begin(), test_s.end() ); + recipes.insert( test_s.cbegin(), test_s.cend() ); } return recipes; } +std::map basecamp::recipe_deck( const std::string &bldg ) const +{ + const std::map recipes = recipe_group::get_recipes_by_bldg( bldg ); + return recipes; +} + std::string basecamp::get_gatherlist() const { const auto &e = expansions.find( base_camps::base_dir ); @@ -379,7 +407,7 @@ void basecamp::update_provides( const std::string &bldg, expansion_data &e_data } } -void basecamp::update_in_progress( const std::string &bldg, const std::string &dir ) +void basecamp::update_in_progress( const std::string &bldg, const point &dir ) { if( !recipe_id( bldg ).is_valid() ) { return; @@ -626,7 +654,7 @@ void basecamp::form_crafting_inventory( const bool by_radio ) } // display names -std::string basecamp::expansion_tab( const std::string &dir ) const +std::string basecamp::expansion_tab( const point &dir ) const { if( dir == base_camps::base_dir ) { return _( "Base Missions" ); @@ -635,7 +663,8 @@ std::string basecamp::expansion_tab( const std::string &dir ) const const auto &e = expansions.find( dir ); if( e != expansions.end() ) { - const auto e_type = expansion_types.find( base_camps::faction_encode_abs( e->second, 0 ) ); + recipe_id id( base_camps::faction_encode_abs( e->second, 0 ) ); + const auto e_type = expansion_types.find( id ); if( e_type != expansion_types.end() ) { return e_type->second + _( "Expansion" ); } diff --git a/src/basecamp.h b/src/basecamp.h index 4c1fd4e49350b..0e50cbf3b01d2 100644 --- a/src/basecamp.h +++ b/src/basecamp.h @@ -11,7 +11,9 @@ #include #include "inventory.h" +#include "optional.h" #include "point.h" +#include "translations.h" class JsonIn; class JsonOut; @@ -46,7 +48,36 @@ class window; namespace base_camps { -const std::string base_dir = "[B]"; + +enum tab_mode { + TAB_MAIN, + TAB_N, + TAB_NE, + TAB_E, + TAB_SE, + TAB_S, + TAB_SW, + TAB_W, + TAB_NW +}; + +struct direction_data { + // used for composing mission ids + std::string id; + // tab order + tab_mode tab_order; + // such as [B], [NW], etc + translation bracket_abbr; + // MAIN, [NW], etc + translation tab_title; +}; + +// base_dir and the eight directional points +extern const std::map all_directions; + +point direction_from_id( const std::string &id ); + +const point base_dir = point_zero; const std::string prefix = "faction_base_"; const std::string id = "FACTION_CAMP"; const int prefix_len = 13; @@ -72,7 +103,7 @@ struct basecamp_fuel { struct basecamp_upgrade { std::string bldg; - std::string name; + translation name; bool avail = false; bool in_progress = false; }; @@ -83,8 +114,8 @@ class basecamp basecamp(); basecamp( const std::string &name_, const tripoint &omt_pos ); basecamp( const std::string &name_, const tripoint &bb_pos_, - const std::vector &directions_, - const std::map &expansions_ ); + const std::vector &directions_, + const std::map &expansions_ ); inline bool is_valid() const { return !name.empty() && omt_pos != tripoint_zero; @@ -102,7 +133,7 @@ class basecamp return name; } std::string board_name() const; - std::vector directions; + std::vector directions; std::vector fortifications; std::string name; void faction_display( const catacurses::window &fac_w, int width ) const; @@ -112,23 +143,24 @@ class basecamp void query_new_name(); void add_expansion( const std::string &terrain, const tripoint &new_pos ); void add_expansion( const std::string &bldg, const tripoint &new_pos, - const std::string &dir ); + const point &dir ); void define_camp( npc &p, const std::string &camp_type = "default" ); - std::string expansion_tab( const std::string &dir ) const; + std::string expansion_tab( const point &dir ) const; // upgrade levels bool has_provides( const std::string &req, const expansion_data &e_data, int level = 0 ) const; - bool has_provides( const std::string &req, const std::string &dir = "all", int level = 0 ) const; + bool has_provides( const std::string &req, cata::optional dir = cata::nullopt, + int level = 0 ) const; void update_resources( const std::string &bldg ); void update_provides( const std::string &bldg, expansion_data &e_data ); - void update_in_progress( const std::string &bldg, const std::string &dir ); + void update_in_progress( const std::string &bldg, const point &dir ); bool can_expand(); /// Returns the name of the building the current building @ref dir upgrades into, /// "null" if there isn't one - std::string next_upgrade( const std::string &dir, int offset = 1 ) const; - std::vector available_upgrades( const std::string &dir ); + std::string next_upgrade( const point &dir, int offset = 1 ) const; + std::vector available_upgrades( const point &dir ); // camp utility functions int recruit_evaluation() const; @@ -148,7 +180,10 @@ class basecamp bool distribute_food(); // recipes, gathering, and craft support functions - std::map recipe_deck( const std::string &dir ) const; + // from a direction + std::map recipe_deck( const point &dir ) const; + // from a building + std::map recipe_deck( const std::string &bldg ) const; int recipe_batch_max( const recipe &making ) const; void form_crafting_inventory( bool by_radio = false ); void form_crafting_inventory( map &target_map ); @@ -188,8 +223,8 @@ class basecamp void place_results( item result, bool by_radio ); // mission description functions - void add_available_recipes( mission_data &mission_key, const std::string &dir, - const std::map &craft_recipes ); + void add_available_recipes( mission_data &mission_key, const point &dir, + const std::map &craft_recipes ); std::string recruit_description( int npc_count ); /// Provides a "guess" for some of the things your gatherers will return with @@ -201,7 +236,7 @@ class basecamp farm_ops operation ); /// Returns the description of a camp crafting options. converts fire charges to charcoal, /// allows dark crafting - std::string craft_description( const std::string &itm ); + std::string craft_description( const recipe_id &itm ); // main mission description collection void get_available_missions( mission_data &mission_key, bool by_radio = false ); @@ -209,7 +244,7 @@ class basecamp void reset_camp_workers(); comp_list get_mission_workers( const std::string &mission_id, bool contains = false ); // main mission start/return dispatch function - bool handle_mission( const std::string &miss_id, const std::string &miss_dir, + bool handle_mission( const std::string &miss_id, cata::optional miss_dir, bool by_radio = false ); // mission start functions @@ -218,11 +253,11 @@ class basecamp bool must_feed, const std::string &desc, bool group, const std::vector &equipment, const std::string &skill_tested, int skill_level ); - void start_upgrade( const std::string &bldg, const std::string &dir, const std::string &key, + void start_upgrade( const std::string &bldg, const point &dir, const std::string &key, bool by_radio ); std::string om_upgrade_description( const std::string &bldg, bool trunc = false ) const; void start_menial_labor(); - void start_crafting( const std::string &cur_id, const std::string &cur_dir, + void start_crafting( const std::string &cur_id, const point &cur_dir, const std::string &type, const std::string &miss_id, bool by_radio = false ); @@ -235,8 +270,8 @@ class basecamp void start_fortifications( std::string &bldg_exp, bool by_radio ); void start_combat_mission( const std::string &miss ); /// Called when a companion starts a chop shop @ref task mission - bool start_garage_chop( const std::string &dir, const tripoint &omt_tgt ); - void start_farm_op( const std::string &dir, const tripoint &omt_tgt, farm_ops op ); + bool start_garage_chop( const point &dir, const tripoint &omt_tgt ); + void start_farm_op( const point &dir, const tripoint &omt_tgt, farm_ops op ); ///Display items listed in @ref equipment to let the player pick what to give the departing ///NPC, loops until quit or empty. std::vector give_equipment( std::vector equipment, const std::string &msg ); @@ -254,9 +289,9 @@ class basecamp const std::string &skill, int difficulty ); /// Called to close upgrade missions, @ref miss is the name of the mission id /// and @ref dir is the direction of the location to be upgraded - bool upgrade_return( const std::string &dir, const std::string &miss ); + bool upgrade_return( const point &dir, const std::string &miss ); /// As above, but with an explicit blueprint recipe to upgrade - bool upgrade_return( const std::string &dir, const std::string &miss, const std::string &bldg ); + bool upgrade_return( const point &dir, const std::string &miss, const std::string &bldg ); /// Choose which expansion you should start, called when a survey mission is completed bool survey_return(); @@ -291,7 +326,7 @@ class basecamp std::vector assigned_npcs; // location of associated bulletin board tripoint bb_pos; - std::map expansions; + std::map expansions; comp_list camp_workers; tripoint dumping_spot; diff --git a/src/faction.cpp b/src/faction.cpp index 11b04c9a8e0f2..7966001f8ef97 100644 --- a/src/faction.cpp +++ b/src/faction.cpp @@ -433,8 +433,7 @@ void basecamp::faction_display( const catacurses::window &fac_w, const int width yours->food_supply_text(), yours->food_supply ); nc_color food_col = yours->food_supply_color(); mvwprintz( fac_w, point( width, ++y ), food_col, food_text ); - const std::string base_dir = "[B]"; - std::string bldg = next_upgrade( base_dir, 1 ); + std::string bldg = next_upgrade( base_camps::base_dir, 1 ); std::string bldg_full = _( "Next Upgrade : " ) + bldg; mvwprintz( fac_w, point( width, ++y ), col, bldg_full ); std::string requirements = om_upgrade_description( bldg, true ); diff --git a/src/faction_camp.cpp b/src/faction_camp.cpp index 246440313ff90..2da2184d106b9 100644 --- a/src/faction_camp.cpp +++ b/src/faction_camp.cpp @@ -109,8 +109,8 @@ struct miss_data { translation ret_desc; }; -std::string select_camp_option( const std::map &pos_options, - const std::string &option ); +recipe_id select_camp_option( const std::map &pos_options, + const std::string &option ); // enventually this will move to JSON std::map miss_info = {{ @@ -446,14 +446,14 @@ static cata::optional get_basecamp( npc &p, const std::string &camp_ return temp_camp; } -std::string base_camps::select_camp_option( const std::map &pos_options, +recipe_id base_camps::select_camp_option( const std::map &pos_options, const std::string &option ) { - std::vector pos_name_ids; + std::vector pos_name_ids; std::vector pos_names; for( const auto &it : pos_options ) { - pos_names.push_back( it.first ); - pos_name_ids.push_back( it.second ); + pos_names.push_back( it.second.translated() ); + pos_name_ids.push_back( it.first ); } if( pos_name_ids.size() == 1 ) { @@ -463,7 +463,7 @@ std::string base_camps::select_camp_option( const std::map( choice ) >= pos_name_ids.size() ) { popup( _( "You choose to wait..." ) ); - return std::string(); + return recipe_id::NULL_ID(); } return pos_name_ids[choice]; } @@ -479,9 +479,9 @@ void talk_function::start_camp( npc &p ) popup( _( "You cannot build a camp here." ) ); return; } - const std::string &camp_type = base_camps::select_camp_option( pos_camps, - _( "Select a camp type:" ) ); - if( camp_type.empty() ) { + const recipe_id camp_type = base_camps::select_camp_option( pos_camps, + _( "Select a camp type:" ) ); + if( !camp_type ) { return; } @@ -539,12 +539,12 @@ void talk_function::start_camp( npc &p ) if( display && !query_yn( _( "%s \nAre you sure you wish to continue? " ), buffer ) ) { return; } - const recipe &making = recipe_id( camp_type ).obj(); + const recipe &making = camp_type.obj(); if( !run_mapgen_update_func( making.get_blueprint(), omt_pos ) ) { popup( _( "%s failed to start the %s basecamp." ), p.disp_name(), making.get_blueprint() ); return; } - get_basecamp( p, camp_type ); + get_basecamp( p, camp_type.str() ); } void talk_function::recover_camp( npc &p ) @@ -609,16 +609,19 @@ void talk_function::basecamp_mission( npc &p ) } } -void basecamp::add_available_recipes( mission_data &mission_key, const std::string &dir, - const std::map &craft_recipes ) +void basecamp::add_available_recipes( mission_data &mission_key, const point &dir, + const std::map &craft_recipes ) { + const std::string dir_id = base_camps::all_directions.at( dir ).id; + const std::string dir_abbr = base_camps::all_directions.at( dir ).bracket_abbr.translated(); for( const auto &recipe_data : craft_recipes ) { - const std::string &title_e = dir + recipe_data.first; - const std::string &entry = craft_description( recipe_data.second ); - const recipe &recp = recipe_id( recipe_data.second ).obj(); + const std::string id = dir_id + recipe_data.first.str(); + const std::string &title_e = dir_abbr + recipe_data.second; + const std::string &entry = craft_description( recipe_data.first ); + const recipe &recp = recipe_data.first.obj(); bool craftable = recp.requirements().can_make_with_inventory( _inv, recp.get_component_filter() ); - mission_key.add_start( title_e, "", dir, entry, craftable ); + mission_key.add_start( id, title_e, dir, entry, craftable ); } } @@ -626,7 +629,10 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio { std::string entry; - const std::string base_dir = "[B]"; + const point &base_dir = base_camps::base_dir; + const std::string base_dir_id = base_camps::all_directions.at( base_dir ).id; + const std::string base_dir_abbr = base_camps::all_directions + .at( base_dir ).bracket_abbr.translated(); reset_camp_resources( by_radio ); std::string gather_bldg = "null"; @@ -636,7 +642,8 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_upgrade_camp" ]; entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } for( const basecamp_upgrade &upgrade : available_upgrades( base_dir ) ) { @@ -646,28 +653,28 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio if( npc_list.empty() && !upgrade.in_progress ) { entry = om_upgrade_description( upgrade.bldg ); mission_key.add_start( miss_info.miss_id + upgrade.bldg, - miss_info.desc + " " + upgrade.name, "", entry, upgrade.avail ); + miss_info.desc + " " + upgrade.name, cata::nullopt, entry, upgrade.avail ); } else if( !npc_list.empty() && upgrade.in_progress ) { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); mission_key.add_return( miss_info.ret_miss_id + upgrade.bldg, - miss_info.ret_desc + " " + upgrade.name, "", entry, avail ); + miss_info.ret_desc + " " + upgrade.name, cata::nullopt, entry, avail ); } } // this used to be optional, but now it isn't. Keep it at the same scope { - comp_list npc_list = get_mission_workers( "_faction_camp_crafting_" + base_dir ); + comp_list npc_list = get_mission_workers( "_faction_camp_crafting_" + base_dir_id ); const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_camp_crafting_" ]; //This handles all crafting by the base, regardless of level if( npc_list.empty() ) { - std::map craft_recipes = recipe_deck( base_dir ); + std::map craft_recipes = recipe_deck( base_dir ); add_available_recipes( mission_key, base_dir, craft_recipes ); } else { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( base_dir + miss_info.ret_miss_id, - base_dir + miss_info.ret_desc, base_dir, entry, avail ); + mission_key.add_return( base_dir_id + miss_info.ret_miss_id, + base_dir_abbr + miss_info.ret_desc, base_dir, entry, avail ); } } @@ -685,12 +692,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Time: 3 Hours, Repeated\n" "Positions: %d/3\n" ), gathering_description( gather_bldg ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.size() < 3 ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_fixed( entry, npc_list, 3_hours ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } if( !by_radio ) { entry = string_format( _( "Notes:\n" @@ -741,12 +749,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: Very Low\n" "Time: 3 Hours, Repeated\n" "Positions: %d/3\n" ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.size() < 3 ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_fixed( entry, npc_list, 3_hours ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } @@ -765,13 +774,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "\n\nRisk: None\n" "Time: 3 Hours\n" "Positions: %d/1\n" ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.empty() ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, - avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } } @@ -797,12 +806,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: None\n" "Time: 3 Hours \n" "Positions: %d/1\n" ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.empty() ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } @@ -821,12 +831,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: None\n" "Time: 6 Hour Base + Travel Time + Cutting Time\n" "Positions: %d/1\n" ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.empty() ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } @@ -846,12 +857,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: None\n" "Time: 6 Hour Base + Travel Time + Cutting Time\n" "Positions: %d/1\n" ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.empty() ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } @@ -870,12 +882,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: Medium\n" "Time: 6 Hour Construction + Travel\n" "Positions: %d/1\n" ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.empty() ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } @@ -895,12 +908,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: Medium\n" "Time: 1 Hour Base + Travel\n" "Positions: %d/1\n" ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.empty() ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } @@ -918,12 +932,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: Very Low\n" "Time: 4 Hours, Repeated\n" "Positions: %d/3\n" ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.size() < 3 ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_fixed( entry, npc_list, 4_hours ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } @@ -940,12 +955,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: Low\n" "Time: 6 Hours, Repeated\n" "Positions: %d/2\n" ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.size() < 2 ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_fixed( entry, npc_list, 6_hours ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } @@ -962,12 +978,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: Medium\n" "Time: 6 Hours, Repeated\n" "Positions: %d/1\n" ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.empty() ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_fixed( entry, npc_list, 6_hours ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } @@ -975,15 +992,16 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio comp_list npc_list = get_mission_workers( "_faction_camp_om_fortifications" ); const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_camp_om_fortifications" ]; entry = om_upgrade_description( "faction_wall_level_N_0" ); - mission_key.add_start( "Construct Map Fort", _( "Construct Map Fortifications" ), "", + mission_key.add_start( "Construct Map Fort", _( "Construct Map Fortifications" ), cata::nullopt, entry, npc_list.empty() ); entry = om_upgrade_description( "faction_wall_level_N_1" ); - mission_key.add_start( "Construct Trench", _( "Construct Spiked Trench" ), "", entry, + mission_key.add_start( "Construct Trench", _( "Construct Spiked Trench" ), cata::nullopt, entry, npc_list.empty() ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } @@ -991,12 +1009,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio comp_list npc_list = get_mission_workers( "_faction_camp_recruit_0" ); const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_camp_recruit_0" ]; entry = recruit_description( npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.empty() ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } @@ -1016,12 +1035,13 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: High\n" "Time: Travel\n" "Positions: %d/3\n" ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.size() < 3 ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } @@ -1043,49 +1063,52 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: Very High\n" "Time: Travel\n" "Positions: %d/3\n" ), npc_list.size() ); - mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), "", entry, + mission_key.add_start( miss_info.miss_id, miss_info.desc.translated(), cata::nullopt, entry, npc_list.size() < 3 ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), "", entry, avail ); + mission_key.add_return( miss_info.ret_miss_id, miss_info.ret_desc.translated(), cata::nullopt, + entry, avail ); } } //This starts all of the expansion missions - for( const std::string &dir : directions ) { - const tripoint omt_trg = omt_pos + talk_function::om_dir_to_offset( dir ); + for( const point &dir : directions ) { + const tripoint omt_trg = omt_pos + dir; + const std::string &dir_id = base_camps::all_directions.at( dir ).id; + const std::string &dir_abbr = base_camps::all_directions.at( dir ).bracket_abbr.translated(); // return legacy workers - comp_list npc_list = get_mission_workers( "_faction_upgrade_exp_" + dir ); + comp_list npc_list = get_mission_workers( "_faction_upgrade_exp_" + dir_id ); if( !npc_list.empty() ) { const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_upgrade_exp_" ]; entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( "Recover Ally, " + dir + " Expansion", - _( "Recover Ally, " ) + dir + _( " Expansion" ), dir, + mission_key.add_return( "Recover Ally, " + dir_id + " Expansion", + _( "Recover Ally, " ) + dir_abbr + _( " Expansion" ), dir, entry, avail ); } for( const basecamp_upgrade &upgrade : available_upgrades( dir ) ) { const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_upgrade_exp_" ]; - comp_list npc_list = get_mission_workers( upgrade.bldg + "_faction_upgrade_exp_" + dir ); + comp_list npc_list = get_mission_workers( upgrade.bldg + "_faction_upgrade_exp_" + dir_id ); if( npc_list.empty() ) { entry = om_upgrade_description( upgrade.bldg ); - mission_key.add_start( dir + miss_info.miss_id + upgrade.bldg, - dir + miss_info.desc + " " + upgrade.name, dir, entry, + mission_key.add_start( dir_id + miss_info.miss_id + upgrade.bldg, + dir_abbr + miss_info.desc + " " + upgrade.name, dir, entry, upgrade.avail ); } else { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( "Recover Ally, " + dir + " Expansion" + upgrade.bldg, - _( "Recover Ally, " ) + dir + _( " Expansion" ) + " " + + mission_key.add_return( "Recover Ally, " + dir_id + " Expansion" + upgrade.bldg, + _( "Recover Ally, " ) + dir_abbr + _( " Expansion" ) + " " + upgrade.name, dir, entry, avail ); } } if( has_provides( "dismantling", dir ) ) { - comp_list npc_list = get_mission_workers( "_faction_exp_chop_shop_" + dir ); + comp_list npc_list = get_mission_workers( "_faction_exp_chop_shop_" + dir_id ); const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_exp_chop_shop_" ]; entry = _( "Notes:\n" "Have a companion attempt to completely dissemble a vehicle into " @@ -1097,32 +1120,32 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "> Skill plays a huge role to determine what is salvaged.\n \n" "Risk: None\n" "Time: 5 days \n" ); - mission_key.add_start( dir + miss_info.miss_id, dir + miss_info.desc, dir, entry, + mission_key.add_start( dir_id + miss_info.miss_id, dir_abbr + miss_info.desc, dir, entry, npc_list.empty() ); if( !npc_list.empty() ) { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( dir + miss_info.ret_miss_id, dir + miss_info.ret_desc, dir, + mission_key.add_return( dir_id + miss_info.ret_miss_id, dir_abbr + miss_info.ret_desc, dir, entry, avail ); } } - std::map craft_recipes = recipe_deck( dir ); + std::map craft_recipes = recipe_deck( dir ); if( has_provides( "kitchen", dir ) ) { - comp_list npc_list = get_mission_workers( "_faction_exp_kitchen_cooking_" + dir ); + comp_list npc_list = get_mission_workers( "_faction_exp_kitchen_cooking_" + dir_id ); const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_exp_kitchen_cooking_" ]; if( npc_list.empty() ) { add_available_recipes( mission_key, dir, craft_recipes ); } else { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( dir + miss_info.ret_miss_id, dir + miss_info.ret_desc, dir, + mission_key.add_return( dir_id + miss_info.ret_miss_id, dir_abbr + miss_info.ret_desc, dir, entry, avail ); } } if( has_provides( "blacksmith", dir ) ) { - comp_list npc_list = get_mission_workers( "_faction_exp_blacksmith_crafting_" + dir ); + comp_list npc_list = get_mission_workers( "_faction_exp_blacksmith_crafting_" + dir_id ); const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_exp_blacksmith_crafting_" ]; if( npc_list.empty() ) { @@ -1130,14 +1153,14 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio } else { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( dir + miss_info.ret_miss_id, dir + miss_info.ret_desc, dir, + mission_key.add_return( dir_id + miss_info.ret_miss_id, dir_abbr + miss_info.ret_desc, dir, entry, avail ); } } if( has_provides( "farming", dir ) ) { size_t plots = 0; - comp_list npc_list = get_mission_workers( "_faction_exp_plow_" + dir ); + comp_list npc_list = get_mission_workers( "_faction_exp_plow_" + dir_id ); const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_exp_plow_" ]; if( npc_list.empty() ) { entry = _( "Notes:\n" @@ -1152,18 +1175,18 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: None\n" "Time: 5 Min / Plot \n" "Positions: 0/1 \n" ); - mission_key.add_start( dir + miss_info.miss_id, dir + miss_info.desc, dir, entry, + mission_key.add_start( dir_id + miss_info.miss_id, dir_abbr + miss_info.desc, dir, entry, plots > 0 ); } else { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( dir + miss_info.ret_miss_id, dir + miss_info.ret_desc, dir, + mission_key.add_return( dir_id + miss_info.ret_miss_id, dir_abbr + miss_info.ret_desc, dir, entry, avail ); } } if( has_provides( "farming", dir ) ) { size_t plots = 0; - comp_list npc_list = get_mission_workers( "_faction_exp_plant_" + dir ); + comp_list npc_list = get_mission_workers( "_faction_exp_plant_" + dir_id ); const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_exp_plant_" ]; if( npc_list.empty() ) { entry = _( "Notes:\n" @@ -1180,18 +1203,18 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: None\n" "Time: 1 Min / Plot \n" "Positions: 0/1 \n" ); - mission_key.add_start( dir + miss_info.miss_id, dir + miss_info.desc, dir, entry, + mission_key.add_start( dir_id + miss_info.miss_id, dir_abbr + miss_info.desc, dir, entry, plots > 0 && warm_enough_to_plant( omt_trg ) ); } else { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( dir + miss_info.ret_miss_id, dir + miss_info.ret_desc, dir, + mission_key.add_return( dir_id + miss_info.ret_miss_id, dir_abbr + miss_info.ret_desc, dir, entry, avail ); } } if( has_provides( "farming", dir ) ) { size_t plots = 0; - comp_list npc_list = get_mission_workers( "_faction_exp_harvest_" + dir ); + comp_list npc_list = get_mission_workers( "_faction_exp_harvest_" + dir_id ); const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_exp_harvest_" ]; if( npc_list.empty() ) { entry = _( "Notes:\n" @@ -1205,35 +1228,36 @@ void basecamp::get_available_missions( mission_data &mission_key, bool by_radio "Risk: None\n" "Time: 3 Min / Plot \n" "Positions: 0/1 \n" ); - mission_key.add_start( dir + miss_info.miss_id, dir + miss_info.desc, dir, entry, + mission_key.add_start( dir_id + miss_info.miss_id, dir_abbr + miss_info.desc, dir, entry, plots > 0 ); } else { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( dir + miss_info.ret_miss_id, dir + miss_info.ret_desc, dir, + mission_key.add_return( dir_id + miss_info.ret_miss_id, dir_abbr + miss_info.ret_desc, dir, entry, avail ); } } if( has_provides( "reseeding", dir ) ) { - comp_list npc_list = get_mission_workers( "_faction_exp_farm_crafting_" + dir ); + comp_list npc_list = get_mission_workers( "_faction_exp_farm_crafting_" + dir_id ); const base_camps::miss_data &miss_info = base_camps::miss_info[ "_faction_exp_farm_crafting_" ]; if( npc_list.empty() ) { add_available_recipes( mission_key, dir, craft_recipes ); } else { entry = miss_info.action.translated(); bool avail = update_time_left( entry, npc_list ); - mission_key.add_return( dir + miss_info.ret_miss_id, dir + miss_info.ret_desc, dir, + mission_key.add_return( dir_id + miss_info.ret_miss_id, dir_abbr + miss_info.ret_desc, dir, entry, avail ); } } } } -bool basecamp::handle_mission( const std::string &miss_id, const std::string &miss_dir, +bool basecamp::handle_mission( const std::string &miss_id, const cata::optional miss_dir, bool by_radio ) { - const std::string base_dir = "[B]"; + const point base_dir = base_camps::base_dir; + const std::string base_dir_id = base_camps::all_directions.at( base_dir ).id; npc_ptr comp = nullptr; if( miss_id == "Distribute Food" ) { @@ -1356,80 +1380,84 @@ bool basecamp::handle_mission( const std::string &miss_id, const std::string &mi survey_return(); } - if( miss_dir == base_dir ) { - start_crafting( miss_id, miss_dir, "BASE", "_faction_camp_crafting_", by_radio ); - } - if( miss_id == base_dir + " (Finish) Crafting" ) { - const std::string msg = _( "returns to you with something..." ); - mission_return( "_faction_camp_crafting_" + miss_dir, 1_minutes, true, msg, - "construction", 2 ); + const std::string miss_dir_id = miss_dir ? base_camps::all_directions + .at( *miss_dir ).id : std::string(); + // crafting missions are always supposed to have a direction + if( miss_dir ) { + if( *miss_dir == base_dir ) { + start_crafting( miss_id, *miss_dir, "BASE", "_faction_camp_crafting_", by_radio ); + } + if( miss_id == base_dir_id + " (Finish) Crafting" ) { + const std::string msg = _( "returns to you with something..." ); + mission_return( "_faction_camp_crafting_" + miss_dir_id, 1_minutes, true, msg, + "construction", 2 ); + } } - for( const std::string &dir : directions ) { - if( dir == miss_dir ) { - const tripoint omt_trg = expansions[ dir ].pos; - if( miss_id.size() > ( 18 + miss_dir.size() ) && - miss_id.substr( 0, 18 + miss_dir.size() ) == ( miss_dir + " Expansion Upgrade" ) ) { - const std::string bldg = miss_id.substr( 18 + miss_dir.size() ); - start_upgrade( bldg, dir, bldg + "_faction_upgrade_exp_" + miss_dir, by_radio ); - } else if( miss_id == "Recover Ally, " + miss_dir + " Expansion" ) { - upgrade_return( dir, "_faction_upgrade_exp_" + miss_dir ); + for( const point &dir : directions ) { + if( miss_dir && dir == *miss_dir ) { + const tripoint omt_trg = expansions[dir].pos; + if( miss_id.substr( 0, 18 + miss_dir_id.size() ) == miss_dir_id + " Expansion Upgrade" ) { + const std::string bldg = miss_id.substr( 18 + miss_dir_id.size() ); + start_upgrade( bldg, dir, bldg + "_faction_upgrade_exp_" + miss_dir_id, by_radio ); + } else if( miss_id == "Recover Ally, " + miss_dir_id + " Expansion" ) { + upgrade_return( dir, "_faction_upgrade_exp_" + miss_dir_id ); } else { - const std::string search_str = "Recover Ally, " + miss_dir + " Expansion"; + const std::string search_str = "Recover Ally, " + miss_dir_id + " Expansion"; size_t search_len = search_str.size(); if( miss_id.size() > search_len && miss_id.substr( 0, search_len ) == search_str ) { const std::string bldg = miss_id.substr( search_len ); - upgrade_return( dir, bldg + "_faction_upgrade_exp_" + miss_dir, bldg ); + upgrade_return( dir, bldg + "_faction_upgrade_exp_" + miss_dir_id, bldg ); } } - start_crafting( miss_id, miss_dir, "FARM", "_faction_exp_farm_crafting_", + start_crafting( miss_id, *miss_dir, "FARM", "_faction_exp_farm_crafting_", by_radio ); - if( miss_id == miss_dir + " (Finish) Crafting" && miss_dir != base_dir ) { + if( miss_id == miss_dir_id + " (Finish) Crafting" && *miss_dir != base_dir ) { const std::string msg = _( "returns from your farm with something..." ); - mission_return( "_faction_exp_farm_crafting_" + miss_dir, 1_minutes, true, msg, + mission_return( "_faction_exp_farm_crafting_" + miss_dir_id, 1_minutes, true, msg, "construction", 2 ); } - start_crafting( miss_id, miss_dir, "COOK", "_faction_exp_kitchen_cooking_", + start_crafting( miss_id, *miss_dir, "COOK", "_faction_exp_kitchen_cooking_", by_radio ); - if( miss_id == miss_dir + " (Finish) Cooking" ) { + if( miss_id == miss_dir_id + " (Finish) Cooking" ) { const std::string msg = _( "returns from your kitchen with something..." ); - mission_return( "_faction_exp_kitchen_cooking_" + miss_dir, 1_minutes, + mission_return( "_faction_exp_kitchen_cooking_" + miss_dir_id, 1_minutes, true, msg, "cooking", 2 ); } - start_crafting( miss_id, miss_dir, "SMITH", "_faction_exp_blacksmith_crafting_", + start_crafting( miss_id, *miss_dir, "SMITH", "_faction_exp_blacksmith_crafting_", by_radio ); - if( miss_id == miss_dir + " (Finish) Smithing" ) { + if( miss_id == miss_dir_id + " (Finish) Smithing" ) { const std::string msg = _( "returns from your blacksmith shop with something..." ); - mission_return( "_faction_exp_blacksmith_crafting_" + miss_dir, 1_minutes, + mission_return( "_faction_exp_blacksmith_crafting_" + miss_dir_id, 1_minutes, true, msg, "fabrication", 2 ); } - if( miss_id == miss_dir + " Plow Fields" ) { - start_farm_op( miss_dir, omt_trg, farm_ops::plow ); - } else if( miss_id == miss_dir + " (Finish) Plow Fields" ) { - farm_return( "_faction_exp_plow_" + miss_dir, omt_trg, farm_ops::plow ); + if( miss_id == miss_dir_id + " Plow Fields" ) { + start_farm_op( *miss_dir, omt_trg, farm_ops::plow ); + } else if( miss_id == miss_dir_id + " (Finish) Plow Fields" ) { + farm_return( "_faction_exp_plow_" + miss_dir_id, omt_trg, farm_ops::plow ); } - if( miss_id == miss_dir + " Plant Fields" ) { - start_farm_op( miss_dir, omt_trg, farm_ops::plant ); - } else if( miss_id == miss_dir + " (Finish) Plant Fields" ) { - farm_return( "_faction_exp_plant_" + miss_dir, omt_trg, farm_ops::plant ); + if( miss_id == miss_dir_id + " Plant Fields" ) { + start_farm_op( *miss_dir, omt_trg, farm_ops::plant ); + } else if( miss_id == miss_dir_id + " (Finish) Plant Fields" ) { + farm_return( "_faction_exp_plant_" + miss_dir_id, omt_trg, farm_ops::plant ); } - if( miss_id == miss_dir + " Harvest Fields" ) { - start_farm_op( miss_dir, omt_trg, farm_ops::harvest ); - } else if( miss_id == miss_dir + " (Finish) Harvest Fields" ) { - farm_return( "_faction_exp_harvest_" + miss_dir, omt_trg, + if( miss_id == miss_dir_id + " Harvest Fields" ) { + start_farm_op( *miss_dir, omt_trg, farm_ops::harvest ); + } else if( miss_id == miss_dir_id + " (Finish) Harvest Fields" ) { + farm_return( "_faction_exp_harvest_" + miss_dir_id, omt_trg, farm_ops::harvest ); } - if( miss_id == miss_dir + " Chop Shop" ) { - start_garage_chop( miss_dir, omt_trg ); - } else if( miss_id == miss_dir + " (Finish) Chop Shop" ) { + if( miss_id == miss_dir_id + " Chop Shop" ) { + start_garage_chop( *miss_dir, omt_trg ); + } else if( miss_id == miss_dir_id + " (Finish) Chop Shop" ) { const std::string msg = _( "returns from your garage..." ); - mission_return( "_faction_exp_chop_shop_" + miss_dir, 5_days, true, msg, + mission_return( "_faction_exp_chop_shop_" + miss_dir_id, 5_days, true, msg, "mechanics", 2 ); } break; @@ -1464,7 +1492,7 @@ npc_ptr basecamp::start_mission( const std::string &miss_id, time_duration durat return comp; } -void basecamp::start_upgrade( const std::string &bldg, const std::string &dir, +void basecamp::start_upgrade( const std::string &bldg, const point &dir, const std::string &key, bool by_radio ) { const recipe &making = recipe_id( bldg ).obj(); @@ -1810,24 +1838,28 @@ void basecamp::start_combat_mission( const std::string &miss ) } } -// the structure of this function drives me insane -// recipe_deck returns a map of descriptions to recipe ids -// loop through the recipe deck map, looking for direction + description, ie "[N] Cook: Meat Pie" -// if there's a match, we know the player selected this mission -void basecamp::start_crafting( const std::string &cur_id, const std::string &cur_dir, +// the structure of this function has driven (at least) two devs insane +// recipe_deck returns a map of recipe ids to descriptions +// it first checks whether the mission id starts with the correct direction prefix, +// and then search for the mission id without direction prefix in the recipes +// if there's a match, the player has selected a crafting mission +void basecamp::start_crafting( const std::string &cur_id, const point &cur_dir, const std::string &type, const std::string &miss_id, bool by_radio ) { - const std::map &recipes = recipe_deck( type ); - for( auto &r : recipes ) { - if( cur_id != cur_dir + r.first ) { - continue; - } - const recipe &making = recipe_id( r.second ).obj(); + const std::string cur_dir_id = base_camps::all_directions.at( cur_dir ).id; + const std::map &recipes = recipe_deck( type ); + if( cur_id.substr( 0, cur_dir_id.size() ) != cur_dir_id ) { + // not a crafting mission or has the wrong direction + return; + } + const auto it = recipes.find( recipe_id( cur_id.substr( cur_dir_id.size() ) ) ); + if( it != recipes.end() ) { + const recipe &making = it->first.obj(); if( !making.requirements().can_make_with_inventory( _inv, making.get_component_filter(), 1 ) ) { popup( _( "You don't have the materials to craft that" ) ); - continue; + return; } int batch_size = 1; @@ -1838,14 +1870,14 @@ void basecamp::start_crafting( const std::string &cur_id, const std::string &cur popup_input.title( title ).edit( batch_size ); if( popup_input.canceled() || batch_size <= 0 ) { - continue; + return; } if( batch_size > recipe_batch_max( making ) ) { popup( _( "Your batch is too large!" ) ); - continue; + return; } time_duration work_days = base_camps::to_workdays( making.batch_duration( batch_size ) ); - npc_ptr comp = start_mission( miss_id + cur_dir, work_days, true, _( "begins to work..." ), + npc_ptr comp = start_mission( miss_id + cur_dir_id, work_days, true, _( "begins to work..." ), false, {}, making.skill_used.str(), making.difficulty ); if( comp != nullptr ) { consume_components( making, batch_size, by_radio ); @@ -1980,8 +2012,9 @@ static std::pair farm_action( const tripoint &omt_tgt, farm return std::make_pair( plots_cnt, crops ); } -void basecamp::start_farm_op( const std::string &dir, const tripoint &omt_tgt, farm_ops op ) +void basecamp::start_farm_op( const point &dir, const tripoint &omt_tgt, farm_ops op ) { + const std::string &dir_id = base_camps::all_directions.at( dir ).id; std::pair farm_data = farm_action( omt_tgt, op ); size_t plots_cnt = farm_data.first; if( !plots_cnt ) { @@ -1992,7 +2025,7 @@ void basecamp::start_farm_op( const std::string &dir, const tripoint &omt_tgt, f switch( op ) { case farm_ops::harvest: work += 3_minutes * plots_cnt; - start_mission( "_faction_exp_harvest_" + dir, work, true, + start_mission( "_faction_exp_harvest_" + dir_id, work, true, _( "begins to harvest the field..." ), false, {}, "survival", 0 ); break; case farm_ops::plant: { @@ -2012,13 +2045,13 @@ void basecamp::start_farm_op( const std::string &dir, const tripoint &omt_tgt, f return; } work += 1_minutes * plots_seeded; - start_mission( "_faction_exp_plant_" + dir, work, true, + start_mission( "_faction_exp_plant_" + dir_id, work, true, _( "begins planting the field..." ), false, plant_these, "", 0 ); break; } case farm_ops::plow: work += 5_minutes * plots_cnt; - start_mission( "_faction_exp_plow_" + dir, work, true, + start_mission( "_faction_exp_plow_" + dir_id, work, true, _( "begins plowing the field..." ), false, {}, "", 0 ); break; default: @@ -2026,7 +2059,7 @@ void basecamp::start_farm_op( const std::string &dir, const tripoint &omt_tgt, f } } -bool basecamp::start_garage_chop( const std::string &dir, const tripoint &omt_tgt ) +bool basecamp::start_garage_chop( const point &dir, const tripoint &omt_tgt ) { editmap edit; vehicle *car = edit.mapgen_veh_query( omt_tgt ); @@ -2038,7 +2071,8 @@ bool basecamp::start_garage_chop( const std::string &dir, const tripoint &omt_tg return false; } - npc_ptr comp = start_mission( "_faction_exp_chop_shop_" + dir, 5_days, true, + const std::string dir_id = base_camps::all_directions.at( dir ).id; + npc_ptr comp = start_mission( "_faction_exp_chop_shop_" + dir_id, 5_days, true, _( "begins working in the garage..." ), false, {}, "mechanics", 2 ); if( comp == nullptr ) { @@ -2159,7 +2193,7 @@ npc_ptr basecamp::mission_return( const std::string &miss_id, time_duration min_ return comp; } -bool basecamp::upgrade_return( const std::string &dir, const std::string &miss ) +bool basecamp::upgrade_return( const point &dir, const std::string &miss ) { const std::string bldg = next_upgrade( dir, 1 ); if( bldg == "null" ) { @@ -2168,7 +2202,7 @@ bool basecamp::upgrade_return( const std::string &dir, const std::string &miss ) return upgrade_return( dir, miss, bldg ); } -bool basecamp::upgrade_return( const std::string &dir, const std::string &miss, +bool basecamp::upgrade_return( const point &dir, const std::string &miss, const std::string &bldg ) { auto e = expansions.find( dir ); @@ -2503,7 +2537,7 @@ bool basecamp::survey_return() popup( _( "Expansions must be on the same level as the camp" ) ); return false; } - const std::string dir = talk_function::om_simple_dir( omt_pos, where ); + const point dir = talk_function::om_simple_dir( omt_pos, where ); if( expansions.find( dir ) != expansions.end() ) { popup( _( "You already have an expansion at that location" ) ); return false; @@ -2517,15 +2551,16 @@ bool basecamp::survey_return() return false; } - const std::string &expansion_type = base_camps::select_camp_option( pos_expansions, - _( "Select an expansion:" ) ); + const recipe_id expansion_type = base_camps::select_camp_option( pos_expansions, + _( "Select an expansion:" ) ); - if( !run_mapgen_update_func( expansion_type, where ) ) { - popup( _( "%s failed to add the %s expansion" ), comp->disp_name(), expansion_type ); + if( !run_mapgen_update_func( expansion_type.str(), where ) ) { + popup( _( "%s failed to add the %s expansion" ), comp->disp_name(), + expansion_type->blueprint_name() ); return false; } - omt_ref = oter_id( expansion_type ); - add_expansion( expansion_type, where, dir ); + omt_ref = oter_id( expansion_type.str() ); + add_expansion( expansion_type.str(), where, dir ); const std::string msg = _( "returns from surveying for the expansion." ); finish_return( *comp, true, msg, "construction", 2 ); return true; @@ -2554,23 +2589,18 @@ bool basecamp::farm_return( const std::string &task, const tripoint &omt_tgt, fa } // window manipulation -void talk_function::draw_camp_tabs( const catacurses::window &win, const camp_tab_mode cur_tab, +void talk_function::draw_camp_tabs( const catacurses::window &win, + const base_camps::tab_mode cur_tab, const std::vector> &entries ) { werase( win ); const int width = getmaxx( win ); mvwhline( win, point( 0, 2 ), LINE_OXOX, width ); - std::vector tabs; - tabs.push_back( _( "MAIN" ) ); - tabs.push_back( _( " [N] " ) ); - tabs.push_back( _( " [NE] " ) ); - tabs.push_back( _( " [E] " ) ); - tabs.push_back( _( " [SE] " ) ); - tabs.push_back( _( " [S] " ) ); - tabs.push_back( _( " [SW] " ) ); - tabs.push_back( _( " [W] " ) ); - tabs.push_back( _( " [NW] " ) ); + std::vector tabs( base_camps::all_directions.size() ); + for( const auto &direction : base_camps::all_directions ) { + tabs.at( direction.second.tab_order ) = direction.second.tab_title.translated(); + } const int tab_step = 3; int tab_space = 1; int tab_x = 0; @@ -2584,7 +2614,7 @@ void talk_function::draw_camp_tabs( const catacurses::window &win, const camp_ta } std::string talk_function::name_mission_tabs( const tripoint &omt_pos, const std::string &role_id, - const std::string &cur_title, camp_tab_mode cur_tab ) + const std::string &cur_title, base_camps::tab_mode cur_tab ) { if( role_id != base_camps::id ) { return cur_title; @@ -2594,37 +2624,12 @@ std::string talk_function::name_mission_tabs( const tripoint &omt_pos, const std return cur_title; } basecamp *bcp = *temp_camp; - std::string dir; - switch( cur_tab ) { - case TAB_MAIN: - dir = "[B]"; - break; - case TAB_N: - dir = "[N]"; - break; - case TAB_NE: - dir = "[NE]"; - break; - case TAB_E: - dir = "[E]"; - break; - case TAB_SE: - dir = "[SE]"; - break; - case TAB_S: - dir = "[S]"; - break; - case TAB_SW: - dir = "[SW]"; - break; - case TAB_W: - dir = "[W]"; - break; - case TAB_NW: - dir = "[NW]"; - break; + for( const auto &direction : base_camps::all_directions ) { + if( cur_tab == direction.second.tab_order ) { + return bcp->expansion_tab( direction.first ); + } } - return bcp->expansion_tab( dir ); + return bcp->expansion_tab( base_camps::base_dir ); } // recipes and craft support functions @@ -3220,39 +3225,9 @@ std::vector> talk_function::om_building_region( return om_camp_region; } -point talk_function::om_dir_to_offset( const std::string &dir ) -{ - std::map dir2pt = { { - { "[B]", point_zero }, - { "[N]", point_north }, { "[S]", point_south }, - { "[E]", point_east }, { "[W]", point_west }, - { "[NE]", point_north_east }, { "[SE]", point_south_east }, - { "[NW]", point_north_west }, { "[SW]", point_south_west } - } - }; - return dir2pt[ dir ]; -} - -std::string talk_function::om_simple_dir( const tripoint &omt_pos, const tripoint &omt_tar ) +point talk_function::om_simple_dir( const tripoint &omt_pos, const tripoint &omt_tar ) { - std::string dir = "["; - if( omt_tar.y < omt_pos.y ) { - dir += "N"; - } - if( omt_tar.y > omt_pos.y ) { - dir += "S"; - } - if( omt_tar.x < omt_pos.x ) { - dir += "W"; - } - if( omt_tar.x > omt_pos.x ) { - dir += "E"; - } - dir += "]"; - if( omt_tar.x == omt_pos.x && omt_tar.y == omt_pos.y ) { - return "[B]"; - } - return dir; + return { clamp( omt_tar.x - omt_pos.x, -1, 1 ), clamp( omt_tar.y - omt_pos.y, -1, 1 ) }; } // mission descriptions @@ -3281,9 +3256,9 @@ std::string camp_trip_description( const time_duration &total_time, return entry; } -std::string basecamp::craft_description( const std::string &itm ) +std::string basecamp::craft_description( const recipe_id &itm ) { - const recipe &making = recipe_id( itm ).obj(); + const recipe &making = itm.obj(); std::vector component_print_buffer; int pane = FULL_SCREEN_WIDTH; @@ -3306,7 +3281,7 @@ std::string basecamp::craft_description( const std::string &itm ) int basecamp::recruit_evaluation( int &sbase, int &sexpansions, int &sfaction, int &sbonus ) const { - auto e = expansions.find( "[B]" ); + auto e = expansions.find( base_camps::base_dir ); if( e == expansions.end() ) { sbase = 0; sexpansions = 0; @@ -3320,7 +3295,7 @@ int basecamp::recruit_evaluation( int &sbase, int &sexpansions, int &sfaction, i //How could we ever starve? //More than 5 farms at recruiting base int farm = 0; - for( const std::string &dir : directions ) { + for( const point &dir : directions ) { if( has_provides( "farming", dir ) ) { farm++; } diff --git a/src/faction_camp.h b/src/faction_camp.h index 3e06e9bee8b6c..2f9c56c053ae9 100644 --- a/src/faction_camp.h +++ b/src/faction_camp.h @@ -6,6 +6,8 @@ #include #include +#include "basecamp.h" + namespace catacurses { class window; @@ -15,18 +17,6 @@ struct point; struct tripoint; struct mission_entry; -enum camp_tab_mode { - TAB_MAIN, - TAB_N, - TAB_NE, - TAB_E, - TAB_SE, - TAB_S, - TAB_SW, - TAB_W, - TAB_NW -}; - enum class farm_ops { plow = 1, plant = 2, @@ -52,17 +42,15 @@ void recover_camp( npc & ); ///Changes an NPC camp manager to a follower void remove_overseer( npc & ); -void draw_camp_tabs( const catacurses::window &win, camp_tab_mode cur_tab, +void draw_camp_tabs( const catacurses::window &win, base_camps::tab_mode cur_tab, const std::vector> &entries ); std::string name_mission_tabs( const tripoint &omt_pos, const std::string &role_id, - const std::string &cur_title, camp_tab_mode cur_tab ); + const std::string &cur_title, base_camps::tab_mode cur_tab ); /// Returns the OM tiles surrounding the camp, @ref purge removes all tiles that aren't expansions std::vector> om_building_region( const tripoint &omt_pos, int range, bool purge = false ); -/// Converts the camp and expansion points into direction strings, "[NW]" -std::string om_simple_dir( const tripoint &omt_pos, const tripoint &omt_tar ); -/// Converts a direction into a point offset -point om_dir_to_offset( const std::string &dir ); +/// Returns the x and y coordinates of ( omt_tar - omt_pos ), clamped to [-1, 1] +point om_simple_dir( const tripoint &omt_pos, const tripoint &omt_tar ); } // namespace talk_function #endif diff --git a/src/item.cpp b/src/item.cpp index 05d8e04cfb2d1..a29225dae18bd 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -2383,7 +2383,7 @@ std::string item::info( std::vector &info, const iteminfo_query *parts making->result_name(), percent_progress ) ) ); } else { - info.push_back( iteminfo( "DESCRIPTION", _( type->description ) ) ); + info.push_back( iteminfo( "DESCRIPTION", type->description.translated() ) ); } } } @@ -2890,7 +2890,7 @@ std::string item::info( std::vector &info, const iteminfo_query *parts } insert_separation_line(); info.emplace_back( "DESCRIPTION", temp1.str() ); - info.emplace_back( "DESCRIPTION", _( mod->type->description ) ); + info.emplace_back( "DESCRIPTION", mod->type->description.translated() ); } bool contents_header = false; for( const item &contents_item : contents ) { @@ -2904,7 +2904,7 @@ std::string item::info( std::vector &info, const iteminfo_query *parts info.emplace_back( "DESCRIPTION", space ); } - const std::string description = _( contents_item.type->description ); + const translation &description = contents_item.type->description; if( contents_item.made_of_from_type( LIQUID ) ) { units::volume contents_volume = contents_item.volume() * batch; @@ -2922,7 +2922,7 @@ std::string item::info( std::vector &info, const iteminfo_query *parts converted_volume ); } else { info.emplace_back( "DESCRIPTION", contents_item.display_name() ); - info.emplace_back( "DESCRIPTION", description ); + info.emplace_back( "DESCRIPTION", description.translated() ); } } } diff --git a/src/item_factory.cpp b/src/item_factory.cpp index 97b58993257f4..54d3b14da6b7c 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -1215,7 +1215,7 @@ const itype *Item_factory::find_template( const itype_id &id ) const def->id = id; def->name = string_format( "undefined-%ss", id.c_str() ); def->name_plural = string_format( "undefined-%s", id.c_str() ); - def->description = string_format( "Missing item definition for %s.", id.c_str() ); + def->description = no_translation( string_format( "Missing item definition for %s.", id.c_str() ) ); m_runtimes[ id ].reset( def ); return def; @@ -2082,7 +2082,7 @@ void Item_factory::load_basic_info( JsonObject &jo, itype &def, const std::strin } if( jo.has_string( "description" ) ) { - def.description = jo.get_string( "description" ); + jo.read( "description", def.description ); } if( jo.has_string( "symbol" ) ) { diff --git a/src/itype.h b/src/itype.h index 84187e289d094..e67ac15665def 100644 --- a/src/itype.h +++ b/src/itype.h @@ -827,7 +827,7 @@ struct itype { std::string looks_like; std::string snippet_category; - std::string description; // Flavor text + translation description; // Flavor text // The container it comes in cata::optional default_container; diff --git a/src/mission_companion.cpp b/src/mission_companion.cpp index 51c7caa150cdf..f7b15f4839c77 100644 --- a/src/mission_companion.cpp +++ b/src/mission_companion.cpp @@ -91,7 +91,7 @@ struct comp_rank { mission_data::mission_data() { - for( int tab_num = TAB_MAIN; tab_num != TAB_NW + 3; tab_num++ ) { + for( int tab_num = base_camps::TAB_MAIN; tab_num != base_camps::TAB_NW + 3; tab_num++ ) { std::vector k; entries.push_back( k ); } @@ -377,7 +377,7 @@ bool talk_function::display_and_choose_opts( mission_data &mission_key, const tr TITLE_TAB_HEIGHT = 1; } - camp_tab_mode tab_mode = TAB_MAIN; + base_camps::tab_mode tab_mode = base_camps::TAB_MAIN; size_t part_y = TERMY > FULL_SCREEN_HEIGHT ? ( TERMY - FULL_SCREEN_HEIGHT ) / 4 : 0; size_t part_x = TERMX > FULL_SCREEN_WIDTH ? ( TERMX - FULL_SCREEN_WIDTH ) / 4 : 0; @@ -488,25 +488,34 @@ bool talk_function::display_and_choose_opts( mission_data &mission_key, const tr } } - draw_scrollbar( w_list, sel, info_height + 1, folded_names_lines, point_south ); + if( cur_key_list.size() > info_height + 1 ) { + scrollbar() + .offset_x( 0 ) + .offset_y( 1 ) + .content_size( folded_names_lines ) + .viewport_pos( sel ) + .viewport_size( info_height + 1 ) + .apply( w_list ); + } wrefresh( w_list ); werase( w_info ); // Fold mission text, store it for scrolling mission_text = foldstring( mission_key.cur_key.text, info_width - 2, ' ' ); - if( info_offset > mission_text.size() - info_height ) { + if( info_height >= mission_text.size() ) { + info_offset = 0; + } else if( info_offset + info_height > mission_text.size() ) { info_offset = mission_text.size() - info_height; } - if( mission_text.size() < info_height ) { - info_offset = 0; + if( mission_text.size() > info_height ) { + scrollbar() + .offset_x( info_width - 1 ) + .offset_y( 0 ) + .content_size( mission_text.size() ) + .viewport_pos( info_offset ) + .viewport_size( info_height ) + .apply( w_info ); } - scrollbar() - .offset_x( info_width - 1 ) - .offset_y( 0 ) - .content_size( mission_text.size() ) - .viewport_pos( info_offset ) - .viewport_size( info_height ) - .apply( w_info ); end_line = std::min( info_height, mission_text.size() - info_offset ); // Display the current subset of the mission text. @@ -526,7 +535,6 @@ bool talk_function::display_and_choose_opts( mission_data &mission_key, const tr } const std::string action = ctxt.handle_input(); if( action == "DOWN" ) { - mvwprintz( w_list, point( 1, sel + 2 ), c_white, "-%s", mission_key.cur_key.id ); if( sel == cur_key_list.size() - 1 ) { sel = 0; // Wrap around } else { @@ -535,7 +543,6 @@ bool talk_function::display_and_choose_opts( mission_data &mission_key, const tr info_offset = 0; redraw = true; } else if( action == "UP" ) { - mvwprintz( w_list, point( 1, sel + 2 ), c_white, "-%s", mission_key.cur_key.id ); if( sel == 0 ) { sel = cur_key_list.size() - 1; // Wrap around } else { @@ -558,11 +565,11 @@ bool talk_function::display_and_choose_opts( mission_data &mission_key, const tr info_offset = 0; do { - if( tab_mode == TAB_NW ) { - tab_mode = TAB_MAIN; + if( tab_mode == base_camps::TAB_NW ) { + tab_mode = base_camps::TAB_MAIN; reset_cur_key_list(); } else { - tab_mode = static_cast( tab_mode + 1 ); + tab_mode = static_cast( tab_mode + 1 ); cur_key_list = mission_key.entries[tab_mode + 1]; } } while( cur_key_list.empty() ); @@ -573,13 +580,13 @@ bool talk_function::display_and_choose_opts( mission_data &mission_key, const tr info_offset = 0; do { - if( tab_mode == TAB_MAIN ) { - tab_mode = TAB_NW; + if( tab_mode == base_camps::TAB_MAIN ) { + tab_mode = base_camps::TAB_NW; } else { - tab_mode = static_cast( tab_mode - 1 ); + tab_mode = static_cast( tab_mode - 1 ); } - if( tab_mode == TAB_MAIN ) { + if( tab_mode == base_camps::TAB_MAIN ) { reset_cur_key_list(); } else { cur_key_list = mission_key.entries[tab_mode + 1]; @@ -2120,20 +2127,20 @@ void talk_function::loot_building( const tripoint &site ) void mission_data::add( const std::string &id, const std::string &name_display, const std::string &text ) { - add( id, name_display, "", text, false, true ); + add( id, name_display, cata::nullopt, text, false, true ); } void mission_data::add_return( const std::string &id, const std::string &name_display, - const std::string &dir, const std::string &text, bool possible ) + const cata::optional dir, const std::string &text, bool possible ) { add( id, name_display, dir, text, true, possible ); } void mission_data::add_start( const std::string &id, const std::string &name_display, - const std::string &dir, const std::string &text, bool possible ) + const cata::optional dir, const std::string &text, bool possible ) { add( id, name_display, dir, text, false, possible ); } void mission_data::add( const std::string &id, const std::string &name_display, - const std::string &dir, const std::string &text, + const cata::optional dir, const std::string &text, bool priority, bool possible ) { mission_entry miss; @@ -2154,24 +2161,7 @@ void mission_data::add( const std::string &id, const std::string &name_display, if( !possible ) { entries[10].push_back( miss ); } - if( dir.empty() || dir == "[B]" ) { - entries[1].push_back( miss ); - } - if( dir == "[N]" ) { - entries[2].push_back( miss ); - } else if( dir == "[NE]" ) { - entries[3].push_back( miss ); - } else if( dir == "[E]" ) { - entries[4].push_back( miss ); - } else if( dir == "[SE]" ) { - entries[5].push_back( miss ); - } else if( dir == "[S]" ) { - entries[6].push_back( miss ); - } else if( dir == "[SW]" ) { - entries[7].push_back( miss ); - } else if( dir == "[W]" ) { - entries[8].push_back( miss ); - } else if( dir == "[NW]" ) { - entries[9].push_back( miss ); - } + const point direction = dir ? *dir : base_camps::base_dir; + const int tab_order = base_camps::all_directions.at( direction ).tab_order; + entries[tab_order + 1].emplace_back( miss ); } diff --git a/src/mission_companion.h b/src/mission_companion.h index 25856836b2cce..526007e4aa00b 100644 --- a/src/mission_companion.h +++ b/src/mission_companion.h @@ -7,6 +7,8 @@ #include #include "calendar.h" +#include "optional.h" +#include "point.h" #include "type_id.h" class npc; @@ -24,7 +26,7 @@ using comp_list = std::vector; struct mission_entry { std::string id; std::string name_display; - std::string dir; + cata::optional dir; std::string text; bool priority; bool possible; @@ -48,11 +50,11 @@ class mission_data void add( const std::string &id, const std::string &name_display = "", const std::string &text = "" ); void add_start( const std::string &id, const std::string &name_display, - const std::string &dir, const std::string &text, bool possible = true ); + cata::optional dir, const std::string &text, bool possible = true ); void add_return( const std::string &id, const std::string &name_display, - const std::string &dir, const std::string &text, bool possible = true ); + cata::optional dir, const std::string &text, bool possible = true ); void add( const std::string &id, const std::string &name_display, - const std::string &dir, const std::string &text, + cata::optional dir, const std::string &text, bool priority = false, bool possible = true ); }; diff --git a/src/recipe.cpp b/src/recipe.cpp index 59f8396f13d77..1effa63e3cd10 100644 --- a/src/recipe.cpp +++ b/src/recipe.cpp @@ -539,7 +539,7 @@ const std::string &recipe::get_blueprint() const return blueprint; } -const std::string &recipe::blueprint_name() const +const translation &recipe::blueprint_name() const { return bp_name; } diff --git a/src/recipe.h b/src/recipe.h index ed4c440b1de8f..9c83647e6eea4 100644 --- a/src/recipe.h +++ b/src/recipe.h @@ -11,6 +11,7 @@ #include #include "requirements.h" +#include "translations.h" #include "type_id.h" class item; @@ -43,7 +44,7 @@ class recipe std::string category; std::string subcategory; - std::string description; + translation description; int time = 0; // in movement points (100 per turn) int difficulty = 0; @@ -122,7 +123,7 @@ class recipe bool is_blueprint() const; const std::string &get_blueprint() const; - const std::string &blueprint_name() const; + const translation &blueprint_name() const; const std::vector &blueprint_resources() const; const std::vector> &blueprint_provides() const; const std::vector> &blueprint_requires() const; @@ -176,7 +177,7 @@ class recipe int batch_rsize = 0; // minimum batch size to needed to reach batch_rscale int result_mult = 1; // used by certain batch recipes that create more than one stack of the result std::string blueprint; - std::string bp_name; + translation bp_name; std::vector bp_resources; std::vector> bp_provides; std::vector> bp_requires; diff --git a/src/recipe_groups.cpp b/src/recipe_groups.cpp index b3c2bbb422e2c..fee6bf9c9eaf5 100644 --- a/src/recipe_groups.cpp +++ b/src/recipe_groups.cpp @@ -23,8 +23,8 @@ using group_id = string_id; struct recipe_group_data { group_id id; std::string building_type = "NONE"; - std::map recipes; - std::map> om_terrains; + std::map recipes; + std::map> om_terrains; bool was_loaded; void load( JsonObject &jo, const std::string &src ); @@ -42,9 +42,11 @@ void recipe_group_data::load( JsonObject &jo, const std::string & ) JsonArray jsarr = jo.get_array( "recipes" ); while( jsarr.has_more() ) { JsonObject ordering = jsarr.next_object(); - const std::string name_id = ordering.get_string( "id" ); - const std::string desc = ordering.get_string( "description" ); - recipes[desc] = name_id; + recipe_id name_id; + ordering.read( "id", name_id ); + translation desc; + ordering.read( "description", desc ); + recipes.emplace( name_id, desc ); om_terrains[name_id] = std::set(); JsonArray js_terr = ordering.get_array( "om_terrains" ); while( js_terr.has_more() ) { @@ -57,19 +59,18 @@ void recipe_group_data::load( JsonObject &jo, const std::string & ) void recipe_group_data::check() const { for( const auto &a : recipes ) { - if( !recipe_id( a.second ).is_valid() ) { + if( !a.first.is_valid() ) { debugmsg( "%s is not a valid recipe", a.second ); } } } -std::map recipe_group::get_recipes_by_bldg( const std::string &bldg ) +std::map recipe_group::get_recipes_by_bldg( const std::string &bldg ) { - std::map all_rec; + std::map all_rec; if( bldg == "ALL" ) { for( const auto &gr : recipe_groups_data.get_all() ) { - std::map tmp = gr.recipes; - all_rec.insert( tmp.begin(), tmp.end() ); + all_rec.insert( gr.recipes.cbegin(), gr.recipes.cend() ); } return all_rec; } else { @@ -77,29 +78,28 @@ std::map recipe_group::get_recipes_by_bldg( const std: if( gr.building_type != bldg ) { continue; } - std::map tmp = gr.recipes; - all_rec.insert( tmp.begin(), tmp.end() ); + all_rec.insert( gr.recipes.cbegin(), gr.recipes.cend() ); } return all_rec; } } -std::map recipe_group::get_recipes_by_id( const std::string &id, +std::map recipe_group::get_recipes_by_id( const std::string &id, const std::string &om_terrain_id ) { - std::map all_rec; + std::map all_rec; if( !recipe_groups_data.is_valid( group_id( id ) ) ) { return all_rec; } const recipe_group_data &group = recipe_groups_data.obj( group_id( id ) ); if( om_terrain_id != "ANY" ) { for( const auto &recp : group.recipes ) { - const auto &recp_terrain = group.om_terrains.find( recp.second ); + const auto &recp_terrain = group.om_terrains.find( recp.first ); if( recp_terrain == group.om_terrains.end() ) { continue; } if( recp_terrain->second.find( om_terrain_id ) != recp_terrain->second.end() ) { - all_rec[recp.first] = recp.second; + all_rec.emplace( recp ); } } return all_rec; diff --git a/src/recipe_groups.h b/src/recipe_groups.h index 6576fa7e0b0ef..b4c50bee7dc6d 100644 --- a/src/recipe_groups.h +++ b/src/recipe_groups.h @@ -5,6 +5,9 @@ #include #include +#include "translations.h" +#include "type_id.h" + class JsonObject; namespace recipe_group @@ -14,8 +17,8 @@ void load( JsonObject &jo, const std::string &src ); void check(); void reset(); -std::map get_recipes_by_bldg( const std::string &bldg ); -std::map get_recipes_by_id( const std::string &id, +std::map get_recipes_by_bldg( const std::string &bldg ); +std::map get_recipes_by_id( const std::string &id, const std::string &om_terrain_id = "ANY" ); } // namespace recipe_group diff --git a/src/savegame_json.cpp b/src/savegame_json.cpp index b8ff8c8776772..3553a8392b6f4 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -3211,7 +3211,14 @@ void basecamp::deserialize( JsonIn &jsin ) while( ja.has_more() ) { JsonObject edata = ja.next_object(); expansion_data e; - const std::string dir = edata.get_string( "dir" ); + point dir; + if( edata.has_string( "dir" ) ) { + // old save compatibility + const std::string dir_id = edata.get_string( "dir" ); + dir = base_camps::direction_from_id( dir_id ); + } else { + edata.read( "dir", dir ); + } edata.read( "type", e.type ); if( edata.has_int( "cur_level" ) ) { edata.read( "cur_level", e.cur_level ); @@ -3240,7 +3247,7 @@ void basecamp::deserialize( JsonIn &jsin ) } edata.read( "pos", e.pos ); expansions[ dir ] = e; - if( dir != "[B]" ) { + if( dir != base_camps::base_dir ) { directions.push_back( dir ); } }