Skip to content

Commit

Permalink
Merge pull request #73574 from irwiss/bug-72241
Browse files Browse the repository at this point in the history
Fix fake obstacle parts, duplicated fake parts
  • Loading branch information
Maleclypse authored May 9, 2024
2 parents 85b8f01 + cc59f3c commit 677a59c
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 17 deletions.
13 changes: 13 additions & 0 deletions data/mods/TEST_DATA/vehicle.json
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,19 @@
{ "x": 0, "y": -1, "parts": [ "frame#vertical", "seat", "large_storage_battery" ] }
]
},
{
"id": "obstacle_test",
"type": "vehicle",
"name": "TEST obstacle boards",
"blueprint": [ "===" ],
"parts": [
{ "x": -2, "y": 0, "parts": [ "frame", "board" ] },
{ "x": -1, "y": 0, "parts": [ "frame", "board" ] },
{ "x": 0, "y": 0, "parts": [ "frame", "board", "omnicam" ] },
{ "x": 1, "y": 0, "parts": [ "frame", "board" ] },
{ "x": 2, "y": 0, "parts": [ "frame", "board" ] }
]
},
{
"id": "scooter_test",
"type": "vehicle",
Expand Down
27 changes: 15 additions & 12 deletions src/vehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2603,7 +2603,7 @@ std::vector<int> vehicle::parts_at_relative( const point &dp, const bool use_cac

std::optional<vpart_reference> vpart_position::obstacle_at_part() const
{
std::optional<vpart_reference> part = part_with_feature( VPFLAG_OBSTACLE, true );
std::optional<vpart_reference> part = part_with_feature( VPFLAG_OBSTACLE, true, true );
if( !part ) {
return std::nullopt; // No obstacle here
}
Expand Down Expand Up @@ -2663,19 +2663,19 @@ std::optional<vpart_reference> vpart_position::cargo() const
}

std::optional<vpart_reference> vpart_position::part_with_feature( const std::string &f,
const bool unbroken ) const
bool unbroken, bool include_fake ) const
{
const int i = vehicle().part_with_feature( mount(), f, unbroken );
const int i = vehicle().part_with_feature( mount(), f, unbroken, include_fake );
if( i < 0 ) {
return std::nullopt;
}
return vpart_reference( vehicle(), i );
}

std::optional<vpart_reference> vpart_position::part_with_feature( const vpart_bitflags f,
const bool unbroken ) const
bool unbroken, bool include_fake ) const
{
const int i = vehicle().part_with_feature( part_index(), f, unbroken );
const int i = vehicle().part_with_feature( part_index(), f, unbroken, include_fake );
if( i < 0 ) {
return std::nullopt;
}
Expand Down Expand Up @@ -2756,13 +2756,14 @@ std::string optional_vpart_position::extended_description() const
return desc;
}

