From 12443935e6b55d19e3f985c3ec0cae531e458837 Mon Sep 17 00:00:00 2001 From: davidpwbrown <39344466+davidpwbrown@users.noreply.github.com> Date: Fri, 6 Mar 2020 11:34:18 +0000 Subject: [PATCH] Allow professions to start with a nearby vehicle (#37314) Adds trucker profession. --- data/json/professions.json | 17 +++++++++++++ doc/JSON_INFO.md | 16 +++++++++--- src/game.cpp | 52 ++++++++++++++++++++++++++++++++++++++ src/game.h | 4 ++- src/newcharacter.cpp | 9 ++++++- src/overmapbuffer.cpp | 3 ++- src/player.h | 2 +- src/profession.cpp | 13 +++++++++- src/profession.h | 3 +++ src/string_id_null_ids.cpp | 1 + 10 files changed, 111 insertions(+), 9 deletions(-) diff --git a/data/json/professions.json b/data/json/professions.json index cfa565f1af588..a6a973384eb1b 100644 --- a/data/json/professions.json +++ b/data/json/professions.json @@ -1481,6 +1481,23 @@ "female": [ "bra", "panties" ] } }, + { + "type": "profession", + "ident": "trucker", + "name": "Trucker", + "description": "You ruled the road in your big rig and managed to drive it somewhere you hoped was safe when the riots hit. Now it's just you and your trusty truck cab.", + "points": 5, + "skills": [ { "level": 1, "name": "mechanics" }, { "level": 4, "name": "driving" } ], + "vehicle": "semi_truck", + "items": { + "both": { + "items": [ "tank_top", "socks", "boots_steel", "pants", "multitool", "wristwatch", "gloves_work", "hat_ball" ], + "entries": [ { "group": "charged_cell_phone" } ] + }, + "male": [ "boxer_shorts" ], + "female": [ "bra", "panties" ] + } + }, { "type": "profession", "ident": "lumberjack", diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index b31c3ce06e8e5..303daab1d8aa4 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -814,12 +814,20 @@ Example for mods: This mod removes one of the rocks (the other rock is still created), the t-shirt, adds a 2x4 item and gives female characters a t-shirt with the special snippet id. -#### `pet` +#### `pets` -(optional, string mtype_id) +(optional, array of string mtype_ids ) -A string that is the same as a monster id -player will start with this as a tamed pet. +A list of strings, each is the same as a monster id +player will start with these as tamed pets. + +#### `vehicle` + +(optional, string vproto_id ) + +A string, which is the same as a vehicle ( vproto_id ) +player will start with this as a nearby vehicle. +( it will find the nearest road and place it there, then mark it as "remembered" on the overmap ) #### `flags` diff --git a/src/game.cpp b/src/game.cpp index 48e63c554742d..5f47840d25822 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -838,6 +838,11 @@ bool game::start_game() add_msg( m_debug, "cannot place starting pet, no space!" ); } } + if( u.starting_vehicle && + !place_vehicle_nearby( u.starting_vehicle, u.global_omt_location().xy(), 1, 30, + std::vector {} ) ) { + debugmsg( "could not place starting vehicle" ); + } // Assign all of this scenario's missions to the player. for( const mission_type_id &m : scen->missions() ) { const auto mission = mission::reserve_new( m, character_id() ); @@ -848,6 +853,53 @@ bool game::start_game() return true; } +vehicle *game::place_vehicle_nearby( const vproto_id &id, const point &origin, int min_distance, + int max_distance, const std::vector &omt_search_types ) +{ + std::vector search_types = omt_search_types; + if( search_types.empty() ) { + vehicle veh( id ); + std::vector omt_search_types; + if( veh.max_ground_velocity() > 0 ) { + search_types.push_back( "road" ); + search_types.push_back( "field" ); + } else if( veh.can_float() ) { + search_types.push_back( "river" ); + search_types.push_back( "lake" ); + } + } + for( const std::string &search_type : search_types ) { + omt_find_params find_params; + find_params.must_see = false; + find_params.cant_see = false; + find_params.types.emplace_back( search_type, ot_match_type::type ); + // find nearest road + find_params.min_distance = min_distance; + find_params.search_range = max_distance; + // if player spawns underground, park their car on the surface. + const tripoint omt_origin( origin.x, origin.y, 0 ); + for( const tripoint &goal : overmap_buffer.find_all( omt_origin, find_params ) ) { + // try place vehicle there. + tinymap target_map; + target_map.load( omt_to_sm_copy( goal ), false ); + const tripoint origin( SEEX, SEEY, goal.z ); + static const std::vector angles = {0, 90, 180, 270}; + vehicle *veh = target_map.add_vehicle( id, origin, random_entry( angles ), rng( 50, 80 ), + 0, + false ); + if( veh ) { + tripoint abs_local = g->m.getlocal( target_map.getabs( origin ) ); + veh->sm_pos = ms_to_sm_remain( abs_local ); + veh->pos = abs_local.xy(); + overmap_buffer.add_vehicle( veh ); + target_map.save(); + return veh; + } + } + } + return nullptr; +} + //Make any nearby overmap npcs active, and put them in the right location. void game::load_npcs() { diff --git a/src/game.h b/src/game.h index 767ad951ee788..6c3aa728ce561 100644 --- a/src/game.h +++ b/src/game.h @@ -733,7 +733,9 @@ class game // Data Initialization void init_autosave(); // Initializes autosave parameters void create_starting_npcs(); // Creates NPCs that start near you - + // create vehicle nearby, for example; for a profession vehicle. + vehicle *place_vehicle_nearby( const vproto_id &id, const point &origin, int min_distance, + int max_distance, const std::vector &omt_search_types = {} ); // V Menu Functions and helpers: void list_items_monsters(); // Called when you invoke the `V`-menu diff --git a/src/newcharacter.cpp b/src/newcharacter.cpp index 7504dc5d5b83c..092ef74843c8d 100644 --- a/src/newcharacter.cpp +++ b/src/newcharacter.cpp @@ -52,6 +52,7 @@ #include "pimpl.h" #include "type_id.h" #include "cata_string_consts.h" +#include "veh_type.h" // Colors used in this file: (Most else defaults to c_light_gray) #define COL_STAT_ACT c_white // Selected stat @@ -519,6 +520,7 @@ bool avatar::create( character_type type, const std::string &tempname ) for( mtype_id elem : prof->pets() ) { starting_pets.push_back( elem ); } + starting_vehicle = prof->vehicle(); std::list prof_items = prof->items( male, get_mutations() ); for( item &it : prof_items ) { @@ -1479,7 +1481,6 @@ tab_direction set_profession( const catacurses::window &w, avatar &u, points_lef } } // Profession pet - cata::optional montype; if( !sorted_profs[cur_id]->pets().empty() ) { buffer += colorize( _( "Pets:" ), c_light_blue ) + "\n"; for( auto elem : sorted_profs[cur_id]->pets() ) { @@ -1487,6 +1488,12 @@ tab_direction set_profession( const catacurses::window &w, avatar &u, points_lef buffer += mon.get_name() + "\n"; } } + // Profession vehicle + if( sorted_profs[cur_id]->vehicle() ) { + buffer += colorize( _( "Vehicle:" ), c_light_blue ) + "\n"; + vproto_id veh_id = sorted_profs[cur_id]->vehicle(); + buffer += veh_id->name; + } // Profession spells if( !sorted_profs[cur_id]->spells().empty() ) { buffer += colorize( _( "Spells:" ), c_light_blue ) + "\n"; diff --git a/src/overmapbuffer.cpp b/src/overmapbuffer.cpp index 2de6c86b85028..516c69e5fc9db 100644 --- a/src/overmapbuffer.cpp +++ b/src/overmapbuffer.cpp @@ -600,7 +600,8 @@ void overmapbuffer::remove_vehicle( const vehicle *veh ) void overmapbuffer::add_vehicle( vehicle *veh ) { - const point omt = ms_to_omt_copy( g->m.getabs( veh->global_pos3().xy() ) ); + const point abs_pos = g->m.getabs( veh->global_pos3().xy() ); + const point omt = ms_to_omt_copy( abs_pos ); const overmap_with_local_coords om_loc = get_om_global( omt ); int id = om_loc.om->vehicles.size() + 1; // this *should* be unique but just in case diff --git a/src/player.h b/src/player.h index dcf5910a8ad0f..fedd52b66ff0f 100644 --- a/src/player.h +++ b/src/player.h @@ -938,7 +938,7 @@ class player : public Character bool reach_attacking = false; bool manual_examine = false; - + vproto_id starting_vehicle; std::vector starting_pets; void make_craft_with_command( const recipe_id &id_to_make, int batch_size, bool is_long = false, diff --git a/src/profession.cpp b/src/profession.cpp index 20765f0229e7b..87f4c62ddd64f 100644 --- a/src/profession.cpp +++ b/src/profession.cpp @@ -171,6 +171,9 @@ void profession::load( const JsonObject &jo, const std::string & ) _description_male = to_translation( "prof_desc_male", desc ); _description_female = to_translation( "prof_desc_female", desc ); } + if( jo.has_string( "vehicle" ) ) { + _starting_vehicle = vproto_id( jo.get_string( "vehicle" ) ); + } if( jo.has_array( "pets" ) ) { for( JsonObject subobj : jo.get_array( "pets" ) ) { int count = subobj.get_int( "amount" ); @@ -286,7 +289,10 @@ void profession::check_definition() const if( !item_group::group_is_defined( _starting_items_female ) ) { debugmsg( "_starting_items_female group is undefined" ); } - + if( _starting_vehicle && !_starting_vehicle.is_valid() ) { + debugmsg( "vehicle prototype %s for profession %s does not exist", _starting_vehicle.c_str(), + id.c_str() ); + } for( const auto &a : _starting_CBMs ) { if( !a.is_valid() ) { debugmsg( "bionic %s for profession %s does not exist", a.c_str(), id.c_str() ); @@ -434,6 +440,11 @@ std::list profession::items( bool male, const std::vector &trait return result; } +vproto_id profession::vehicle() const +{ + return _starting_vehicle; +} + std::vector profession::pets() const { return _starting_pets; diff --git a/src/profession.h b/src/profession.h index 1c9427a717d05..61649631d7b31 100644 --- a/src/profession.h +++ b/src/profession.h @@ -13,6 +13,7 @@ #include "pldata.h" #include "translations.h" #include "type_id.h" +#include "veh_type.h" template class generic_factory; @@ -69,6 +70,7 @@ class profession std::vector _starting_CBMs; std::vector _starting_traits; std::vector _starting_pets; + vproto_id _starting_vehicle = vproto_id::NULL_ID(); // the int is what level the spell starts at std::map _starting_spells; std::set flags; // flags for some special properties of the profession @@ -103,6 +105,7 @@ class profession signed int point_cost() const; std::list items( bool male, const std::vector &traits ) const; std::vector addictions() const; + vproto_id vehicle() const; std::vector pets() const; std::vector CBMs() const; StartingSkillList skills() const; diff --git a/src/string_id_null_ids.cpp b/src/string_id_null_ids.cpp index 3c57688a3b1dd..b33c3e44c615e 100644 --- a/src/string_id_null_ids.cpp +++ b/src/string_id_null_ids.cpp @@ -55,3 +55,4 @@ MAKE_NULL_ID2( requirement_data, "null" ) MAKE_NULL_ID2( body_part_struct, "NUM_BP" ) MAKE_NULL_ID2( bionic_data, "" ) MAKE_NULL_ID2( construction, "constr_null", -1 ) +MAKE_NULL_ID2( vehicle_prototype, "null" )