/** *Caches a vehicle definition from a JsonObject to be loaded after itypes is initialized. */ void vehicle_prototype::load(JsonObject &jo) { vehicle_prototype &vproto = vtypes[ vproto_id( jo.get_string( "id" ) ) ]; // If there are already parts defined, this vehicle prototype overrides an existing one. // If the json contains a name, it means a completely new prototype (replacing the // original one), therefor the old data has to be cleared. // If the json does not contain a name (the prototype would have no name), it means appending // to the existing prototype (the parts are not cleared). if( !vproto.parts.empty() && jo.has_string( "name" ) ) { vproto = std::move( vehicle_prototype() ); } if( vproto.parts.empty() ) { vproto.name = jo.get_string( "name" ); } vgroups[vgroup_id(jo.get_string("id"))].add_vehicle(vproto_id(jo.get_string("id")), 100); JsonArray parts = jo.get_array("parts"); while (parts.has_more()) { JsonObject part = parts.next_object(); const point pxy( part.get_int("x"), part.get_int("y") ); const vpart_str_id pid( part.get_string( "part" ) ); vproto.parts.emplace_back( pxy, pid ); } JsonArray items = jo.get_array("items"); while(items.has_more()) { JsonObject spawn_info = items.next_object(); vehicle_item_spawn next_spawn; next_spawn.pos.x = spawn_info.get_int("x"); next_spawn.pos.y = spawn_info.get_int("y"); next_spawn.chance = spawn_info.get_int("chance"); if(next_spawn.chance <= 0 || next_spawn.chance > 100) { debugmsg("Invalid spawn chance in %s (%d, %d): %d%%", vproto.name.c_str(), next_spawn.pos.x, next_spawn.pos.y, next_spawn.chance); } if(spawn_info.has_array("items")) { //Array of items that all spawn together (ie jack+tire) JsonArray item_group = spawn_info.get_array("items"); while(item_group.has_more()) { next_spawn.item_ids.push_back(item_group.next_string()); } } else if(spawn_info.has_string("items")) { //Treat single item as array next_spawn.item_ids.push_back(spawn_info.get_string("items")); } if(spawn_info.has_array("item_groups")) { //Pick from a group of items, just like map::place_items JsonArray item_group_names = spawn_info.get_array("item_groups"); while(item_group_names.has_more()) { next_spawn.item_groups.push_back(item_group_names.next_string()); } } else if(spawn_info.has_string("item_groups")) { next_spawn.item_groups.push_back(spawn_info.get_string("item_groups")); } vproto.item_spawns.push_back( std::move( next_spawn ) ); } }
void check_vehicle_damage( std::string explosive_id, std::string vehicle_id, int range ) { // Clear map clear_map(); tripoint origin( 30, 30, 0 ); vehicle *target_vehicle = g->m.add_vehicle( vproto_id( vehicle_id ), origin, 0, -1, 0 ); std::vector<int> before_hp = get_part_hp( target_vehicle ); while( g->m.veh_at( origin ) ) { origin.x++; } origin.x += range; // Set off an explosion item grenade( explosive_id ); grenade.charges = 0; grenade.type->invoke( g->u, grenade, origin ); std::vector<int> after_hp = get_part_hp( target_vehicle ); // We don't expect any destroyed parts. CHECK( before_hp.size() == after_hp.size() ); for( unsigned int i = 0; i < before_hp.size(); ++i ) { INFO( target_vehicle->parts[ i ].name() ); if( target_vehicle->parts[ i ].name() == "windshield" || target_vehicle->parts[ i ].name() == "headlight" ) { CHECK( before_hp[ i ] >= after_hp[ i ] ); } else { CHECK( before_hp[ i ] == after_hp[ i ] ); } } }
statistics find_inner( std::string type, std::string terrain, int delay, bool smooth ) { statistics efficiency; for( int i = 0; i < 10; i++) { efficiency.add( test_efficiency( vproto_id( type ), ter_id( terrain ), delay, -1, smooth ) ); } return efficiency; }
void VehicleGroup::load(JsonObject &jo) { VehicleGroup &group = vgroups[vgroup_id(jo.get_string("id"))]; JsonArray vehicles = jo.get_array("vehicles"); while (vehicles.has_more()) { JsonArray pair = vehicles.next_array(); group.add_vehicle(vproto_id(pair.get_string(0)), pair.get_int(1)); } }
efficiency_stat find_inner( const std::string &type, int &expected_mass, const std::string &terrain, const int delay, const bool smooth, const bool test_mass = false ) { efficiency_stat efficiency; for( int i = 0; i < 10; i++ ) { efficiency.add( test_efficiency( vproto_id( type ), expected_mass, ter_id( terrain ), delay, -1, smooth, test_mass ) ); } return efficiency; }
// Behold: power of laziness void print_drag_test_strings( const std::string &type ) { std::ostringstream ss; vehicle *veh_ptr = setup_drag_test( vproto_id( type ) ); if( veh_ptr == nullptr ) { return; } ss << " test_vehicle_drag( \"" << type << "\", "; ss << veh_ptr->coeff_air_drag() << ", "; ss << veh_ptr->coeff_rolling_drag() << ", "; ss << veh_ptr->safe_velocity() << ", "; ss << veh_ptr->max_velocity(); ss << " );" << std::endl; printf( "%s", ss.str().c_str() ); fflush( stdout ); }
void construct::done_vehicle( const tripoint &p ) { std::string name = string_input_popup( _( "Enter new vehicle name:" ), 20 ); if( name.empty() ) { name = _( "Car" ); } vehicle *veh = g->m.add_vehicle( vproto_id( "none" ), p, 270, 0, 0 ); if( !veh ) { debugmsg( "error constructing vehicle" ); return; } veh->name = name; veh->install_part( 0, 0, vpart_from_item( g->u.lastconsumed ) ); // Update the vehicle cache immediately, // or the vehicle will be invisible for the first couple of turns. g->m.add_vehicle_to_cache( veh ); }
static void test_repair( const std::vector<item> &tools, bool expect_craftable ) { clear_player(); clear_map(); const tripoint test_origin( 60, 60, 0 ); g->u.setpos( test_origin ); const item backpack( "backpack" ); g->u.wear( g->u.i_add( backpack ), false ); for( const item gear : tools ) { g->u.i_add( gear ); } const tripoint vehicle_origin = test_origin + tripoint( 1, 1, 0 ); vehicle *veh_ptr = g->m.add_vehicle( vproto_id( "bicycle" ), vehicle_origin, -90, 0, 0 ); REQUIRE( veh_ptr != nullptr ); // Find the frame at the origin. vehicle_part *origin_frame = nullptr; for( vehicle_part *part : veh_ptr->get_parts_at( vehicle_origin, "", part_status_flag::any ) ) { if( part->info().location == "structure" ) { origin_frame = part; break; } } REQUIRE( origin_frame != nullptr ); REQUIRE( origin_frame->hp() == origin_frame->info().durability ); veh_ptr->mod_hp( *origin_frame, -100 ); REQUIRE( origin_frame->hp() < origin_frame->info().durability ); const vpart_info &vp = origin_frame->info(); // Assertions about frame part? requirement_data reqs = vp.repair_requirements(); // Bust cache on crafting_inventory() g->u.mod_moves( 1 ); inventory crafting_inv = g->u.crafting_inventory(); bool can_repair = vp.repair_requirements().can_make_with_inventory( g->u.crafting_inventory(), is_crafting_component ); CHECK( can_repair == expect_craftable ); }
/** *Caches a vehicle definition from a JsonObject to be loaded after itypes is initialized. */ void vehicle_prototype::load( JsonObject &jo ) { vehicle_prototype &vproto = vtypes[ vproto_id( jo.get_string( "id" ) ) ]; // If there are already parts defined, this vehicle prototype overrides an existing one. // If the json contains a name, it means a completely new prototype (replacing the // original one), therefore the old data has to be cleared. // If the json does not contain a name (the prototype would have no name), it means appending // to the existing prototype (the parts are not cleared). if( !vproto.parts.empty() && jo.has_string( "name" ) ) { vproto = vehicle_prototype(); } if( vproto.parts.empty() ) { vproto.name = jo.get_string( "name" ); } vgroups[vgroup_id( jo.get_string( "id" ) )].add_vehicle( vproto_id( jo.get_string( "id" ) ), 100 ); const auto add_part_obj = [&]( JsonObject part, point pos ) { part_def pt; pt.pos = pos; pt.part = vpart_id( part.get_string( "part" ) ); assign( part, "ammo", pt.with_ammo, true, 0, 100 ); assign( part, "ammo_types", pt.ammo_types, true ); assign( part, "ammo_qty", pt.ammo_qty, true, 0 ); assign( part, "fuel", pt.fuel, true ); vproto.parts.push_back( pt ); }; const auto add_part_string = [&]( std::string part, point pos ) { part_def pt; pt.pos = pos; pt.part = vpart_id( part ); vproto.parts.push_back( pt ); }; JsonArray parts = jo.get_array( "parts" ); while( parts.has_more() ) { JsonObject part = parts.next_object(); point pos = point( part.get_int( "x" ), part.get_int( "y" ) ); if( part.has_string( "part" ) ) { add_part_obj( part, pos ); } else if( part.has_array( "parts" ) ) { JsonArray subparts = part.get_array( "parts" ); while( subparts.has_more() ) { if( subparts.test_string() ) { std::string part_name = subparts.next_string(); add_part_string( part_name, pos ); } else { JsonObject subpart = subparts.next_object(); add_part_obj( subpart, pos ); } } } } JsonArray items = jo.get_array( "items" ); while( items.has_more() ) { JsonObject spawn_info = items.next_object(); vehicle_item_spawn next_spawn; next_spawn.pos.x = spawn_info.get_int( "x" ); next_spawn.pos.y = spawn_info.get_int( "y" ); next_spawn.chance = spawn_info.get_int( "chance" ); if( next_spawn.chance <= 0 || next_spawn.chance > 100 ) { debugmsg( "Invalid spawn chance in %s (%d, %d): %d%%", vproto.name.c_str(), next_spawn.pos.x, next_spawn.pos.y, next_spawn.chance ); } // constrain both with_magazine and with_ammo to [0-100] next_spawn.with_magazine = std::max( std::min( spawn_info.get_int( "magazine", next_spawn.with_magazine ), 100 ), 0 ); next_spawn.with_ammo = std::max( std::min( spawn_info.get_int( "ammo", next_spawn.with_ammo ), 100 ), 0 ); if( spawn_info.has_array( "items" ) ) { //Array of items that all spawn together (i.e. jack+tire) JsonArray item_group = spawn_info.get_array( "items" ); while( item_group.has_more() ) { next_spawn.item_ids.push_back( item_group.next_string() ); } } else if( spawn_info.has_string( "items" ) ) { //Treat single item as array next_spawn.item_ids.push_back( spawn_info.get_string( "items" ) ); } if( spawn_info.has_array( "item_groups" ) ) { //Pick from a group of items, just like map::place_items JsonArray item_group_names = spawn_info.get_array( "item_groups" ); while( item_group_names.has_more() ) { next_spawn.item_groups.push_back( item_group_names.next_string() ); } } else if( spawn_info.has_string( "item_groups" ) ) { next_spawn.item_groups.push_back( spawn_info.get_string( "item_groups" ) ); } vproto.item_spawns.push_back( std::move( next_spawn ) ); } }
vehicle* VehicleFactory::add_vehicle(map& m, const std::string &vehicle_id, const point &p, const int facing, const int fuel, const int status, const bool mergewrecks) { return m.add_vehicle(groups.count(vehicle_id) > 0 ? vproto_id(groups[vehicle_id].pick()) : vproto_id(vehicle_id), p.x, p.y, facing, fuel, status, mergewrecks); }
#include "catch/catch.hpp" #include "game.h" #include "map.h" #include "vehicle.h" #include "veh_type.h" #include "player.h" TEST_CASE( "destroy_grabbed_vehicle_section" ) { GIVEN( "A vehicle grabbed by the player" ) { tripoint test_origin( 60, 60, 0 ); g->u.setpos( test_origin ); tripoint vehicle_origin = test_origin + tripoint( 1, 1, 0 ); vehicle *veh_ptr = g->m.add_vehicle( vproto_id( "bicycle" ), vehicle_origin, -90 ); REQUIRE( veh_ptr != nullptr ); tripoint grab_point = test_origin + tripoint( 1, 0, 0 ); g->u.grab_type = OBJECT_VEHICLE; g->u.grab_point = grab_point; WHEN( "The vehicle section grabbed by the player is destroyed" ) { g->m.destroy( grab_point ); THEN( "The player's grab is released" ) { CHECK( g->u.grab_type == OBJECT_NONE ); CHECK( g->u.grab_point == tripoint_zero ); } } } }