From 9b2e8d2586847533c54fef06cc0f63cbe7be6e30 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:41:48 +0100 Subject: [PATCH 01/31] Display messages in third column --- src/veh_interact.cpp | 54 +++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index eacaefb012bb6..27647f11c1da5 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -135,47 +135,49 @@ void veh_interact::allocate_windows() const int grid_h = total_h - 2; // exterior borders take 2 w_grid = newwin(grid_h, grid_w, y0 + 1, x0 + 1); - int mode_x, mode_y, msg_x, msg_y, disp_x, parts_x; + int mode_x, mode_y, msg_x, disp_x, parts_x; int stats_x, stats_y, list_x, name_x, name_y; int mode_h = 1; - int msg_h = 3; int name_h = 1; int stats_h = 6; - page_size = grid_h - ( mode_h + msg_h ) - ( stats_h + name_h ) - 2; + page_size = grid_h - ( mode_h + stats_h + name_h ) - 2; - int pane_y = y0 + 1 + msg_h + mode_h + 1; + int pane_y = y0 + 1 + mode_h + 1; - int pane_w = 32 + (extra_w / 4); // uses 1/4 of extra space - int disp_w = grid_w - ( pane_w * 2 ) - 2; // interior borders take 2 + int pane_w = ( grid_w / 3 ) - 1; + + int disp_w = grid_w - ( pane_w * 2 ) - 2; + int disp_h = page_size * 0.45; + int parts_h = page_size - disp_h; + int parts_y = pane_y + disp_h; mode_y = y0 + 1; - msg_y = mode_y + mode_h; name_y = pane_y + page_size + 1; stats_y = name_y + name_h; mode_x = x0 + 1; - msg_x = x0 + 1; disp_x = x0 + 1; + parts_x = x0 + 1; name_x = x0 + 1; stats_x = x0 + 1; - parts_x = disp_x + disp_w + 1; - list_x = parts_x + pane_w + 1; + list_x = disp_x + disp_w + 1; + msg_x = list_x + pane_w + 1; // match grid lines - mvwputch(w_border, msg_h + mode_h + 1, 0, BORDER_COLOR, LINE_XXXO); // |- - mvwputch(w_border, msg_h + mode_h + 1, total_w - 1, BORDER_COLOR, LINE_XOXX); // -| - mvwputch(w_border, msg_h + mode_h + 1 + page_size + 1, 0, BORDER_COLOR, LINE_XXXO); // |- - mvwputch(w_border, msg_h + mode_h + 1 + page_size + 1, total_w - 1, BORDER_COLOR, LINE_XOXX); // -| + mvwputch(w_border, mode_h + 1, 0, BORDER_COLOR, LINE_XXXO); // |- + mvwputch(w_border, mode_h + 1, total_w - 1, BORDER_COLOR, LINE_XOXX); // -| + mvwputch(w_border, mode_h + 1 + page_size + 1, 0, BORDER_COLOR, LINE_XXXO); // |- + mvwputch(w_border, mode_h + 1 + page_size + 1, total_w - 1, BORDER_COLOR, LINE_XOXX); // -| // make the windows w_mode = newwin(mode_h, grid_w, mode_y, mode_x ); - w_msg = newwin(msg_h, grid_w, msg_y, msg_x ); - w_disp = newwin(page_size, disp_w, pane_y, disp_x ); - w_parts = newwin(page_size, pane_w, pane_y, parts_x); - w_list = newwin(page_size, pane_w, pane_y, list_x ); + w_msg = newwin(page_size, pane_w, pane_y, msg_x ); + w_disp = newwin(disp_h, disp_w, pane_y, disp_x ); + w_parts = newwin(parts_h, disp_w, parts_y, parts_x); + w_list = newwin(page_size, pane_w, pane_y, list_x ); w_details = NULL; // only pops up when in install menu w_stats = newwin(stats_h, grid_w, stats_y, stats_x); w_name = newwin(name_h, grid_w, name_y, name_x ); @@ -1448,20 +1450,20 @@ void veh_interact::display_grid() const int grid_w = getmaxx(w_grid); // Two lines dividing the three middle sections. - for (int i = 1 + getmaxy( w_mode ) + getmaxy( w_msg ); i < (1 + getmaxy( w_mode ) + getmaxy( w_msg ) + getmaxy( w_disp ) ); ++i) { + for (int i = 1 + getmaxy( w_mode ); i < (1 + getmaxy( w_mode ) + page_size ); ++i) { mvwputch(w_grid, i, getmaxx( w_disp ), BORDER_COLOR, LINE_XOXO); // | - mvwputch(w_grid, i, getmaxx( w_disp ) + 1 + getmaxx( w_parts) , BORDER_COLOR, LINE_XOXO); // | + mvwputch(w_grid, i, getmaxx( w_disp ) + 1 + getmaxx( w_list) , BORDER_COLOR, LINE_XOXO); // | } // Two lines dividing the vertical menu sections. for (int i = 0; i < grid_w; ++i) { - mvwputch( w_grid, getmaxy( w_mode ) + getmaxy( w_msg ), i, BORDER_COLOR, LINE_OXOX ); // - - mvwputch( w_grid, getmaxy( w_mode ) + getmaxy( w_msg ) + 1 + getmaxy( w_disp ), i, BORDER_COLOR, LINE_OXOX ); // - + mvwputch( w_grid, getmaxy( w_mode ), i, BORDER_COLOR, LINE_OXOX ); // - + mvwputch( w_grid, getmaxy( w_mode ) + 1 + page_size, i, BORDER_COLOR, LINE_OXOX ); // - } // Fix up the line intersections. - mvwputch(w_grid, getmaxy( w_mode ) + getmaxy( w_msg ), getmaxx( w_disp ), BORDER_COLOR, LINE_OXXX); - mvwputch(w_grid, getmaxy( w_mode ) + getmaxy( w_msg ) + 1 + getmaxy( w_disp ), getmaxx( w_disp ), BORDER_COLOR, LINE_XXOX); // _|_ - mvwputch(w_grid, getmaxy( w_mode ) + getmaxy( w_msg ), getmaxx( w_disp ) + 1 + getmaxx( w_parts ), BORDER_COLOR, LINE_OXXX); - mvwputch(w_grid, getmaxy( w_mode ) + getmaxy( w_msg ) + 1 + getmaxy( w_disp ), getmaxx( w_disp ) + 1 + getmaxx( w_parts ), BORDER_COLOR, LINE_XXOX); // _|_ + mvwputch(w_grid, getmaxy( w_mode ), getmaxx( w_disp ), BORDER_COLOR, LINE_OXXX); + mvwputch(w_grid, getmaxy( w_mode ) + 1 + page_size, getmaxx( w_disp ), BORDER_COLOR, LINE_XXOX); // _|_ + mvwputch(w_grid, getmaxy( w_mode ), getmaxx( w_disp ) + 1 + getmaxx( w_list ), BORDER_COLOR, LINE_OXXX); + mvwputch(w_grid, getmaxy( w_mode ) + 1 + page_size, getmaxx( w_disp ) + 1 + getmaxx( w_list ), BORDER_COLOR, LINE_XXOX); // _|_ wrefresh(w_grid); } From 16b24d0434fbdb22cbaf3281adb605d7b453e3e7 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:41:48 +0100 Subject: [PATCH 02/31] Vehicle part installation uses requirement data --- src/game.cpp | 9 +++------ src/game_constants.h | 3 +++ src/newcharacter.cpp | 1 - src/veh_type.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/veh_type.h | 17 +++++++++++++++++ 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index d079fdcedb7a3..63f23278dcbc2 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -7448,13 +7448,10 @@ void game::exam_vehicle(vehicle &veh, const tripoint &p, int cx, int cy) return; } - if (vehint.sel_cmd != ' ') { + if (vehint.sel_cmd != ' '&& vehint.sel_vpart_info != nullptr ) { int time = 200; int skill = u.get_skill_level( skill_id( "mechanics" ) ); - int diff = 1; - if (vehint.sel_vpart_info != NULL) { - diff = vehint.sel_vpart_info->difficulty + 3; - } + int diff = vehint.sel_vpart_info->difficulty + 3; int setup = (calendar::turn == veh.last_repair_turn ? 0 : 1); ///\EFFECT_MECHANICS reduces time spent examining vehicle int setuptime = std::max(setup * 3000, setup * 6000 - skill * 400); @@ -7468,7 +7465,7 @@ void game::exam_vehicle(vehicle &veh, const tripoint &p, int cx, int cy) // Stored in activity.index and used in the complete_vehicle() callback to finish task. switch (vehint.sel_cmd) { case 'i': - time = setuptime + std::max(mintime, 5000 * diff - skill * 2500); + time = vehint.sel_vpart_info->install_time( g->u ); break; case 'r': time = setuptime + std::max(mintime, (8 * diff - skill * 4) * dmg); diff --git a/src/game_constants.h b/src/game_constants.h index 4227d6114c26a..0594f64af12f5 100644 --- a/src/game_constants.h +++ b/src/game_constants.h @@ -85,4 +85,7 @@ /** Maximum density of a map field */ #define MAX_FIELD_DENSITY 3 +/** Maximum (effective) level for a skill */ +#define MAX_SKILL 10 + #endif diff --git a/src/newcharacter.cpp b/src/newcharacter.cpp index 3734c100150fb..d7458371dbb1b 100644 --- a/src/newcharacter.cpp +++ b/src/newcharacter.cpp @@ -54,7 +54,6 @@ #define HIGH_STAT 14 // The point after which stats cost double #define MAX_STAT 20 // The point after which stats can not be increased further -#define MAX_SKILL 20 // The maximum selectable skill level #define NEWCHAR_TAB_MAX 6 // The ID of the rightmost tab diff --git a/src/veh_type.cpp b/src/veh_type.cpp index f06be3a06eb38..4620d8406421a 100644 --- a/src/veh_type.cpp +++ b/src/veh_type.cpp @@ -10,11 +10,14 @@ #include "vehicle_group.h" #include "init.h" #include "generic_factory.h" +#include "character.h" #include #include #include +const skill_id skill_mechanics( "mechanics" ); + std::unordered_map vtypes; // GENERAL GUIDELINES @@ -171,6 +174,24 @@ void vpart_info::load( JsonObject &jo ) assign( jo, "bonus", def.bonus ); assign( jo, "flags", def.flags ); + auto reqs = jo.get_object( "requirements" ); + if( reqs.has_object( "install" ) ) { + auto ins = reqs.get_object( "install" ); + + auto sk = ins.get_array( "skills" ); + if( !sk.empty() ) { + def.install_skills.clear(); + } + while( sk.has_more() ) { + auto cur = sk.next_array(); + def.install_skills.emplace( skill_id( cur.get_string( 0 ) ) , cur.size() >= 2 ? cur.get_int( 1 ) : 1 ); + } + + assign( ins, "time", def.install_moves ); + + def.install_reqs.load( ins ); + } + if( jo.has_member( "symbol" ) ) { def.sym = jo.get_string( "symbol" )[ 0 ]; } @@ -329,6 +350,18 @@ void vpart_info::check() for( auto &part_ptr : vehicle_part_int_types ) { auto &part = *part_ptr; + for( auto &e : part.install_skills ) { + if( !e.first.is_valid() ) { + debugmsg( "vehicle part %s has unknown install skill %s", part.id.c_str(), e.first.c_str() ); + } + } + + part.install_reqs.check_consistency( part.id.c_str() ); + + if( part.install_moves < 0 ) { + debugmsg( "vehicle part %s has negative installation time", part.id.c_str() ); + } + if( !item_group::group_is_defined( part.breaks_into_group ) ) { debugmsg( "Vehicle part %s breaks into non-existent item group %s.", part.id.c_str(), part.breaks_into_group.c_str() ); @@ -391,6 +424,12 @@ std::string vpart_info::name() const return name_; } +int vpart_info::install_time( const Character &ch ) const { + ///\EFFECT_MECHANICS reduces time consumed installing vehicle parts + int lvl = std::min( ch.get_skill_level( skill_mechanics ).level(), MAX_SKILL ); + return install_moves * ( 1.0 - ( lvl / 2.0 ) / MAX_SKILL ); +} + template<> const vehicle_prototype &string_id::obj() const { diff --git a/src/veh_type.h b/src/veh_type.h index f2cdac93e66eb..e0197add4030c 100644 --- a/src/veh_type.h +++ b/src/veh_type.h @@ -6,6 +6,7 @@ #include "enums.h" #include "color.h" #include "damage.h" +#include "requirements.h" #include #include @@ -25,6 +26,10 @@ struct vehicle_item_spawn; struct quality; using quality_id = string_id; typedef int nc_color; +class Character; + +class Skill; +using skill_id = string_id; // bitmask backing store of -certian- vpart_info.flags, ones that // won't be going away, are involved in core functionality, and are checked frequently @@ -127,6 +132,18 @@ class vpart_info /** Mechanics skill required to install item */ int difficulty = 0; + /** Installation requirements for this component */ + requirement_data install_reqs; + + /** Required skills to install this component */ + std::map install_skills; + + /** Installation time (in moves) for component (@see install_time), default 1 hour */ + int install_moves = 60000; + + /** Installation time (in moves) for this component accounting for player skills */ + int install_time( const Character &ch ) const; + /** @ref item_group this part breaks into when destroyed */ std::string breaks_into_group = "EMPTY_GROUP"; From 4a202ee46467597dcd769f20fdd3a432e2d44411 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:41:48 +0100 Subject: [PATCH 03/31] Synthesise requirements for legacy parts --- src/requirements.h | 5 +++++ src/veh_type.cpp | 26 ++++++++++++++++++++++++-- src/veh_type.h | 3 +++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/requirements.h b/src/requirements.h index 5af3c0963f963..cc33ccae33dea 100644 --- a/src/requirements.h +++ b/src/requirements.h @@ -127,6 +127,11 @@ struct quality_requirement { * std::string get_color(bool has_one, const inventory &crafting_inv) const; */ struct requirement_data { + // temporarily break encapsulation pending migration of legacy parts + // @see vpart_info::check + // @todo remove once all parts specify installation requirements directly + friend class vpart_info; + typedef std::vector< std::vector > alter_tool_comp_vector; typedef std::vector< std::vector > alter_item_comp_vector; typedef std::vector< std::vector > alter_quali_req_vector; diff --git a/src/veh_type.cpp b/src/veh_type.cpp index 4620d8406421a..d792ac057d686 100644 --- a/src/veh_type.cpp +++ b/src/veh_type.cpp @@ -190,6 +190,7 @@ void vpart_info::load( JsonObject &jo ) assign( ins, "time", def.install_moves ); def.install_reqs.load( ins ); + def.legacy = false; } if( jo.has_member( "symbol" ) ) { @@ -347,8 +348,29 @@ void vpart_info::finalize() void vpart_info::check() { - for( auto &part_ptr : vehicle_part_int_types ) { - auto &part = *part_ptr; + for( auto &vp : vehicle_part_types ) { + auto &part = vp.second; + + // handle legacy parts without requirement data + if( part.legacy ) { + part.install_reqs.components = { { { { part.item, 1 } } } }; + part.install_skills.emplace( skill_mechanics, part.difficulty ); + + if( part.has_flag( "TOOL_WRENCH" ) || part.has_flag( "WHEEL" ) ) { + part.install_reqs.qualities = { { { quality_id( "WRENCH" ), 1, 1 } } }; + } else if( part.has_flag( "TOOL_SCREWDRIVER" ) ) { + part.install_reqs.qualities = { { { { quality_id( "SCREW" ), 1, 1 } } } }; + } else if( part.has_flag( "NAILABLE" ) ) { + part.install_reqs.qualities = { { { { quality_id( "HAMMER" ), 1, 1 } } } }; + part.install_reqs.components.push_back( { { { "nail", 20 } } } ); + } else { + part.install_reqs.components.push_back( { { { "duct_tape", 20 } } } ); + } + } + + if( part.install_reqs.get_components().empty() ) { + debugmsg( "vehicle part %s has no installation components", part.id.c_str() ); + } for( auto &e : part.install_skills ) { if( !e.first.is_valid() ) { diff --git a/src/veh_type.h b/src/veh_type.h index e0197add4030c..01bc845f0de37 100644 --- a/src/veh_type.h +++ b/src/veh_type.h @@ -132,6 +132,9 @@ class vpart_info /** Mechanics skill required to install item */ int difficulty = 0; + /** Legacy parts don't specify installation requirements */ + bool legacy = true; + /** Installation requirements for this component */ requirement_data install_reqs; From d2f5407a8ec9031a571149afe5497fb525fea1ca Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:41:48 +0100 Subject: [PATCH 04/31] Vehicle part removal uses requirement data --- src/game.cpp | 5 +++-- src/veh_type.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ src/veh_type.h | 12 ++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 63f23278dcbc2..09b159aea1fe3 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -7471,10 +7471,11 @@ void game::exam_vehicle(vehicle &veh, const tripoint &p, int cx, int cy) time = setuptime + std::max(mintime, (8 * diff - skill * 4) * dmg); break; case 'o': - time = setuptime + std::max(mintime, 4000 * diff - skill * 2000); + time = vehint.sel_vpart_info->removal_time( g->u ); break; case 'c': - time = setuptime + std::max(mintime, 6000 * diff - skill * 4000); + time = vehint.sel_vpart_info->removal_time( g->u ) + + vehint.sel_vpart_info->install_time( g->u ); break; } u.assign_activity( ACT_VEHICLE, time, (int)vehint.sel_cmd ); diff --git a/src/veh_type.cpp b/src/veh_type.cpp index d792ac057d686..6bb2298e95631 100644 --- a/src/veh_type.cpp +++ b/src/veh_type.cpp @@ -192,6 +192,23 @@ void vpart_info::load( JsonObject &jo ) def.install_reqs.load( ins ); def.legacy = false; } + if( reqs.has_object( "removal" ) ) { + auto rem = reqs.get_object( "removal" ); + + auto sk = rem.get_array( "skills" ); + if( !sk.empty() ) { + def.removal_skills.clear(); + } + while( sk.has_more() ) { + auto cur = sk.next_array(); + def.removal_skills.emplace( skill_id( cur.get_string( 0 ) ) , cur.size() >= 2 ? cur.get_int( 1 ) : 1 ); + } + + assign( rem, "time", def.removal_moves ); + + def.removal_reqs.load( rem ); + def.legacy = false; + } if( jo.has_member( "symbol" ) ) { def.sym = jo.get_string( "symbol" )[ 0 ]; @@ -358,10 +375,13 @@ void vpart_info::check() if( part.has_flag( "TOOL_WRENCH" ) || part.has_flag( "WHEEL" ) ) { part.install_reqs.qualities = { { { quality_id( "WRENCH" ), 1, 1 } } }; + part.removal_reqs.qualities = { { { quality_id( "WRENCH" ), 1, 1 } } }; } else if( part.has_flag( "TOOL_SCREWDRIVER" ) ) { part.install_reqs.qualities = { { { { quality_id( "SCREW" ), 1, 1 } } } }; + part.removal_reqs.qualities = { { { { quality_id( "SCREW" ), 1, 1 } } } }; } else if( part.has_flag( "NAILABLE" ) ) { part.install_reqs.qualities = { { { { quality_id( "HAMMER" ), 1, 1 } } } }; + part.removal_reqs.qualities = { { { { quality_id( "HAMMER" ), 1, 1 } } } }; part.install_reqs.components.push_back( { { { "nail", 20 } } } ); } else { part.install_reqs.components.push_back( { { { "duct_tape", 20 } } } ); @@ -372,18 +392,34 @@ void vpart_info::check() debugmsg( "vehicle part %s has no installation components", part.id.c_str() ); } + if( part.removal_moves < 0 ) { + part.removal_moves = part.install_moves / 2; + } + for( auto &e : part.install_skills ) { if( !e.first.is_valid() ) { debugmsg( "vehicle part %s has unknown install skill %s", part.id.c_str(), e.first.c_str() ); } } + for( auto &e : part.removal_skills ) { + if( !e.first.is_valid() ) { + debugmsg( "vehicle part %s has unknown removal skill %s", part.id.c_str(), e.first.c_str() ); + } + } + part.install_reqs.check_consistency( part.id.c_str() ); + part.removal_reqs.check_consistency( part.id.c_str() ); + if( part.install_moves < 0 ) { debugmsg( "vehicle part %s has negative installation time", part.id.c_str() ); } + if( part.removal_moves < 0 ) { + debugmsg( "vehicle part %s has negative removal time", part.id.c_str() ); + } + if( !item_group::group_is_defined( part.breaks_into_group ) ) { debugmsg( "Vehicle part %s breaks into non-existent item group %s.", part.id.c_str(), part.breaks_into_group.c_str() ); @@ -452,6 +488,12 @@ int vpart_info::install_time( const Character &ch ) const { return install_moves * ( 1.0 - ( lvl / 2.0 ) / MAX_SKILL ); } +int vpart_info::removal_time( const Character &ch ) const { + ///\EFFECT_MECHANICS reduces time consumed removing vehicle parts + int lvl = std::min( ch.get_skill_level( skill_mechanics ).level(), MAX_SKILL ); + return removal_moves * ( 1.0 - ( lvl / 2.0 ) / MAX_SKILL ); +} + template<> const vehicle_prototype &string_id::obj() const { diff --git a/src/veh_type.h b/src/veh_type.h index 01bc845f0de37..12dc378e18aec 100644 --- a/src/veh_type.h +++ b/src/veh_type.h @@ -147,6 +147,18 @@ class vpart_info /** Installation time (in moves) for this component accounting for player skills */ int install_time( const Character &ch ) const; + /** Requirements for removal of this component */ + requirement_data removal_reqs; + + /** Required skills to remove this component */ + std::map removal_skills; + + /** Removal time (in moves) for component (@see removal_time), default is half @ref install_moves */ + int removal_moves = -1; + + /** Removal time (in moves) for this component accounting for player skills */ + int removal_time( const Character &ch ) const; + /** @ref item_group this part breaks into when destroyed */ std::string breaks_into_group = "EMPTY_GROUP"; From d472e7df690d2b832e5a419a60087a6269b522b9 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:41:48 +0100 Subject: [PATCH 05/31] Avoid spurious string construction --- src/veh_type.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/veh_type.cpp b/src/veh_type.cpp index 6bb2298e95631..9a425f0afc29e 100644 --- a/src/veh_type.cpp +++ b/src/veh_type.cpp @@ -408,9 +408,9 @@ void vpart_info::check() } } - part.install_reqs.check_consistency( part.id.c_str() ); + part.install_reqs.check_consistency( part.id.str() ); - part.removal_reqs.check_consistency( part.id.c_str() ); + part.removal_reqs.check_consistency( part.id.str() ); if( part.install_moves < 0 ) { debugmsg( "vehicle part %s has negative installation time", part.id.c_str() ); From 9ed7a1562a5a88cc6dd26a10e8d96f2e519b6b13 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:41:48 +0100 Subject: [PATCH 06/31] Display and enforce installation requirements --- src/game_constants.h | 3 + src/veh_interact.cpp | 145 ++++++++++++++++++++----------------------- src/veh_interact.h | 5 +- 3 files changed, 73 insertions(+), 80 deletions(-) diff --git a/src/game_constants.h b/src/game_constants.h index 0594f64af12f5..b9b820ec8f93d 100644 --- a/src/game_constants.h +++ b/src/game_constants.h @@ -82,6 +82,9 @@ /** Weight per level of LIFT/JACK tool quality */ #define TOOL_LIFT_FACTOR 500000 // 500kg/level +/** Cap JACK requirements to support arbritrarily large vehicles */ +#define JACK_LIMIT 6000000 // 6000kg (6 metric tonnes) + /** Maximum density of a map field */ #define MAX_FIELD_DENSITY 3 diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 27647f11c1da5..b72c260acdf55 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include #ifdef _MSC_VER #include @@ -33,7 +35,7 @@ static inline const char * status_color( bool status ) { - static const char *good = "ltgreen"; + static const char *good = "green"; static const char *bad = "red"; return status ? good : bad; } @@ -312,6 +314,10 @@ void veh_interact::cache_tool_availability() map_selector( g->u.pos(), PICKUP_RANGE ).max_quality( LIFT ), vehicle_selector(g->u.pos(), 2, true, *veh ).max_quality( LIFT ) } ); + max_jack = std::max( { g->u.max_quality( JACK ), + map_selector( g->u.pos(), PICKUP_RANGE ).max_quality( JACK ), + vehicle_selector(g->u.pos(), 2, true, *veh ).max_quality( JACK ) } ); + // cap JACK requirements at 6000kg to support arbritrarily large vehicles double qual = ceil( double( std::min( veh->total_mass(), 6000 ) * 1000 ) / TOOL_LIFT_FACTOR ); @@ -440,29 +446,29 @@ task_reason veh_interact::cant_do (char mode) return CAN_DO; } -bool veh_interact::is_drive_conflict(int msg_width){ +bool veh_interact::is_drive_conflict() { bool install_muscle_engine = (sel_vpart_info->fuel_type == "muscle"); bool has_muscle_engine = veh->has_engine_type("muscle", false); bool can_install = !(has_muscle_engine && install_muscle_engine); if (!can_install) { werase (w_msg); - fold_and_print(w_msg, 0, 1, msg_width - 2, c_ltred, + fold_and_print(w_msg, 0, 1, getmaxx( w_msg ) - 2, c_ltred, _("Only one muscle powered engine can be installed.")); wrefresh (w_msg); } return !can_install; } -bool veh_interact::can_install_part(int msg_width){ +bool veh_interact::can_install_part() { if( sel_vpart_info == NULL ) { werase (w_msg); wrefresh (w_msg); return false; } - if( g->u.has_trait("DEBUG_HS") ) { - return true; + if( is_drive_conflict() ) { + return false; } bool is_engine = sel_vpart_info->has_flag("ENGINE"); @@ -480,7 +486,6 @@ bool veh_interact::can_install_part(int msg_width){ } } } - bool is_wheel = sel_vpart_info->has_flag("WHEEL"); int dif_steering = 0; if (sel_vpart_info->has_flag("STEERABLE")) { @@ -499,89 +504,73 @@ bool veh_interact::can_install_part(int msg_width){ } } - itype_id itm = sel_vpart_info->item; - bool drive_conflict = is_drive_conflict(msg_width); - - bool has_comps = crafting_inv.has_components(itm, 1); - - ///\EFFECT_STR allows installing tires on heavier vehicles without a jack - ///\EFFECT_STR allows installing heavier parts without lifting equipment - bool can_lift = is_wheel ? g->u.can_lift( *veh ) : g->u.can_lift( item( itm ) ); - bool has_aid = is_wheel ? has_jack : item( itm ).weight() < max_lift * TOOL_LIFT_FACTOR; - int req_str = is_wheel ? veh->lift_strength() : item( itm ).lift_strength(); - - ///\EFFECT_MECHANICS determines which vehicle parts can be installed - bool has_skill = g->u.get_skill_level( skill_mechanics ) >= sel_vpart_info->difficulty; + auto reqs = sel_vpart_info->install_reqs; + bool ok = reqs.can_make_with_inventory( crafting_inv ); - bool has_tools = ((has_welder && has_goggles) || has_duct_tape) && has_wrench; - bool has_skill2 = !is_engine || (g->u.get_skill_level( skill_mechanics ) >= dif_eng); - bool has_skill3 = g->u.get_skill_level(skill_mechanics) >= dif_steering; - bool is_wrenchable = sel_vpart_info->has_flag("TOOL_WRENCH"); - bool is_screwable = sel_vpart_info->has_flag("TOOL_SCREWDRIVER"); - bool is_wood = sel_vpart_info->has_flag("NAILABLE"); - bool is_hand_remove = sel_vpart_info->has_flag("TOOL_NONE"); + std::ostringstream msg; + msg << _( "Time required:\n" ); + msg << "> " << calendar::print_duration( sel_vpart_info->install_time( g->u ) / 100 ) << "\n"; - if (drive_conflict) { - return false; // No, you cannot has twin pedal power + msg << _( "Skills required:\n" ); + for( const auto& e : sel_vpart_info->install_skills ) { + bool hasSkill = g->u.get_skill_level( e.first ) >= e.second; + ok -= !hasSkill; + msg << string_format( "> %2$s %3$i\n", status_color( hasSkill ), + _( e.first.obj().name().c_str() ), e.second ); } - - std::string msg = string_format( _( "Needs %2$s" ), status_color( has_comps ), item::nname( itm ).c_str() ); - - if( is_hand_remove ) { - // no other tool requirements - - } else if( is_wrenchable ) { - msg += string_format( _( ", a wrench or duct tape" ), - status_color( has_wrench ), status_color( has_duct_tape ) ); - - } else if( is_screwable ) { - msg += string_format( _( ", a screwdriver or duct tape"), - status_color( has_screwdriver ), status_color( has_duct_tape ) ); - - } else if( is_wood ) { - msg += string_format( _( ", either nails and something to drive them or duct tape" ), - status_color( has_nails ), status_color( has_hammer || has_nailgun ), status_color( has_duct_tape ) ); - - } else { - msg += string_format( _( ", a wrench, either a powered welder (and welding goggles) or duct tape" ), - status_color( has_wrench ), status_color( has_welder ), status_color( has_goggles ), status_color( has_duct_tape ) ); + if( sel_vpart_info->install_skills.empty() ) { + msg << string_format( "> %2$s", status_color( true ), _( "NONE" ) ) << "\n"; } + + auto comps = reqs.get_folded_components_list( getmaxx( w_msg ), c_white, crafting_inv ); + std::copy( comps.begin(), comps.end(), std::ostream_iterator( msg, "\n" ) ); + auto tools = reqs.get_folded_tools_list( getmaxx( w_msg ), c_white, crafting_inv ); + std::copy( tools.begin(), tools.end(), std::ostream_iterator( msg, "\n" ) ); - msg += string_format( _( " and level %2$d skill in mechanics." ), status_color( has_skill ), sel_vpart_info->difficulty ); + msg << _( "Additional requirements:\n" ); - if( engines && is_engine ) { // already has engine - msg += string_format( _( " You also need level %2$d skill in mechanics to install additional engines." ), - status_color( has_skill2 ), dif_eng ); + if( dif_eng > 0 ) { + ok -= g->u.get_skill_level( skill_mechanics ) < dif_eng; + msg << string_format( _( "> %2$s %3$i for extra engines." ), + status_color( g->u.get_skill_level( skill_mechanics ) >= dif_eng ), + skill_mechanics.obj().name().c_str(), dif_eng ) << "\n"; } if( dif_steering > 0 ) { - msg += string_format( _( " You also need level %2$d skill in mechanics to install additional steering axles." ), - status_color( has_skill3 ), dif_steering ); + ok -= g->u.get_skill_level( skill_mechanics ) < dif_steering; + msg << string_format( _( "> %2$s %3$i for extra steering axles." ), + status_color( g->u.get_skill_level( skill_mechanics ) >= dif_steering ), + skill_mechanics.obj().name().c_str(), dif_steering ) << "\n"; + } + + int lvl, str; + quality_id qual; + bool use_aid, use_str; + item base( sel_vpart_info->item ); + if( base.is_wheel() ) { + qual = JACK; + lvl = ceil( double( std::min( veh->total_mass() * 1000, JACK_LIMIT ) / TOOL_LIFT_FACTOR ) ); + str = veh->lift_strength(); + use_aid = max_jack >= lvl; + use_str = g->u.can_lift( *veh ); + } else { + qual = LIFT; + lvl = ceil( double( base.weight() ) / TOOL_LIFT_FACTOR ); + str = base.lift_strength(); + use_aid = max_lift >= lvl; + use_str = g->u.can_lift( base ); } - msg += string_format( _(" You also need either lifting equipment or %3$d strength." ), - status_color( has_aid ), status_color( can_lift ), req_str ); - - werase (w_msg); - fold_and_print( w_msg, 0, 1, msg_width - 2, c_ltgray, msg ); - wrefresh (w_msg); + ok -= !( use_aid || use_str ); + msg << string_format( _( "> 1 tool with %2$s %3$i OR strength %5$i" ), + status_color( use_aid ), qual.obj().name.c_str(), lvl, + status_color( use_str ), str ) << "\n"; - if( !has_comps || !has_skill || !has_skill2 || !has_skill3 ) { - return false; - } else if( !can_lift && !has_aid ) { - return false; - } else if(is_hand_remove) { - return true; - } else if(is_wrenchable) { - return has_duct_tape || has_wrench; - } else if(is_screwable) { - return has_duct_tape || has_screwdriver; - } else if(is_wood) { - return has_duct_tape || (has_nails && (has_hammer || has_nailgun)); - } else { - return has_tools; - } + werase( w_msg ); + fold_and_print( w_msg, 0, 1, getmaxx( w_msg ) - 2, c_ltgray, msg.str() ); + wrefresh( w_msg ); + return ok || g->u.has_trait( "DEBUG_HS" ); } /** @@ -730,7 +719,7 @@ void veh_interact::do_install() display_details( sel_vpart_info ); - bool can_install = can_install_part(msg_width); + bool can_install = can_install_part(); const std::string action = main_context.handle_input(); if (action == "INSTALL" || action == "CONFIRM"){ diff --git a/src/veh_interact.h b/src/veh_interact.h index 606db6ef17bc0..b5e3755ab1766 100644 --- a/src/veh_interact.h +++ b/src/veh_interact.h @@ -80,6 +80,7 @@ class veh_interact input_context main_context; int max_lift; // maximum level of available lifting equipment (if any) + int max_jack; // maximum level of available jacking equipment (if any) int part_at( int dx, int dy ); void move_cursor( int dx, int dy ); @@ -132,10 +133,10 @@ class veh_interact //do_remove supporting operation, writes requirements to ui bool can_remove_part( int veh_part_index, int mech_skill, int msg_width ); //do install support, writes requirements to ui - bool can_install_part( int msg_width ); + bool can_install_part(); //true if trying to install foot crank with electric engines for example //writes failure to ui - bool is_drive_conflict( int msg_width ); + bool is_drive_conflict(); /* true if current selected square has part with "FUEL_TANK flag and * they are not full. Otherwise will be false. */ From 864c6b7fc34852a7928d1f6eaf053fff80e28346 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:41:48 +0100 Subject: [PATCH 07/31] Display and enforce removal requirements --- src/veh_interact.cpp | 126 +++++++++++++++++++------------------------ src/veh_interact.h | 2 +- src/veh_type.cpp | 2 + 3 files changed, 59 insertions(+), 71 deletions(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index b72c260acdf55..2d559f3ab1508 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -1034,83 +1034,71 @@ void veh_interact::do_refill() sel_cmd = 'f'; } -bool veh_interact::can_remove_part(int veh_part_index, int mech_skill, int msg_width){ - werase (w_msg); - if (veh->can_unmount(veh_part_index)) { - bool is_wood = veh->part_flag(veh_part_index, "NAILABLE"); - bool is_wheel = veh->part_flag(veh_part_index, "WHEEL"); - bool is_wrenchable = veh->part_flag(veh_part_index, "TOOL_WRENCH") || - (is_wheel && veh->part_flag(veh_part_index, "NO_JACK")); - bool is_screwable = veh->part_flag(veh_part_index, "TOOL_SCREWDRIVER"); - bool is_hand_remove = veh->part_flag(veh_part_index, "TOOL_NONE"); - - int skill_req; - if (veh->part_flag(veh_part_index, "DIFFICULTY_REMOVE")) { - skill_req = veh->part_info(veh_part_index).difficulty; - } else if (is_screwable || is_wrenchable || is_hand_remove || is_wood) { - skill_req = 1; - } else { - skill_req = 2; - } - - bool has_skill = false; - if (mech_skill >= skill_req) has_skill = true; - - std::string msg; - - if( is_hand_remove ) { - msg = _( "You need "); - - } else if( is_wood ) { - msg = string_format( _("You need a hammer and"), status_color( has_hammer ) ); +bool veh_interact::can_remove_part( int idx ) { + if( sel_vpart_info == NULL ) { + werase( w_msg ); + wrefresh (w_msg); + return false; + } - } else if( is_wrenchable ) { - msg = string_format( _("You need a wrench and"), status_color( has_wrench ) ); + auto reqs = sel_vpart_info->removal_reqs; + bool ok = reqs.can_make_with_inventory( crafting_inv ); - } else if( is_screwable ) { - msg = string_format( _("You need a screwdriver and"), status_color( has_screwdriver ) ); + std::ostringstream msg; + msg << _( "Time required:\n" ); + msg << "> " << calendar::print_duration( sel_vpart_info->removal_time( g->u ) / 100 ) << "\n"; - } else if( is_wheel ) { - msg = string_format( _("You need a wrench, either lifting equipment or %4$d strength and"), - status_color( has_wrench ), status_color( has_jack ), status_color( g->u.can_lift( *veh ) ), veh->lift_strength() ); - } else { - msg = string_format( _( "You need a wrench and a hacksaw, cutting torch and welding goggles, or circular saw (off) and" ), - status_color( has_wrench ), status_color( has_hacksaw ) ); - } + msg << _( "Skills required:\n" ); + for( const auto& e : sel_vpart_info->removal_skills ) { + bool hasSkill = g->u.get_skill_level( e.first ) >= e.second; + ok -= !hasSkill; + msg << string_format( "> %2$s %3$i\n", status_color( hasSkill ), + _( e.first.obj().name().c_str() ), e.second ); + } + if( sel_vpart_info->removal_skills.empty() ) { + msg << string_format( "> %2$s", status_color( true ), _( "NONE" ) ) << "\n"; + } - msg += string_format( " level %2$d mechanics skill to remove this part.", status_color( has_skill ), skill_req ); + auto comps = reqs.get_folded_components_list( getmaxx( w_msg ), c_white, crafting_inv ); + std::copy( comps.begin(), comps.end(), std::ostream_iterator( msg, "\n" ) ); - fold_and_print( w_msg, 0, 1, msg_width - 2, c_ltgray, msg ); - wrefresh(w_msg); + auto tools = reqs.get_folded_tools_list( getmaxx( w_msg ), c_white, crafting_inv ); + std::copy( tools.begin(), tools.end(), std::ostream_iterator( msg, "\n" ) ); - if (g->u.has_trait("DEBUG_HS")) { - return true; - } + msg << _( "Additional requirements:\n" ); - if( !has_skill ) { - return false; - } + int lvl, str; + quality_id qual; + bool use_aid, use_str; + item base( sel_vpart_info->item ); + if( base.is_wheel() ) { + qual = JACK; + lvl = ceil( double( std::min( veh->total_mass() * 1000, JACK_LIMIT ) / TOOL_LIFT_FACTOR ) ); + str = veh->lift_strength(); + use_aid = max_jack >= lvl; + use_str = g->u.can_lift( *veh ); + } else { + qual = LIFT; + lvl = ceil( double( base.weight() ) / TOOL_LIFT_FACTOR ); + str = base.lift_strength(); + use_aid = max_lift >= lvl; + use_str = g->u.can_lift( base ); + } - if( is_wheel ) { - ///\EFFECT_STR allows removing tires on heavier vehicles without a jack - return has_wrench && ( g->u.can_lift( *veh ) || has_jack ); - } + ok -= !( use_aid || use_str ); + msg << string_format( _( "> 1 tool with %2$s %3$i OR strength %5$i" ), + status_color( use_aid ), qual.obj().name.c_str(), lvl, + status_color( use_str ), str ) << "\n"; - //check if have all necessary materials - if( ( is_wrenchable && ( has_wrench || has_hacksaw) ) || - ( is_hand_remove ) || - ( is_wood && has_hammer ) || - ( is_screwable && ( has_screwdriver || has_hacksaw ) ) || - ( has_wrench && has_hacksaw ) ) { - return true; - } - } else { - mvwprintz(w_msg, 0, 1, c_ltred, - _("You cannot remove that part while something is attached to it.")); - wrefresh (w_msg); + if( !veh->can_unmount( idx ) ) { + msg << string_format( _( "> %2$s" ), status_color( false ), "Remove attached parts first" ) << "\n"; + ok = false; } - return false; + werase( w_msg ); + fold_and_print( w_msg, 0, 1, getmaxx( w_msg ) - 2, c_ltgray, msg.str() ); + wrefresh( w_msg ); + return ok || g->u.has_trait( "DEBUG_HS" ); } /** @@ -1152,11 +1140,9 @@ void veh_interact::do_remove() mvwprintz(w_mode, 0, 1, c_ltgray, _("Choose a part here to remove:")); wrefresh (w_mode); - ///\EFFECT_MECHANICS determines which vehicle parts can be removed - const int skilllevel = g->u.get_skill_level( skill_mechanics ); int pos = 0; for( size_t i = 0; i < parts_here.size(); i++ ) { - if( can_remove_part( parts_here[i], skilllevel, msg_width ) ) { + if( can_remove_part( parts_here[ i ] ) ) { pos = i; break; } @@ -1169,7 +1155,7 @@ void veh_interact::do_remove() werase (w_parts); veh->print_part_desc (w_parts, 0, getmaxy( w_parts ) - 1, getmaxx( w_parts ), cpart, pos); wrefresh (w_parts); - bool can_remove = can_remove_part(parts_here[pos], skilllevel, msg_width); + bool can_remove = can_remove_part( parts_here[ pos ] ); //read input const std::string action = main_context.handle_input(); if (can_remove && (action == "REMOVE" || action == "CONFIRM")) { diff --git a/src/veh_interact.h b/src/veh_interact.h index b5e3755ab1766..154ac1db40f55 100644 --- a/src/veh_interact.h +++ b/src/veh_interact.h @@ -131,7 +131,7 @@ class veh_interact int mostDamagedPart; //do_remove supporting operation, writes requirements to ui - bool can_remove_part( int veh_part_index, int mech_skill, int msg_width ); + bool can_remove_part( int idx ); //do install support, writes requirements to ui bool can_install_part(); //true if trying to install foot crank with electric engines for example diff --git a/src/veh_type.cpp b/src/veh_type.cpp index 9a425f0afc29e..ba98f4071be32 100644 --- a/src/veh_type.cpp +++ b/src/veh_type.cpp @@ -371,7 +371,9 @@ void vpart_info::check() // handle legacy parts without requirement data if( part.legacy ) { part.install_reqs.components = { { { { part.item, 1 } } } }; + part.install_skills.emplace( skill_mechanics, part.difficulty ); + part.removal_skills.emplace( skill_mechanics, part.difficulty ); if( part.has_flag( "TOOL_WRENCH" ) || part.has_flag( "WHEEL" ) ) { part.install_reqs.qualities = { { { quality_id( "WRENCH" ), 1, 1 } } }; From 659ebf2bd09e9de310330c39890eb9e20718c80b Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:41:48 +0100 Subject: [PATCH 08/31] Consume requirements on part installation --- src/veh_interact.cpp | 56 +++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 2d559f3ab1508..560a2830a186e 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -2124,40 +2124,32 @@ void complete_vehicle () // cmd = Install Repair reFill remOve Siphon Changetire reName relAbel switch (cmd) { - case 'i': - if(is_wood) { - tools.push_back(tool_comp("nail", NAILS_USED)); - tools.push_back(tool_comp("duct_tape", DUCT_TAPE_USED)); - g->u.consume_tools(tools); - } - // Only parts that use charges - else if (is_screwable){ - if(!has_screwdriver){ - tools.push_back(tool_comp("duct_tape", DUCT_TAPE_USED)); - g->u.consume_tools(tools); - } + + case 'i': { + auto inv = g->u.crafting_inventory(); + + const auto& reqs = vpinfo.install_reqs; + if( !reqs.can_make_with_inventory( inv ) ) { + add_msg( m_info, _( "You lack the requirements to install the %s." ), vpinfo.name().c_str() ); } - else if (is_wrenchable){ - if(!has_wrench){ - tools.push_back(tool_comp("duct_tape", DUCT_TAPE_USED)); - g->u.consume_tools(tools); + + // consume items extracting a match for the parts base item + item base; + for( const auto& e : reqs.get_components() ) { + for( auto& obj : g->u.consume_items( e ) ) { + if( obj.typeId() == vpinfo.item ) { + base = obj; + } } } - else if (!is_hand_remove){ - if (has_goggles) { - // Need welding goggles to use any of these tools, - // without the goggles one _must_ use the duct tape - tools.push_back(tool_comp("welder", welder_charges)); - tools.push_back(tool_comp("oxy_torch", welder_oxy_charges)); - tools.push_back(tool_comp("welder_crude", welder_crude_charges)); - tools.push_back(tool_comp("toolset", welder_crude_charges)); - } - tools.push_back(tool_comp("duct_tape", DUCT_TAPE_USED)); - tools.push_back(tool_comp("toolbox", DUCT_TAPE_USED)); - g->u.consume_tools(tools); + + for( const auto& e : reqs.get_tools() ) { + g->u.consume_tools( e ); } - partnum = veh->install_part( dx, dy, part_id, consume_vpart_item( part_id ) ); + g->u.invalidate_crafting_inventory(); + + int partnum = !base.is_null() ? veh->install_part( dx, dy, part_id, std::move( base ) ) : -1; if(partnum < 0) { debugmsg ("complete_vehicle install part fails dx=%d dy=%d id=%d", dx, dy, part_id.c_str()); } @@ -2196,11 +2188,11 @@ void complete_vehicle () add_msg( m_good, _("You install a %1$s into the %2$s." ), veh->parts[ partnum ].name().c_str(), veh->name.c_str() ); - // easy parts don't train - if (!is_hand_remove) { - g->u.practice( skill_mechanics, vpinfo.difficulty * 5 + ((is_wood || is_wrenchable || is_screwable) ? 20 : 40) ); + if( reqs.get_tools().empty() ) { + g->u.practice( skill_mechanics, vpinfo.difficulty * 50 ); } break; + } case 'r': { veh->last_repair_turn = calendar::turn; From be0e8702b31b6d5abf53d7737c849e643ba16426 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:41:48 +0100 Subject: [PATCH 09/31] Consume requirements on part removal --- src/veh_interact.cpp | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 560a2830a186e..608b7947f33ec 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -2234,28 +2234,27 @@ void complete_vehicle () } g->pl_refill_vehicle(*veh, vehicle_part); break; - case 'o': - // Only parts that use charges - if (!(is_wrenchable && has_wrench) && !(is_screwable && has_screwdriver) && !is_hand_remove && !is_wheel){ - if( !crafting_inv.has_quality( SAW_M_FINE ) && ( is_wood && !crafting_inv.has_quality( HAMMER ) ) ) { - tools.push_back(tool_comp("circsaw_off", 20)); - tools.push_back(tool_comp("oxy_torch", 10)); - g->u.consume_tools(tools); - } + case 'o': { + auto inv = g->u.crafting_inventory(); + + const auto& reqs = vpinfo.removal_reqs; + if( !reqs.can_make_with_inventory( inv ) ) { + add_msg( m_info, _( "You lack the requirements to remove the %s." ), vpinfo.name().c_str() ); + } + + for( const auto& e : reqs.get_components() ) { + g->u.consume_items( e ); + } + for( const auto& e : reqs.get_tools() ) { + g->u.consume_tools( e ); } - // Nails survive if pulled out with pliers or a claw hammer. TODO: implement PLY tool quality and random chance based on skill/quality - /*if( is_wood && crafting_inv.has_quality( HAMMER ) ) { - item return_nails("nail"); - return_nails.charges = 10; - g->m.add_item_or_charges( g->u.posx, g->u.posy, return_nails ); - }*/ //causes runtime errors. not a critical feature; implement with PLY quality. + + g->u.invalidate_crafting_inventory(); + // Dump contents of part at player's feet, if any. for( auto &elem : veh->get_items(vehicle_part) ) { g->m.add_item_or_charges( g->u.posx(), g->u.posy(), elem ); } - while( !veh->get_items(vehicle_part).empty() ) { - veh->get_items(vehicle_part).erase( veh->get_items(vehicle_part).begin() ); - } // Power cables must remove parts from the target vehicle, too. if (veh->part_flag(vehicle_part, "POWER_TRANSFER")) { @@ -2266,8 +2265,8 @@ void complete_vehicle () if (!broken) { g->m.add_item_or_charges( g->u.pos(), veh->parts[vehicle_part].properties_to_item() ); // simple tasks won't train mechanics - if(type != SEL_JACK && !is_hand_remove) { - g->u.practice( skill_mechanics, (is_wood || is_wrenchable || is_screwable) ? 15 : 30); + if( reqs.get_tools().empty() ) { + g->u.practice( skill_mechanics, vpinfo.difficulty * 50 ); } } else { veh->break_part_into_pieces(vehicle_part, g->u.posx(), g->u.posy()); @@ -2288,6 +2287,8 @@ void complete_vehicle () veh->part_removal_cleanup(); } break; + } + case 'c': parts = veh->parts_at_relative( dx, dy ); if( parts.size() ) { From 3f452c24469c5d8034d164307ad9b544cf9fe3d7 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:41:48 +0100 Subject: [PATCH 10/31] Drop unused declarations --- src/veh_interact.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 608b7947f33ec..572498d575252 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -2097,7 +2097,6 @@ void complete_vehicle () int dx = g->u.activity.values[4]; int dy = g->u.activity.values[5]; int vehicle_part = g->u.activity.values[6]; - int type = g->u.activity.values[7]; const vpart_str_id part_id( g->u.activity.str_values[0] ); std::vector tools; int welder_charges = charges_per_use( "welder" ); @@ -2105,10 +2104,6 @@ void complete_vehicle () int welder_crude_charges = charges_per_use( "welder_crude" ); const inventory &crafting_inv = g->u.crafting_inventory(); const bool has_goggles = crafting_inv.has_quality( GLARE, 2 ); - const bool has_screwdriver = crafting_inv.has_quality( SCREW ); - const bool has_wrench = crafting_inv.has_quality( WRENCH ); - - int partnum; bool broken; @@ -2116,11 +2111,6 @@ void complete_vehicle () std::vector parts; const vpart_info &vpinfo = part_id.obj(); - bool is_wheel = vpinfo.has_flag("WHEEL"); - bool is_wood = vpinfo.has_flag("NAILABLE"); - bool is_screwable = vpinfo.has_flag("TOOL_SCREWDRIVER"); - bool is_wrenchable = vpinfo.has_flag("TOOL_WRENCH"); - bool is_hand_remove = vpinfo.has_flag("TOOL_NONE"); // cmd = Install Repair reFill remOve Siphon Changetire reName relAbel switch (cmd) { From b1f0450c8677faca78dc5375ec69459034a742cf Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:41:48 +0100 Subject: [PATCH 11/31] Use time duration macros --- src/calendar.h | 5 +++++ src/veh_type.h | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/calendar.h b/src/calendar.h index aa99999f9afef..fbd9b7c4142a9 100644 --- a/src/calendar.h +++ b/src/calendar.h @@ -3,6 +3,11 @@ #include +constexpr int MOVES( int n ) +{ + return n * 100; +} + constexpr int SECONDS( int n ) { return n / 6; diff --git a/src/veh_type.h b/src/veh_type.h index 12dc378e18aec..17842e0d64661 100644 --- a/src/veh_type.h +++ b/src/veh_type.h @@ -7,6 +7,7 @@ #include "color.h" #include "damage.h" #include "requirements.h" +#include "calendar.h" #include #include @@ -142,7 +143,7 @@ class vpart_info std::map install_skills; /** Installation time (in moves) for component (@see install_time), default 1 hour */ - int install_moves = 60000; + int install_moves = MOVES( HOURS( 1 ) ); /** Installation time (in moves) for this component accounting for player skills */ int install_time( const Character &ch ) const; From dfac136aa00797eb080714e93a6e91878e22e94c Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:41:48 +0100 Subject: [PATCH 12/31] Add example requirement data to frames --- data/json/vehicleparts/frames.json | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/data/json/vehicleparts/frames.json b/data/json/vehicleparts/frames.json index 9eb3d423c95c9..8faac78253cee 100644 --- a/data/json/vehicleparts/frames.json +++ b/data/json/vehicleparts/frames.json @@ -41,6 +41,19 @@ "location": "structure", "durability": 400, "difficulty": 1, + "requirements": { + "install": { + "skills": [ [ "mechanics", 1 ] ], + "time": 120000, + "qualities": [ { "id": "GLARE", "level": 2 } ], + "tools": [ [ [ "welder", 50 ], [ "welder_crude", 75 ], [ "toolset", 75 ], [ "oxy_torch", 20 ] ] ], + "components": [ [ [ "frame", 1 ] ] ] + }, + "removal": { + "skills": [ [ "mechanics", 1 ] ], + "qualities": [ { "id": "SAW_M", "level": 1 } ] + } + }, "breaks_into": "ig_vp_frame", "flags": [ "MOUNTABLE" ] }, @@ -84,7 +97,20 @@ "location": "structure", "color": "dark_gray", "durability": 1600, - "difficulty": 1, + "difficulty": 3, + "requirements": { + "install": { + "skills": [ [ "mechanics", 3 ] ], + "time": 240000, + "qualities": [ { "id": "GLARE", "level": 2 } ], + "tools": [ [ [ "welder", 200 ], [ "welder_crude", 300 ], [ "toolset", 150 ], [ "oxy_torch", 60 ] ] ], + "components": [ [ [ "hdframe", 1 ] ] ] + }, + "removal": { + "skills": [ [ "mechanics", 1 ] ], + "qualities": [ { "id": "SAW_M", "level": 1 } ] + } + }, "breaks_into": "ig_vp_hdframe", "flags": [ "MOUNTABLE" ] }, From 8e7b84b6d2eb68170e3b517047488fb60ffc10b4 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:43:39 +0100 Subject: [PATCH 13/31] Fix requirements for frame installation --- data/json/vehicleparts/frames.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/json/vehicleparts/frames.json b/data/json/vehicleparts/frames.json index 8faac78253cee..1b586f84dfe6e 100644 --- a/data/json/vehicleparts/frames.json +++ b/data/json/vehicleparts/frames.json @@ -103,7 +103,7 @@ "skills": [ [ "mechanics", 3 ] ], "time": 240000, "qualities": [ { "id": "GLARE", "level": 2 } ], - "tools": [ [ [ "welder", 200 ], [ "welder_crude", 300 ], [ "toolset", 150 ], [ "oxy_torch", 60 ] ] ], + "tools": [ [ [ "welder", 200 ], [ "welder_crude", 300 ], [ "toolset", 300 ], [ "oxy_torch", 60 ] ] ], "components": [ [ [ "hdframe", 1 ] ] ] }, "removal": { From 2464ff5e9fe2b6191148e3d34f01fed6240e9832 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:44:34 +0100 Subject: [PATCH 14/31] Avoid spurious reference to global --- src/game.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 09b159aea1fe3..d2566ec5bcf35 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -7465,17 +7465,17 @@ void game::exam_vehicle(vehicle &veh, const tripoint &p, int cx, int cy) // Stored in activity.index and used in the complete_vehicle() callback to finish task. switch (vehint.sel_cmd) { case 'i': - time = vehint.sel_vpart_info->install_time( g->u ); + time = vehint.sel_vpart_info->install_time( u ); break; case 'r': time = setuptime + std::max(mintime, (8 * diff - skill * 4) * dmg); break; case 'o': - time = vehint.sel_vpart_info->removal_time( g->u ); + time = vehint.sel_vpart_info->removal_time( u ); break; case 'c': - time = vehint.sel_vpart_info->removal_time( g->u ) + - vehint.sel_vpart_info->install_time( g->u ); + time = vehint.sel_vpart_info->removal_time( u ) + + vehint.sel_vpart_info->install_time( u ); break; } u.assign_activity( ACT_VEHICLE, time, (int)vehint.sel_cmd ); From a9712c7c3517f4441a74105f84be2cde2c8eef08 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:45:19 +0100 Subject: [PATCH 15/31] Add std namespace --- src/veh_interact.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 572498d575252..0411d211b22a7 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -550,13 +550,13 @@ bool veh_interact::can_install_part() { item base( sel_vpart_info->item ); if( base.is_wheel() ) { qual = JACK; - lvl = ceil( double( std::min( veh->total_mass() * 1000, JACK_LIMIT ) / TOOL_LIFT_FACTOR ) ); + lvl = std::ceil( double( std::min( veh->total_mass() * 1000, JACK_LIMIT ) / TOOL_LIFT_FACTOR ) ); str = veh->lift_strength(); use_aid = max_jack >= lvl; use_str = g->u.can_lift( *veh ); } else { qual = LIFT; - lvl = ceil( double( base.weight() ) / TOOL_LIFT_FACTOR ); + lvl = std::ceil( double( base.weight() ) / TOOL_LIFT_FACTOR ); str = base.lift_strength(); use_aid = max_lift >= lvl; use_str = g->u.can_lift( base ); @@ -1073,13 +1073,13 @@ bool veh_interact::can_remove_part( int idx ) { item base( sel_vpart_info->item ); if( base.is_wheel() ) { qual = JACK; - lvl = ceil( double( std::min( veh->total_mass() * 1000, JACK_LIMIT ) / TOOL_LIFT_FACTOR ) ); + lvl = std::ceil( double( std::min( veh->total_mass() * 1000, JACK_LIMIT ) / TOOL_LIFT_FACTOR ) ); str = veh->lift_strength(); use_aid = max_jack >= lvl; use_str = g->u.can_lift( *veh ); } else { qual = LIFT; - lvl = ceil( double( base.weight() ) / TOOL_LIFT_FACTOR ); + lvl = std::ceil( double( base.weight() ) / TOOL_LIFT_FACTOR ); str = base.lift_strength(); use_aid = max_lift >= lvl; use_str = g->u.can_lift( base ); From ce2954eb4ff735f2107c480369a2458c16a41a76 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:48:35 +0100 Subject: [PATCH 16/31] Fix correct casting to double --- src/veh_interact.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 0411d211b22a7..fbd15dc96bbcd 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -550,7 +550,7 @@ bool veh_interact::can_install_part() { item base( sel_vpart_info->item ); if( base.is_wheel() ) { qual = JACK; - lvl = std::ceil( double( std::min( veh->total_mass() * 1000, JACK_LIMIT ) / TOOL_LIFT_FACTOR ) ); + lvl = std::ceil( double( std::min( veh->total_mass() * 1000, JACK_LIMIT ) ) / TOOL_LIFT_FACTOR ); str = veh->lift_strength(); use_aid = max_jack >= lvl; use_str = g->u.can_lift( *veh ); @@ -1073,13 +1073,13 @@ bool veh_interact::can_remove_part( int idx ) { item base( sel_vpart_info->item ); if( base.is_wheel() ) { qual = JACK; - lvl = std::ceil( double( std::min( veh->total_mass() * 1000, JACK_LIMIT ) / TOOL_LIFT_FACTOR ) ); + lvl = std::ceil( double( std::min( veh->total_mass() * 1000, JACK_LIMIT ) ) / TOOL_LIFT_FACTOR ); str = veh->lift_strength(); use_aid = max_jack >= lvl; use_str = g->u.can_lift( *veh ); } else { qual = LIFT; - lvl = std::ceil( double( base.weight() ) / TOOL_LIFT_FACTOR ); + lvl = ceil( double( base.weight() ) / TOOL_LIFT_FACTOR ); str = base.lift_strength(); use_aid = max_lift >= lvl; use_str = g->u.can_lift( base ); From 161a7dced9576da36ec184f02d05f6a6d2a158e6 Mon Sep 17 00:00:00 2001 From: Mugling Date: Sun, 19 Jun 2016 10:49:07 +0100 Subject: [PATCH 17/31] Use C++11 nullptr idiom --- src/veh_interact.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index fbd15dc96bbcd..34d9a4d63231a 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -1035,7 +1035,7 @@ void veh_interact::do_refill() } bool veh_interact::can_remove_part( int idx ) { - if( sel_vpart_info == NULL ) { + if( sel_vpart_info == nullptr ) { werase( w_msg ); wrefresh (w_msg); return false; From 8cb88d85f794382f3a63adbc6fb7f182fde84660 Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 00:43:03 +0100 Subject: [PATCH 18/31] Increase to SAW_M level 2 --- data/json/vehicleparts/frames.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/json/vehicleparts/frames.json b/data/json/vehicleparts/frames.json index 1b586f84dfe6e..d32252cf137c4 100644 --- a/data/json/vehicleparts/frames.json +++ b/data/json/vehicleparts/frames.json @@ -51,7 +51,7 @@ }, "removal": { "skills": [ [ "mechanics", 1 ] ], - "qualities": [ { "id": "SAW_M", "level": 1 } ] + "qualities": [ { "id": "SAW_M", "level": 2 } ] } }, "breaks_into": "ig_vp_frame", @@ -108,7 +108,7 @@ }, "removal": { "skills": [ [ "mechanics", 1 ] ], - "qualities": [ { "id": "SAW_M", "level": 1 } ] + "qualities": [ { "id": "SAW_M", "level": 2 } ] } }, "breaks_into": "ig_vp_hdframe", From 0061e57bcda9fa15fded11fafc239e5d57bc4fc4 Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 00:43:50 +0100 Subject: [PATCH 19/31] Fix inverted conditional --- src/veh_interact.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 34d9a4d63231a..f3f8a31cc1c3c 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -2178,7 +2178,7 @@ void complete_vehicle () add_msg( m_good, _("You install a %1$s into the %2$s." ), veh->parts[ partnum ].name().c_str(), veh->name.c_str() ); - if( reqs.get_tools().empty() ) { + if( !reqs.get_tools().empty() ) { g->u.practice( skill_mechanics, vpinfo.difficulty * 50 ); } break; @@ -2255,7 +2255,7 @@ void complete_vehicle () if (!broken) { g->m.add_item_or_charges( g->u.pos(), veh->parts[vehicle_part].properties_to_item() ); // simple tasks won't train mechanics - if( reqs.get_tools().empty() ) { + if( !reqs.get_tools().empty() ) { g->u.practice( skill_mechanics, vpinfo.difficulty * 50 ); } } else { From 99aa03e2db419cc3d092121a48f52030a2b95f14 Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 02:33:50 +0100 Subject: [PATCH 20/31] Full screen display --- src/veh_interact.cpp | 60 +++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index f3f8a31cc1c3c..729441b75441c 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -117,28 +117,14 @@ void veh_interact::exec(vehicle *v) void veh_interact::allocate_windows() { - // main window should also expand to use available display space. - // expanding to evenly use up half of extra space, for now. - const int extra_w = ((TERMX - FULL_SCREEN_WIDTH) / 4) * 2; - const int extra_h = ((TERMY - FULL_SCREEN_HEIGHT) / 4) * 2; - const int total_w = FULL_SCREEN_WIDTH + extra_w; - const int total_h = FULL_SCREEN_HEIGHT + extra_h; - - // position of window within main display - const int x0 = (TERMX - total_w) / 2; - const int y0 = (TERMY - total_h) / 2; - // border window - WINDOW *w_border = newwin(total_h, total_w, y0, x0); + WINDOW *w_border = newwin( TERMY, TERMX, 0, 0 ); draw_border(w_border); // grid window - const int grid_w = total_w - 2; // exterior borders take 2 - const int grid_h = total_h - 2; // exterior borders take 2 - w_grid = newwin(grid_h, grid_w, y0 + 1, x0 + 1); - - int mode_x, mode_y, msg_x, disp_x, parts_x; - int stats_x, stats_y, list_x, name_x, name_y; + const int grid_w = TERMX - 2; // exterior borders take 2 + const int grid_h = TERMY - 2; // exterior borders take 2 + w_grid = newwin(grid_h, grid_w, 1, 1); int mode_h = 1; int name_h = 1; @@ -146,7 +132,7 @@ void veh_interact::allocate_windows() page_size = grid_h - ( mode_h + stats_h + name_h ) - 2; - int pane_y = y0 + 1 + mode_h + 1; + int pane_y = 1 + mode_h + 1; int pane_w = ( grid_w / 3 ) - 1; @@ -155,34 +141,28 @@ void veh_interact::allocate_windows() int parts_h = page_size - disp_h; int parts_y = pane_y + disp_h; - mode_y = y0 + 1; - name_y = pane_y + page_size + 1; - stats_y = name_y + name_h; - - mode_x = x0 + 1; - disp_x = x0 + 1; - parts_x = x0 + 1; - name_x = x0 + 1; - stats_x = x0 + 1; + int name_y = pane_y + page_size + 1; + int stats_y = name_y + name_h; - list_x = disp_x + disp_w + 1; - msg_x = list_x + pane_w + 1; + int list_x = 1 + disp_w + 1; + int msg_x = list_x + pane_w + 1; // match grid lines mvwputch(w_border, mode_h + 1, 0, BORDER_COLOR, LINE_XXXO); // |- - mvwputch(w_border, mode_h + 1, total_w - 1, BORDER_COLOR, LINE_XOXX); // -| + mvwputch(w_border, mode_h + 1, TERMX - 1, BORDER_COLOR, LINE_XOXX); // -| mvwputch(w_border, mode_h + 1 + page_size + 1, 0, BORDER_COLOR, LINE_XXXO); // |- - mvwputch(w_border, mode_h + 1 + page_size + 1, total_w - 1, BORDER_COLOR, LINE_XOXX); // -| + mvwputch(w_border, mode_h + 1 + page_size + 1, TERMX - 1, BORDER_COLOR, LINE_XOXX); // -| // make the windows - w_mode = newwin(mode_h, grid_w, mode_y, mode_x ); - w_msg = newwin(page_size, pane_w, pane_y, msg_x ); - w_disp = newwin(disp_h, disp_w, pane_y, disp_x ); - w_parts = newwin(parts_h, disp_w, parts_y, parts_x); - w_list = newwin(page_size, pane_w, pane_y, list_x ); - w_details = NULL; // only pops up when in install menu - w_stats = newwin(stats_h, grid_w, stats_y, stats_x); - w_name = newwin(name_h, grid_w, name_y, name_x ); + w_mode = newwin( mode_h, grid_w, 1, 1 ); + w_msg = newwin( page_size, pane_w, pane_y, msg_x ); + w_disp = newwin( disp_h, disp_w, pane_y, 1 ); + w_parts = newwin( parts_h, disp_w, parts_y, 1); + w_list = newwin( page_size, pane_w, pane_y, list_x ); + w_stats = newwin( stats_h, grid_w, stats_y, 1 ); + w_name = newwin( name_h, grid_w, name_y, 1 ); + + w_details = NULL; // only pops up when in install menu wrefresh(w_border); delwin( w_border ); From b046f82ede48a3515afb7e35dd6c14e2eab2f629 Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 02:39:31 +0100 Subject: [PATCH 21/31] Fix handling of TOOL_NONE --- src/veh_type.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/veh_type.cpp b/src/veh_type.cpp index ba98f4071be32..fa6b46cf1b6d4 100644 --- a/src/veh_type.cpp +++ b/src/veh_type.cpp @@ -385,6 +385,8 @@ void vpart_info::check() part.install_reqs.qualities = { { { { quality_id( "HAMMER" ), 1, 1 } } } }; part.removal_reqs.qualities = { { { { quality_id( "HAMMER" ), 1, 1 } } } }; part.install_reqs.components.push_back( { { { "nail", 20 } } } ); + } else if( part.has_flag( "TOOL_NONE" ) { + // intentional no-op as we require nothing } else { part.install_reqs.components.push_back( { { { "duct_tape", 20 } } } ); } From df0fbff09348023357dd10d5baf83563c11b48d8 Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 02:45:10 +0100 Subject: [PATCH 22/31] Default to welding not duct tape --- src/veh_type.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/veh_type.cpp b/src/veh_type.cpp index fa6b46cf1b6d4..fdb6d873658ef 100644 --- a/src/veh_type.cpp +++ b/src/veh_type.cpp @@ -385,10 +385,11 @@ void vpart_info::check() part.install_reqs.qualities = { { { { quality_id( "HAMMER" ), 1, 1 } } } }; part.removal_reqs.qualities = { { { { quality_id( "HAMMER" ), 1, 1 } } } }; part.install_reqs.components.push_back( { { { "nail", 20 } } } ); - } else if( part.has_flag( "TOOL_NONE" ) { + } else if( part.has_flag( "TOOL_NONE" ) ) { // intentional no-op as we require nothing } else { - part.install_reqs.components.push_back( { { { "duct_tape", 20 } } } ); + part.install_reqs.qualities = { { { { quality_id( "GLARE" ), 1, 2 } } } }; + part.install_reqs.tools.push_back( { { { "welder", 50 }, { "welder_crude", 75 }, { "oxy_torch", 25 } } } ); } } From c450359a133312f45c515bfbd277394e43db64f4 Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 03:09:05 +0100 Subject: [PATCH 23/31] Update legacy requirements --- src/veh_type.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/veh_type.cpp b/src/veh_type.cpp index fdb6d873658ef..8a2ffa23ebff1 100644 --- a/src/veh_type.cpp +++ b/src/veh_type.cpp @@ -388,8 +388,11 @@ void vpart_info::check() } else if( part.has_flag( "TOOL_NONE" ) ) { // intentional no-op as we require nothing } else { - part.install_reqs.qualities = { { { { quality_id( "GLARE" ), 1, 2 } } } }; - part.install_reqs.tools.push_back( { { { "welder", 50 }, { "welder_crude", 75 }, { "oxy_torch", 25 } } } ); + part.install_reqs.qualities = { { { { quality_id( "WRENCH" ), 1, 2 } }, + { { quality_id( "GLARE" ), 1, 2 } } } }; + part.install_reqs.tools.push_back( { { { "welder", 50 }, { "welder_crude", 75 }, { "oxy_torch", 10 } } } ); + part.removal_reqs.qualities = { { { { quality_id( "WRENCH" ), 1, 2 } }, + { { quality_id( "SAW_M" ), 1, 2 } } } }; } } From 7e6df20bf667ad5cdb9eecc9e999fe6ab29ea460 Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 03:42:30 +0100 Subject: [PATCH 24/31] Refactor part list suggestion order --- src/veh_interact.cpp | 19 ++++++------------- src/veh_interact.h | 2 +- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 729441b75441c..2f4001d9b8c63 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -1306,20 +1306,13 @@ int veh_interact::part_at (int dx, int dy) } /** - * Checks to see if you can currently install this part at current position. + * Checks to see if you can potentially install this part at current position. * Affects coloring in display_list() and is also used to - * sort can_mount so installable parts come first. + * sort can_mount so potentially installable parts come first. */ -bool veh_interact::can_currently_install(const vpart_info &vpart) +bool veh_interact::can_potentially_install(const vpart_info &vpart) { - if (g->u.has_trait("DEBUG_HS")) { - return true; - } - bool has_comps = crafting_inv.has_components(vpart.item, 1); - ///\EFFECT_MECHANICS determines which vehicle parts can be installed - bool has_skill = g->u.get_skill_level( skill_mechanics ) >= vpart.difficulty; - bool is_wheel = vpart.has_flag("WHEEL"); - return (has_comps && (has_skill || is_wheel)); + return g->u.has_trait( "DEBUG_HS" ) || vpart.install_reqs.can_make_with_inventory( crafting_inv ); } /** @@ -1364,7 +1357,7 @@ void veh_interact::move_cursor (int dx, int dy) const vpart_info &vpi = *vp; if ( vpi.id != vpart_shapes[ vpi.name()+ vpi.item][0]->id ) continue; // only add first shape to install list - if (can_currently_install(vpi)) { + if (can_potentially_install(vpi)) { can_mount.insert( can_mount.begin() + divider_index++, &vpi ); } else { can_mount.push_back( &vpi ); @@ -1738,7 +1731,7 @@ void veh_interact::display_list(size_t pos, std::vector list, const vpart_info &info = *list[i]; int y = i - page * lines_per_page + header; mvwputch( w_list, y, 1, info.color, special_symbol( info.sym ) ); - nc_color col = can_currently_install( info ) ? c_white : c_dkgray; + nc_color col = can_potentially_install( info ) ? c_white : c_dkgray; trim_and_print( w_list, y, 3, getmaxx( w_list ) - 3, pos == i ? hilite( col ) : col, info.name().c_str() ); } diff --git a/src/veh_interact.h b/src/veh_interact.h index 154ac1db40f55..7db7f1cc6e8eb 100644 --- a/src/veh_interact.h +++ b/src/veh_interact.h @@ -85,7 +85,7 @@ class veh_interact int part_at( int dx, int dy ); void move_cursor( int dx, int dy ); task_reason cant_do( char mode ); - bool can_currently_install( const vpart_info &vpart ); + bool can_potentially_install( const vpart_info &vpart ); /** Move index (parameter pos) according to input action: * (up or down, single step or whole page). * @param pos index to change. From 2cf5a942044befb36d3c48352396db864cd88a08 Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 03:44:00 +0100 Subject: [PATCH 25/31] Correctly break for missing requirements --- src/veh_interact.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 2f4001d9b8c63..09ecc0e7f8594 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -2094,6 +2094,7 @@ void complete_vehicle () const auto& reqs = vpinfo.install_reqs; if( !reqs.can_make_with_inventory( inv ) ) { add_msg( m_info, _( "You lack the requirements to install the %s." ), vpinfo.name().c_str() ); + break; } // consume items extracting a match for the parts base item @@ -2203,6 +2204,7 @@ void complete_vehicle () const auto& reqs = vpinfo.removal_reqs; if( !reqs.can_make_with_inventory( inv ) ) { add_msg( m_info, _( "You lack the requirements to remove the %s." ), vpinfo.name().c_str() ); + break; } for( const auto& e : reqs.get_components() ) { From 88c5409c6b56a26bb5b9230af72e9da189ee9a89 Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 04:11:10 +0100 Subject: [PATCH 26/31] Replace unsafe idiom with conditional --- src/veh_interact.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 09ecc0e7f8594..5d77c8defe0cd 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -494,7 +494,9 @@ bool veh_interact::can_install_part() { msg << _( "Skills required:\n" ); for( const auto& e : sel_vpart_info->install_skills ) { bool hasSkill = g->u.get_skill_level( e.first ) >= e.second; - ok -= !hasSkill; + if( !hasSkill ) { + ok = false; + } msg << string_format( "> %2$s %3$i\n", status_color( hasSkill ), _( e.first.obj().name().c_str() ), e.second ); } @@ -511,14 +513,18 @@ bool veh_interact::can_install_part() { msg << _( "Additional requirements:\n" ); if( dif_eng > 0 ) { - ok -= g->u.get_skill_level( skill_mechanics ) < dif_eng; + if( g->u.get_skill_level( skill_mechanics ) < dif_eng ) { + ok = false; + } msg << string_format( _( "> %2$s %3$i for extra engines." ), status_color( g->u.get_skill_level( skill_mechanics ) >= dif_eng ), skill_mechanics.obj().name().c_str(), dif_eng ) << "\n"; } if( dif_steering > 0 ) { - ok -= g->u.get_skill_level( skill_mechanics ) < dif_steering; + if( g->u.get_skill_level( skill_mechanics ) < dif_steering ) { + ok = false; + } msg << string_format( _( "> %2$s %3$i for extra steering axles." ), status_color( g->u.get_skill_level( skill_mechanics ) >= dif_steering ), skill_mechanics.obj().name().c_str(), dif_steering ) << "\n"; @@ -542,7 +548,9 @@ bool veh_interact::can_install_part() { use_str = g->u.can_lift( base ); } - ok -= !( use_aid || use_str ); + if( !( use_aid || use_str ) ) { + ok = false; + } msg << string_format( _( "> 1 tool with %2$s %3$i OR strength %5$i" ), status_color( use_aid ), qual.obj().name.c_str(), lvl, status_color( use_str ), str ) << "\n"; @@ -1031,7 +1039,9 @@ bool veh_interact::can_remove_part( int idx ) { msg << _( "Skills required:\n" ); for( const auto& e : sel_vpart_info->removal_skills ) { bool hasSkill = g->u.get_skill_level( e.first ) >= e.second; - ok -= !hasSkill; + if( !hasSkill ) { + ok = false; + } msg << string_format( "> %2$s %3$i\n", status_color( hasSkill ), _( e.first.obj().name().c_str() ), e.second ); } @@ -1065,7 +1075,9 @@ bool veh_interact::can_remove_part( int idx ) { use_str = g->u.can_lift( base ); } - ok -= !( use_aid || use_str ); + if( !( use_aid || use_str ) ) { + ok = false; + } msg << string_format( _( "> 1 tool with %2$s %3$i OR strength %5$i" ), status_color( use_aid ), qual.obj().name.c_str(), lvl, status_color( use_str ), str ) << "\n"; From a216c26b792ea3a7c41d449e901b652834ab9298 Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 04:23:28 +0100 Subject: [PATCH 27/31] Add WRENCH 2 quality --- data/json/items/fake.json | 2 +- data/json/items/tools.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/json/items/fake.json b/data/json/items/fake.json index c890d436364d7..42d7a57503152 100644 --- a/data/json/items/fake.json +++ b/data/json/items/fake.json @@ -18,7 +18,7 @@ "qualities": [ [ "HAMMER", 3 ], [ "HAMMER_FINE", 1 ], [ "SAW_W", 1 ], [ "SAW_M", 2 ], [ "SAW_M_FINE", 1 ], - [ "WRENCH", 1 ], [ "WRENCH_FINE", 1 ], + [ "WRENCH", 2 ], [ "WRENCH_FINE", 1 ], [ "SCREW", 1 ], [ "SCREW_FINE", 1 ], [ "CUT", 2 ], [ "PRY", 1 ], ["DRILL", 1 ], [ "BUTCHER", -100 ] diff --git a/data/json/items/tools.json b/data/json/items/tools.json index 4ecff0ba24c42..367f744283ae8 100644 --- a/data/json/items/tools.json +++ b/data/json/items/tools.json @@ -5114,7 +5114,7 @@ "volume": 2, "bashing": 9, "to_hit": 2, - "qualities": [["WRENCH", 1], ["WRENCH_FINE", 1]] + "qualities": [ ["WRENCH", 2 ], [ "WRENCH_FINE", 1 ] ] }, { "id": "pliers", @@ -7130,7 +7130,7 @@ "bashing": 8, "to_hit": -2, "use_action": [ "HAMMER" ], - "qualities": [["CUT", 1], ["HAMMER", 3], ["SAW_M", 2], ["SAW_W", 2], ["WRENCH", 1], + "qualities": [["CUT", 1], ["HAMMER", 3], ["SAW_M", 2], ["SAW_W", 2], ["WRENCH", 2], ["SCREW", 1], ["HAMMER_FINE", 1], ["SAW_M_FINE", 1], ["WRENCH_FINE", 1], ["SCREW_FINE", 1], ["BUTCHER", 12]] }, From d441efcd5945d6bc2a580d6e6eefba5edba66fca Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 04:41:59 +0100 Subject: [PATCH 28/31] Update missed WRENCH 2 --- data/json/items/tool_armor.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/json/items/tool_armor.json b/data/json/items/tool_armor.json index ef6d174e05a7e..96637f2589959 100644 --- a/data/json/items/tool_armor.json +++ b/data/json/items/tool_armor.json @@ -1187,7 +1187,7 @@ "max_volume": 4, "flags": [ "SHEATH_KNIFE", "SHEATH_SWORD" ] }, "HAMMER" ], - "qualities": [["HAMMER", 3], ["SAW_M", 2], ["SAW_W", 2], ["WRENCH", 1], + "qualities": [["HAMMER", 3], ["SAW_M", 2], ["SAW_W", 2], ["WRENCH", 2], ["SCREW", 1], ["HAMMER_FINE", 1], ["SAW_M_FINE", 1], ["WRENCH_FINE", 1], ["SCREW_FINE", 1]] }, { From 6ec8ef55a114ed6cf1aaa88993a1cc7b5d4661b3 Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 04:47:51 +0100 Subject: [PATCH 29/31] Update removal difficulty --- data/json/vehicle_parts.json | 14 +++++++++++++- src/veh_type.cpp | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/data/json/vehicle_parts.json b/data/json/vehicle_parts.json index 51a020c569d9a..af4a7f0378138 100644 --- a/data/json/vehicle_parts.json +++ b/data/json/vehicle_parts.json @@ -1702,7 +1702,19 @@ "item" : "processor", "difficulty" : 6, "location" : "on_controls", - "flags" : ["ON_CONTROLS", "DIFFICULTY_REMOVE", "SECURITY"], + "requirements": { + "install": { + "time": 30000, + "skills": [ [ "mechanics", 4 ], [ "electronics", 4 ] ], + "qualities": [ { "id": "SCREW", "level": 2 } ], + "components": [ [ [ "processor", 1 ] ] ] + }, + "removal": { + "skills": [ [ "mechanics", 4 ], [ "electronics", 4 ] ], + "qualities": [ { "id": "SCREW", "level": 2 } ] + } + }, + "flags" : ["ON_CONTROLS", "SECURITY"], "breaks_into" : [ {"item": "scrap", "prob": 50}, {"item": "e_scrap", "count": [0, 3]} diff --git a/src/veh_type.cpp b/src/veh_type.cpp index 8a2ffa23ebff1..59cdd10cb4bc6 100644 --- a/src/veh_type.cpp +++ b/src/veh_type.cpp @@ -373,7 +373,7 @@ void vpart_info::check() part.install_reqs.components = { { { { part.item, 1 } } } }; part.install_skills.emplace( skill_mechanics, part.difficulty ); - part.removal_skills.emplace( skill_mechanics, part.difficulty ); + part.removal_skills.emplace( skill_mechanics, std::max( part.difficulty - 2, 2 ) ); if( part.has_flag( "TOOL_WRENCH" ) || part.has_flag( "WHEEL" ) ) { part.install_reqs.qualities = { { { quality_id( "WRENCH" ), 1, 1 } } }; From 6c7a18981e20f5490cc370683e696dae4c438c18 Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 05:00:18 +0100 Subject: [PATCH 30/31] Use fine screwdriving --- data/json/vehicle_parts.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/json/vehicle_parts.json b/data/json/vehicle_parts.json index af4a7f0378138..6da12db909567 100644 --- a/data/json/vehicle_parts.json +++ b/data/json/vehicle_parts.json @@ -1706,12 +1706,12 @@ "install": { "time": 30000, "skills": [ [ "mechanics", 4 ], [ "electronics", 4 ] ], - "qualities": [ { "id": "SCREW", "level": 2 } ], + "qualities": [ { "id": "SCREW_F", "level": 1 } ], "components": [ [ [ "processor", 1 ] ] ] }, "removal": { "skills": [ [ "mechanics", 4 ], [ "electronics", 4 ] ], - "qualities": [ { "id": "SCREW", "level": 2 } ] + "qualities": [ { "id": "SCREW_F", "level": 1 } ] } }, "flags" : ["ON_CONTROLS", "SECURITY"], From cbe52fd0d018bc5c1a46cc0084d47a6f3c6ad9aa Mon Sep 17 00:00:00 2001 From: Mugling Date: Wed, 22 Jun 2016 05:06:24 +0100 Subject: [PATCH 31/31] Try again --- data/json/vehicle_parts.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/json/vehicle_parts.json b/data/json/vehicle_parts.json index 6da12db909567..72f7605179df6 100644 --- a/data/json/vehicle_parts.json +++ b/data/json/vehicle_parts.json @@ -1706,12 +1706,12 @@ "install": { "time": 30000, "skills": [ [ "mechanics", 4 ], [ "electronics", 4 ] ], - "qualities": [ { "id": "SCREW_F", "level": 1 } ], + "qualities": [ { "id": "SCREW_FINE", "level": 1 } ], "components": [ [ [ "processor", 1 ] ] ] }, "removal": { "skills": [ [ "mechanics", 4 ], [ "electronics", 4 ] ], - "qualities": [ { "id": "SCREW_F", "level": 1 } ] + "qualities": [ { "id": "SCREW_FINE", "level": 1 } ] } }, "flags" : ["ON_CONTROLS", "SECURITY"],