diff --git a/data/json/overmap/overmap_terrain/overmap_terrain.json b/data/json/overmap/overmap_terrain/overmap_terrain.json index 7e7bc3f08363e..88cbc53d9ed05 100644 --- a/data/json/overmap/overmap_terrain/overmap_terrain.json +++ b/data/json/overmap/overmap_terrain/overmap_terrain.json @@ -39,7 +39,7 @@ "extras": "build", "mondensity": 2, "see_cost": "high", - "flags": [ "RISK_HIGH", "GENERIC_LOOT" ] + "flags": [ "RISK_HIGH", "GENERIC_LOOT", "PP_GENERATE_RIOT_DAMAGE" ] }, { "type": "overmap_terrain", diff --git a/doc/JSON/JSON_FLAGS.md b/doc/JSON/JSON_FLAGS.md index 363637bdb3c08..6ad3fcf15c969 100644 --- a/doc/JSON/JSON_FLAGS.md +++ b/doc/JSON/JSON_FLAGS.md @@ -1317,6 +1317,7 @@ See [Character](#character) - ```REQUIRES_PREDECESSOR``` Mapgen for this will not start from scratch; it will update the mapgen from the terrain it replaced. This allows the corresponding json mapgen to use the `expects_predecessor` feature. - ```LAKE``` Consider this location to be a valid lake terrain for mapgen purposes. - ```LAKE_SHORE``` Consider this location to be a valid lake shore terrain for mapgen purposes. +- ```PP_GENERATE_RIOT_DAMAGE``` Applies randomized riot damage to the local map as a last stage in generating it. Furniture and terrain will be bashed, items moved around, blood spatters are placed, and rarely spawns fires. - ```SOURCE_FUEL``` For NPC AI, this location may contain fuel for looting. - ```SOURCE_FOOD``` For NPC AI, this location may contain food for looting. - ```SOURCE_FARMING``` For NPC AI, this location may contain useful farming supplies for looting. diff --git a/src/mapgen.cpp b/src/mapgen.cpp index c2971d9708f0c..cead621794b42 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -83,6 +83,9 @@ #include "weighted_list.h" #include "creature_tracker.h" +static const field_type_str_id field_fd_blood( "fd_blood" ); +static const field_type_str_id field_fd_fire( "fd_fire" ); + static const furn_str_id furn_f_ash( "f_ash" ); static const furn_str_id furn_f_bed( "f_bed" ); static const furn_str_id furn_f_console( "f_console" ); @@ -228,6 +231,69 @@ static constexpr int MON_RADIUS = 3; static void science_room( map *m, const point_bub_ms &p1, const point_bub_ms &p2, int z, int rotate ); +static void GENERATOR_riot_damage( map &md, const tripoint_abs_omt &p ) +{ + if( p.z() < 0 ) { + // for the moment make sure we don't apply this to labs or other places + debugmsg( "Riot damage mapgen generator called on underground structure. This is likely a bug." ); + return; + } + std::list all_points_in_map; + // Placeholder / FIXME + // This assumes that we're only dealing with regular 24x24 OMTs. That is likely not the case. + for( int i = 0; i < SEEX * 2; i++ ) { + for( int n = 0; n < SEEY * 2; n++ ) { + tripoint_bub_ms current_tile( i, n, p.z() ); + all_points_in_map.push_back( current_tile ); + } + } + for( size_t i = 0; i < all_points_in_map.size(); i++ ) { + // Pick a tile at random! + tripoint_bub_ms current_tile = random_entry( all_points_in_map ); + // Do nothing at random!; + if( x_in_y( 10, 100 ) ) { + continue; + } + // Bash stuff at random! + if( x_in_y( 20, 100 ) ) { + md.bash( current_tile, rng( 6, 60 ) ); + } + // Move stuff at random! + auto item_iterator = md.i_at( current_tile.xy() ).begin(); + while( item_iterator != md.i_at( current_tile.xy() ).end() ) { + if( x_in_y( 30, 100 ) ) { + // pick a new spot... + tripoint_bub_ms destination_tile( current_tile.x() + rng( -3, 3 ), + current_tile.y() + rng( -3, 3 ), + current_tile.z() ); + // oops, don't place out of bounds. just skip moving + const bool outbounds_X = destination_tile.x() < 0 || destination_tile.x() >= SEEX * 2; + const bool outbounds_Y = destination_tile.y() < 0 || destination_tile.y() >= SEEY * 2; + const bool would_be_destroyed = md.has_flag( ter_furn_flag::TFLAG_DESTROY_ITEM, destination_tile ); + if( outbounds_X || outbounds_Y || would_be_destroyed ) { + item_iterator++; + continue; + } else { + item copy( *item_iterator ); + // add a copy of our item to the destination... + md.add_item( destination_tile, copy ); + // and erase the one at our source. + item_iterator = md.i_at( current_tile.xy() ).erase( item_iterator ); + } + } else { + item_iterator++; + } + } + // Set some fields at random! + if( x_in_y( 3, 100 ) ) { + md.add_field( current_tile, field_fd_blood ); + } + if( x_in_y( 1, 2000 ) ) { + md.add_field( current_tile, field_fd_fire ); + } + } +} + // Assumptions: // - The map supplied is empty, i.e. no grid entries are in use // - The map supports Z levels. @@ -415,6 +481,11 @@ void map::generate( const tripoint_abs_omt &p, const time_point &when, bool save } } + // Apply post-process generators + if( overmap_buffer.ter( p )->has_flag( oter_flags::pp_generate_riot_damage ) ) { + GENERATOR_riot_damage( *this, p ); + } + set_abs_sub( p_sm_base ); } diff --git a/src/omdata.h b/src/omdata.h index 0e1378512928f..6dec7ba768c38 100644 --- a/src/omdata.h +++ b/src/omdata.h @@ -200,6 +200,7 @@ enum class oter_flags : int { ocean_shore, ravine, ravine_edge, + pp_generate_riot_damage, generic_loot, risk_extreme, risk_high, diff --git a/src/overmap.cpp b/src/overmap.cpp index 20cbf1ea8e959..ddca90117846c 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -729,6 +729,7 @@ std::string enum_to_string( oter_flags data ) case oter_flags::ocean_shore: return "OCEAN_SHORE"; case oter_flags::ravine: return "RAVINE"; case oter_flags::ravine_edge: return "RAVINE_EDGE"; + case oter_flags::pp_generate_riot_damage: return "PP_GENERATE_RIOT_DAMAGE"; case oter_flags::generic_loot: return "GENERIC_LOOT"; case oter_flags::risk_extreme: return "RISK_EXTREME"; case oter_flags::risk_high: return "RISK_HIGH";