Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix generation of adjacent elevated bridges #1650

Merged
merged 3 commits into from
Jul 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/basecamp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ void basecamp::define_camp( const tripoint_abs_omt &p, const std::string &camp_t
e.cur_level = -1;
e.pos = omt_pos;
expansions[base_camps::base_dir] = e;
const std::string direction = oter_get_rotation_string( omt_ref );
const std::string &direction = oter_get_rotation_string( omt_ref );
const oter_id bcid( direction.empty() ? "faction_base_camp_0" : "faction_base_camp_new_0" +
direction );
overmap_buffer.ter_set( omt_pos, bcid );
Expand Down
6 changes: 3 additions & 3 deletions src/mapgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6555,19 +6555,19 @@ bool update_mapgen_function_json::update_map( mapgendata &md, const point &offse
{
public:
rotation_guard( const mapgendata &md )
: md( md ), rotation( oter_get_rotation( md.terrain_type() ) ) {
: md( md ), rotation( oter_get_rotations( md.terrain_type() ) ) {
// If the existing map is rotated, we need to rotate it back to the north
// orientation before applying our updates.
if( rotation != 0 ) {
md.m.rotate( rotation, true );
md.m.rotate( 4 - rotation, true );
}
}

~rotation_guard() {
// If we rotated the map before applying updates, we now need to rotate
// it back to where we found it.
if( rotation != 0 ) {
md.m.rotate( 4 - rotation, true );
md.m.rotate( rotation, true );
}
}
private:
Expand Down
25 changes: 25 additions & 0 deletions src/omdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,31 @@ enum class type : int {
const std::array<type, 4> all = {{ type::north, type::east, type::south, type::west }};
const size_t size = all.size();

const std::array<std::string, 4> all_suffixes = {{ "_north", "_east", "_south", "_west" }};
const std::string invalid_dir_suffix;
const std::array<int, 4> all_cw_rotations = {{ 0, 1, 2, 3 }};
const int invalid_dir_rotations = 0;

/** Returns directional suffix associated with the value, e.g. _north or _west. */
constexpr const std::string &get_suffix( type dir )
{
if( dir == type::invalid ) {
return invalid_dir_suffix;
} else {
return all_suffixes[static_cast<size_t>( dir )];
}
}

/** Returns number of clockwise rotations needed to reach this direction from 'north'. */
constexpr int get_num_cw_rotations( type dir )
{
if( dir == type::invalid ) {
return invalid_dir_rotations;
} else {
return all_cw_rotations[static_cast<size_t>( dir )];
}
}

/** Number of bits needed to store directions. */
const size_t bits = static_cast<size_t>( -1 ) >> ( CHAR_BIT *sizeof( size_t ) - size );

Expand Down
132 changes: 64 additions & 68 deletions src/overmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1915,6 +1915,52 @@ bool overmap::generate_sub( const int z )
return requires_sub;
}

static void elevate_bridges(
overmap &om,
const std::vector<point_om_omt> &bridge_points,
const std::string &bridge_overpass_id,
const std::string &bridge_under_id,
const std::string &bridgehead_ground_id,
const std::string &bridgehead_ramp_id )
{
// Check bridgeheads
std::vector<std::pair<point_om_omt, om_direction::type>> bridgehead_points;
for( const point_om_omt &bp : bridge_points ) {
tripoint_om_omt bp_om( bp, 0 );

const oter_id &ot_here = om.ter( bp_om );
const std::string &type_here = ot_here->get_type_id().str();
const om_direction::type dir = oter_get_rotation_dir( ot_here );
if( dir == om_direction::type::invalid ) {
// Shouldn't happen
debugmsg( "Potential bridgehead %s at %s has invalid rotation.", ot_here.id(), bp_om.to_string() );
continue;
}
point vec = om_direction::displace( dir );
const bool is_bridge_fwd = is_ot_match( type_here, om.ter( bp_om + vec ), ot_match_type::type );
const bool is_bridge_bck = is_ot_match( type_here, om.ter( bp_om - vec ), ot_match_type::type );

if( is_bridge_fwd ^ is_bridge_bck ) {
om_direction::type ramp_facing = is_bridge_fwd ? om_direction::opposite( dir ) : dir;
bridgehead_points.emplace_back( bp, ramp_facing );
}
}
// Put bridge points
for( const point_om_omt &bp : bridge_points ) {
tripoint_om_omt p( bp, 0 );
const std::string &rot_sfx = oter_get_rotation_string( om.ter( p ) );
om.ter_set( p + tripoint_above, oter_id( bridge_overpass_id + rot_sfx ) );
om.ter_set( p, oter_id( bridge_under_id + rot_sfx ) );
}
// Put bridgeheads
for( const std::pair<point_om_omt, om_direction::type> &bhp : bridgehead_points ) {
tripoint_om_omt p( bhp.first, 0 );
const std::string &dir_suffix = om_direction::all_suffixes[static_cast<int>( bhp.second )];
om.ter_set( p, oter_id( bridgehead_ground_id + dir_suffix ) );
om.ter_set( p + tripoint_above, oter_id( bridgehead_ramp_id + dir_suffix ) );
}
}

bool overmap::generate_over( const int z )
{
bool requires_over = false;
Expand Down Expand Up @@ -1944,46 +1990,17 @@ bool overmap::generate_over( const int z )
}

if( is_ot_match( "bridge", oter_ground, ot_match_type::type ) ) {
ter_set( p, oter_id( "bridge_road" + oter_get_rotation_string( oter_ground ) ) );
ter_set( p_below, oter_id( "bridge_under" + oter_get_rotation_string( oter_ground ) ) );
bridge_points.emplace_back( i, j );
}
}
}
}

// Check and put bridgeheads
std::vector<std::pair<point_om_omt, std::string>> bridgehead_points;
for( const point_om_omt &bp : bridge_points ) {
tripoint_om_omt bp_om( bp, 0 );
const oter_id oter_ground_north = ter( bp_om + tripoint_north );
const oter_id oter_ground_south = ter( bp_om + tripoint_south );
const oter_id oter_ground_east = ter( bp_om + tripoint_east );
const oter_id oter_ground_west = ter( bp_om + tripoint_west );
const bool is_bridge_north = is_ot_match( "bridge_under", oter_ground_north, ot_match_type::type );
const bool is_bridge_south = is_ot_match( "bridge_under", oter_ground_south, ot_match_type::type );
const bool is_bridge_east = is_ot_match( "bridge_under", oter_ground_east, ot_match_type::type );
const bool is_bridge_west = is_ot_match( "bridge_under", oter_ground_west, ot_match_type::type );

if( is_bridge_north ^ is_bridge_south || is_bridge_east ^ is_bridge_west ) {
std::string ramp_facing;
if( is_bridge_north ) {
ramp_facing = "_south";
} else if( is_bridge_south ) {
ramp_facing = "_north";
} else if( is_bridge_east ) {
ramp_facing = "_west";
} else {
ramp_facing = "_east";
}
bridgehead_points.emplace_back( bp, ramp_facing );
}
}
for( const std::pair<point_om_omt, std::string> &bhp : bridgehead_points ) {
tripoint_om_omt p( bhp.first, 0 );
ter_set( p, oter_id( "bridgehead_ground" + bhp.second ) );
ter_set( p + tripoint_above, oter_id( "bridgehead_ramp" + bhp.second ) );
}
elevate_bridges( *this, bridge_points,
"bridge_road",
"bridge_under",
"bridgehead_ground",
"bridgehead_ramp" );

return requires_over;
}
Expand Down Expand Up @@ -4935,44 +4952,23 @@ std::string oter_no_dir( const oter_id &oter )
return base_oter_id;
}