int vehicle::part_with_feature( int part, vpart_bitflags flag, bool unbroken ) const
int vehicle::part_with_feature( int part, vpart_bitflags flag, bool unbroken,
bool include_fake ) const
{
const vehicle_part &vp = this->part( part );
if( vp.info().has_flag( flag ) && !( unbroken && vp.is_broken() ) ) {
return part;
}
for( const int p : parts_at_relative( vp.mount, /* use_cache = */ true ) ) {
for( const int p : parts_at_relative( vp.mount, /* use_cache = */ true, include_fake ) ) {
const vehicle_part &vp_here = this->part( p );
if( vp_here.info().has_flag( flag ) && !( unbroken && vp_here.is_broken() ) ) {
return p;
Expand All @@ -2771,9 +2772,10 @@ int vehicle::part_with_feature( int part, vpart_bitflags flag, bool unbroken ) c
return -1;
}

int vehicle::part_with_feature( const point &pt, vpart_bitflags f, bool unbroken ) const
int vehicle::part_with_feature( const point &pt, vpart_bitflags f, bool unbroken,
bool include_fake ) const
{
for( const int p : parts_at_relative( pt, /* use_cache = */ true ) ) {
for( const int p : parts_at_relative( pt, /* use_cache = */ true, include_fake ) ) {
const vehicle_part &vp_here = this->part( p );
if( vp_here.info().has_flag( f ) && !( unbroken && vp_here.is_broken() ) ) {
return p;
Expand All @@ -2782,9 +2784,10 @@ int vehicle::part_with_feature( const point &pt, vpart_bitflags f, bool unbroken
return -1;
}

int vehicle::part_with_feature( const point &pt, const std::string &flag, bool unbroken ) const
int vehicle::part_with_feature( const point &pt, const std::string &flag, bool unbroken,
bool include_fake ) const
{
for( const int p : parts_at_relative( pt, /* use_cache = */ false ) ) {
for( const int p : parts_at_relative( pt, /* use_cache = */ false, include_fake ) ) {
const vehicle_part &vp_here = this->part( p );
if( vp_here.info().has_flag( flag ) && !( unbroken && vp_here.is_broken() ) ) {
return p;
Expand Down Expand Up @@ -6450,7 +6453,7 @@ void vehicle::refresh( const bool remove_fakes )
}
// add fake curtains so vision is correctly blocked
for( const std::pair <const point, std::vector<int>> &rp : relative_parts ) {
add_fake_part( rp.first, "OPAQUE" );
add_fake_part( rp.first, "CURTAIN" );
}
} else {
// Always repopulate fake parts in relative_parts cache since we cleared it.
Expand Down
11 changes: 8 additions & 3 deletions src/vehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -1178,27 +1178,32 @@ class vehicle
* @param pt only returns parts from this mount point
* @param f required flag in part's vpart_info flags collection
* @param unbroken if true also requires the part to be !is_broken
* @param include_fake if true fake parts are included
* @returns part index or -1
*/
int part_with_feature( const point &pt, const std::string &f, bool unbroken ) const;
int part_with_feature( const point &pt, const std::string &f, bool unbroken,
bool include_fake = false ) const;
/**
* Returns part index at mount point \p pt which has given \p f flag
* @note uses relative_parts cache
* @param pt only returns parts from this mount point
* @param f required flag in part's vpart_info flags collection
* @param unbroken if true also requires the part to be !is_broken()
* @param include_fake if true fake parts are included
* @returns part index or -1
*/
int part_with_feature( const point &pt, vpart_bitflags f, bool unbroken ) const;
int part_with_feature( const point &pt, vpart_bitflags f, bool unbroken,
bool include_fake = false ) const;
/**
* Returns \p p or part index at mount point \p pt which has given \p f flag
* @note uses relative_parts cache
* @param p index of part to start searching from
* @param f required flag in part's vpart_info flags collection
* @param unbroken if true also requires the part to be !is_broken()
* @param include_fake if true fake parts are included
* @returns part index or -1
*/
int part_with_feature( int p, vpart_bitflags f, bool unbroken ) const;
int part_with_feature( int p, vpart_bitflags f, bool unbroken, bool include_fake = false ) const;
/**
* Returns index of part at mount point \p pt which has given \p f flag
* and is_available(), or -1 if no such part or it's not is_available()
Expand Down
6 changes: 4 additions & 2 deletions src/vpart_position.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,11 @@ class vpart_position
// @return reference to unbroken CARGO part at this position or std::nullopt
std::optional<vpart_reference> cargo() const;
/// @see vehicle::part_with_feature
std::optional<vpart_reference> part_with_feature( const std::string &f, bool unbroken ) const;
std::optional<vpart_reference> part_with_feature( const std::string &f, bool unbroken,
bool include_fake = false ) const;
/// @see vehicle::part_with_feature
std::optional<vpart_reference> part_with_feature( vpart_bitflags f, bool unbroken ) const;
std::optional<vpart_reference> part_with_feature( vpart_bitflags f, bool unbroken,
bool include_fake = false ) const;
/// @see vehicle::part_with_feature
std::optional<vpart_reference> avail_part_with_feature( const std::string &f ) const;
/// @see vehicle::part_with_feature
Expand Down
25 changes: 25 additions & 0 deletions tests/vehicle_fake_part_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "veh_type.h"

static const vproto_id vehicle_prototype_bicycle( "bicycle" );
static const vproto_id vehicle_prototype_obstacle_test( "obstacle_test" );
static const vproto_id vehicle_prototype_schoolbus( "schoolbus" );
static const vproto_id vehicle_prototype_suv( "suv" );
static const vproto_id vehicle_prototype_test_van( "test_van" );
Expand Down Expand Up @@ -322,6 +323,30 @@ TEST_CASE( "ensure_vehicle_with_no_obstacles_has_no_fake_parts", "[vehicle] [veh
}
}

TEST_CASE( "vehicle_with_fake_obstacle_parts_block_movement", "[vehicle][vehicle_fake]" )
{
clear_avatar();
really_clear_map();
map &here = get_map();
Character &you = get_player_character();
const tripoint test_origin( 30, 30, 0 );
vehicle *veh = here.add_vehicle( vehicle_prototype_obstacle_test,
test_origin, 315_degrees, 100, 0 );
REQUIRE( veh != nullptr );
veh->refresh();
here.set_seen_cache_dirty( 0 );
here.build_map_cache( 0 );
validate_part_count( *veh, 0, 315_degrees, 11, 6, 5 );
std::vector<tripoint_bub_ms> route = here.route(
tripoint_bub_ms( test_origin - point( 2, 0 ) ),
tripoint_bub_ms( test_origin + point( 2, 0 ) ),
you.get_pathfinding_settings(),
{} );
REQUIRE( !route.empty() );
CAPTURE( route );
REQUIRE( route.size() == 7 );
}

TEST_CASE( "fake_parts_are_opaque", "[vehicle][vehicle_fake]" )
{
really_clear_map();
Expand Down

0 comments on commit 677a59c

Please sign in to comment.