From 458a638c91e05e455421d51f45a6f4a732acc005 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 b3939d93e200f..7802bf003eab9 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 7683861f069c0..f361c0b7d7a18 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 55c3e8e1eb7c3..a8fef7f63308b 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 5eb9229578b5c..3c8141f61abca 100644 --- a/src/newcharacter.cpp +++ b/src/newcharacter.cpp @@ -51,6 +51,7 @@ #include "optional.h" #include "pimpl.h" #include "type_id.h" +#include "veh_type.h" static const std::string flag_CHALLENGE( "CHALLENGE" ); static const std::string flag_CITY_START( "CITY_START" ); @@ -528,6 +529,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 ) { @@ -1488,7 +1490,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() ) { @@ -1496,6 +1497,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 17c7e237f50de..d660528685e99 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 3626db4b61fb5..3a5284e603a1f 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() ); @@ -482,6 +488,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" )