int oter_get_rotation( const oter_id &oter )
om_direction::type oter_get_rotation_dir( const oter_id &oter )
{
std::string base_oter_id = oter.id().c_str();
size_t oter_len = base_oter_id.size();
if( oter_len > 7 ) {
if( base_oter_id.substr( oter_len - 6, 6 ) == "_south" ) {
return 2;
} else if( base_oter_id.substr( oter_len - 6, 6 ) == "_north" ) {
return 0;
for( const om_direction::type &rot : om_direction::all ) {
const std::string &rot_s = om_direction::get_suffix( rot );
if( string_ends_with( oter.id().str(), rot_s ) ) {
return rot;
}
}
if( oter_len > 6 ) {
if( base_oter_id.substr( oter_len - 5, 5 ) == "_west" ) {
return 1;
} else if( base_oter_id.substr( oter_len - 5, 5 ) == "_east" ) {
return 3;
}
}
return 0;
return om_direction::type::invalid;
}

std::string oter_get_rotation_string( const oter_id &oter )
int oter_get_rotations( const oter_id &oter )
{
std::string base_oter_id = oter.id().c_str();
size_t oter_len = base_oter_id.size();
if( oter_len > 7 ) {
if( base_oter_id.substr( oter_len - 6, 6 ) == "_south" ) {
return "_south";
} else if( base_oter_id.substr( oter_len - 6, 6 ) == "_north" ) {
return "_north";
}
}
if( oter_len > 6 ) {
if( base_oter_id.substr( oter_len - 5, 5 ) == "_west" ) {
return "_west";
} else if( base_oter_id.substr( oter_len - 5, 5 ) == "_east" ) {
return "_east";
}
}
return "";
return om_direction::get_num_cw_rotations( oter_get_rotation_dir( oter ) );
}

const std::string &oter_get_rotation_string( const oter_id &oter )
{
return om_direction::get_suffix( oter_get_rotation_dir( oter ) );
}
18 changes: 13 additions & 5 deletions src/overmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -572,13 +572,21 @@ om_special_sectors get_sectors( int sector_width );
std::string oter_no_dir( const oter_id &oter );

/**
* Return 0, 1, 2, 3 respectively if the suffix is _north, _west, _south, _east
* Return 0 if there's no suffix
* Returns oter rotation direction value.
*/
om_direction::type oter_get_rotation_dir( const oter_id &oter );

/**
* Returns number of clockwise rotations 0, 1, 2, 3 respectively
* if the suffix is _north, _east, _south, _west.
* Returns 0 if there's no suffix.
*/
int oter_get_rotation( const oter_id &oter );
int oter_get_rotations( const oter_id &oter );

/**
* Return the directional suffix or "" if there isn't one.
* Returns the directional suffix or "" if there isn't one.
*
* Returned reference is kept alive during the whole program execution.
*/
std::string oter_get_rotation_string( const oter_id &oter );
const std::string &oter_get_rotation_string( const oter_id &oter );
#endif // CATA_SRC_OVERMAP_H
8 changes: 8 additions & 0 deletions src/string_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,17 @@ bool match_include_exclude( const std::string &text, std::string filter );

/**
* \brief Returns true if s1 starts with s2
*
* TODO: Switch to starts_with method of std::string when we move to C++20
*/
bool string_starts_with( const std::string &s1, const std::string &s2 );

/**
* Returns true if s1 starts with s2.
* This version accepts constant string literals and is ≈1.5 times faster than std::string version.
* Note: N is (size+1) for null-terminated strings.
*
* TODO: Maybe switch to std::string::starts_with + std::string_view when we move to C++20
*/
template <std::size_t N>
inline bool string_starts_with( const std::string &s1, const char( &s2 )[N] )
Expand All @@ -57,13 +61,17 @@ inline bool string_starts_with( const std::string &s1, const char( &s2 )[N] )

/**
* \brief Returns true if s1 ends with s2
*
* TODO: Switch to ends_with method of std::string when we move to C++20
*/
bool string_ends_with( const std::string &s1, const std::string &s2 );

/**
* Returns true iff s1 ends with s2.
* This version accepts constant string literals and is ≈1.5 times faster than std::string version.
* Note: N is (size+1) for null-terminated strings.
*
* TODO: Maybe switch to std::string::ends_with + std::string_view when we move to C++20
*/
template <std::size_t N>
inline bool string_ends_with( const std::string &s1, const char( &s2 )[N] )
Expand Down