diff --git a/data/json/vehicleparts/engineering.json b/data/json/vehicleparts/engineering.json index ec2bddf76d893..c74821a2fa652 100644 --- a/data/json/vehicleparts/engineering.json +++ b/data/json/vehicleparts/engineering.json @@ -115,7 +115,8 @@ { "item": "steel_chunk", "count": [ 4, 6 ] }, { "item": "scrap", "count": [ 4, 6 ] } ], - "flags": [ "FOLDABLE", "PROTRUSION", "EXTRA_DRAG", "ROCKWHEEL" ] + "transform_terrain": { "pre_flags": [ "DIGGABLE" ], "post_terrain": "t_pit_shallow" }, + "flags": [ "FOLDABLE", "PROTRUSION", "EXTRA_DRAG", "ROCKWHEEL", "TRANSFORM_TERRAIN" ] }, { "type": "vehicle_part", diff --git a/data/json/vehicleparts/vehicle_parts.json b/data/json/vehicleparts/vehicle_parts.json index 93525131b0127..01d55bd680531 100644 --- a/data/json/vehicleparts/vehicle_parts.json +++ b/data/json/vehicleparts/vehicle_parts.json @@ -2727,7 +2727,8 @@ "difficulty": 4, "location": "under", "power": -300, - "flags": [ "PLOW", "EXTRA_DRAG" ], + "transform_terrain": { "pre_flags": [ "PLOWABLE" ], "post_terrain": "t_dirtmound" }, + "flags": [ "TRANSFORM_TERRAIN", "PLOW", "EXTRA_DRAG" ], "breaks_into": [ { "item": "plastic_chunk", "count": [ 1, 2 ] } ] }, { diff --git a/doc/JSON_FLAGS.md b/doc/JSON_FLAGS.md index dd7840a93dd50..b9e353338d6f8 100644 --- a/doc/JSON_FLAGS.md +++ b/doc/JSON_FLAGS.md @@ -1307,6 +1307,7 @@ Those flags are added by the game code to specific items (that specific welder, - ```STABLE``` Similar to `WHEEL`, but if the vehicle is only a 1x1 section, this single wheel counts as enough wheels. - ```STEERABLE``` This wheel is steerable. - ```STEREO``` +- ```TRANSFORM_TERRAIN``` Transform terrain (using rules defined in ```transform_terrain```). - ```TOOL_NONE``` Can be removed/installed without any tools - ```TOOL_SCREWDRIVER``` Attached with screws, can be removed/installed with a screwdriver - ```TOOL_WRENCH``` Attached with bolts, can be removed/installed with a wrench diff --git a/src/veh_type.cpp b/src/veh_type.cpp index 1e02f06524ad3..4b540e9739169 100644 --- a/src/veh_type.cpp +++ b/src/veh_type.cpp @@ -329,6 +329,28 @@ void vpart_info::load( JsonObject &jo, const std::string &src ) assign( jo, "flags", def.flags ); assign( jo, "description", def.description ); + if( jo.has_member( "transform_terrain" ) ) { + JsonObject jttd = jo.get_object( "transform_terrain" ); + JsonArray jpf = jttd.get_array( "pre_flags" ); + while( jpf.has_more() ) { + std::string pre_flag = jpf.next_string(); + def.transform_terrain.pre_flags.emplace( pre_flag ); + } + def.transform_terrain.post_terrain = jttd.get_string( "post_terrain", "t_null" ); + def.transform_terrain.post_furniture = jttd.get_string( "post_furniture", "f_null" ); + def.transform_terrain.post_field = jttd.get_string( "post_field", "fd_null" ); + def.transform_terrain.post_field_intensity = jttd.get_int( "post_field_intensity", 0 ); + if( jttd.has_int( "post_field_age" ) ) { + def.transform_terrain.post_field_age = time_duration::from_turns( + jttd.get_int( "post_field_age" ) ); + } else if( jttd.has_string( "post_field_age" ) ) { + def.transform_terrain.post_field_age = time_duration::read_from_json_string( + *jttd.get_raw( "post_field_age" ) ); + } else { + def.transform_terrain.post_field_age = 0_turns; + } + } + if( jo.has_member( "requirements" ) ) { auto reqs = jo.get_object( "requirements" ); diff --git a/src/veh_type.h b/src/veh_type.h index a709cd2fd8b45..d19f17f5c369a 100644 --- a/src/veh_type.h +++ b/src/veh_type.h @@ -121,6 +121,15 @@ struct vpslot_workbench { units::volume allowed_volume; }; +struct transform_terrain_data { + std::set pre_flags; + std::string post_terrain; + std::string post_furniture; + std::string post_field; + int post_field_intensity; + time_duration post_field_age; +}; + class vpart_info { private: @@ -262,6 +271,9 @@ class vpart_info /** Flat decrease of damage of a given type. */ std::array damage_reduction; + /* Contains data for terrain transformer parts */ + transform_terrain_data transform_terrain; + /** * @name Engine specific functions * diff --git a/src/vehicle.cpp b/src/vehicle.cpp index ef6919df80cf1..f5e5ef083676d 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -4284,21 +4284,18 @@ void vehicle::idle( bool on_map ) void vehicle::on_move() { + if( has_part( "TRANSFORM_TERRAIN", true ) ) { + transform_terrain(); + } if( has_part( "SCOOP", true ) ) { operate_scoop(); } if( has_part( "PLANTER", true ) ) { operate_planter(); } - if( has_part( "PLOW", true ) ) { - operate_plow(); - } if( has_part( "REAPER", true ) ) { operate_reaper(); } - if( has_part( "ROCKWHEEL", true ) ) { - operate_rockwheel(); - } occupied_cache_time = calendar::before_time_starts; } diff --git a/src/vehicle.h b/src/vehicle.h index 2efafa646aa2f..bd6fc4e0c3561 100644 --- a/src/vehicle.h +++ b/src/vehicle.h @@ -1399,8 +1399,7 @@ class vehicle //scoop operation,pickups, battery drain, etc. void operate_scoop(); void operate_reaper(); - void operate_plow(); - void operate_rockwheel(); + void transform_terrain(); void add_toggle_to_opts( std::vector &options, std::vector> &actions, const std::string &name, char key, const std::string &flag ); diff --git a/src/vehicle_use.cpp b/src/vehicle_use.cpp index 1abf52b8d07cc..5fee5cd219640 100644 --- a/src/vehicle_use.cpp +++ b/src/vehicle_use.cpp @@ -46,6 +46,7 @@ #include "requirements.h" #include "rng.h" #include "string_id.h" +#include "field.h" static const itype_id fuel_type_none( "null" ); static const itype_id fuel_type_battery( "battery" ); @@ -1077,33 +1078,36 @@ void vehicle::play_chimes() } } -void vehicle::operate_plow() +void vehicle::transform_terrain() { - for( const vpart_reference &vp : get_enabled_parts( "PLOW" ) ) { - const tripoint start_plow = vp.pos(); - if( g->m.has_flag( "PLOWABLE", start_plow ) ) { - g->m.ter_set( start_plow, t_dirtmound ); - } else { - const int speed = abs( velocity ); - int v_damage = rng( 3, speed ); - damage( vp.part_index(), v_damage, DT_BASH, false ); - sounds::sound( start_plow, v_damage, sounds::sound_t::combat, _( "Clanggggg!" ), false, - "smash_success", "hit_vehicle" ); + for( const vpart_reference &vp : get_enabled_parts( "TRANSFORM_TERRAIN" ) ) { + const tripoint start_pos = vp.pos(); + const transform_terrain_data &ttd = vp.info().transform_terrain; + bool prereq_fulfilled = false; + for( const std::string &flag : ttd.pre_flags ) { + if( g->m.has_flag( flag, start_pos ) ) { + prereq_fulfilled = true; + break; + } } - } -} - -void vehicle::operate_rockwheel() -{ - for( const vpart_reference &vp : get_enabled_parts( "ROCKWHEEL" ) ) { - const tripoint start_dig = vp.pos(); - if( g->m.has_flag( "DIGGABLE", start_dig ) ) { - g->m.ter_set( start_dig, t_pit_shallow ); + if( prereq_fulfilled ) { + const ter_id new_ter = ter_id( ttd.post_terrain ); + if( new_ter != t_null ) { + g->m.ter_set( start_pos, new_ter ); + } + const furn_id new_furn = furn_id( ttd.post_furniture ); + if( new_furn != f_null ) { + g->m.furn_set( start_pos, new_furn ); + } + const field_id new_field = field_from_ident( ttd.post_field ); + if( new_field != fd_null ) { + g->m.add_field( start_pos, new_field, ttd.post_field_intensity, ttd.post_field_age ); + } } else { const int speed = abs( velocity ); int v_damage = rng( 3, speed ); damage( vp.part_index(), v_damage, DT_BASH, false ); - sounds::sound( start_dig, v_damage, sounds::sound_t::combat, _( "Clanggggg!" ), false, + sounds::sound( start_pos, v_damage, sounds::sound_t::combat, _( "Clanggggg!" ), false, "smash_success", "hit_vehicle" ); } }