diff --git a/src/character.cpp b/src/character.cpp index c2b46774186a0..79859d300a56b 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -591,7 +591,7 @@ Character::Character() : name.clear(); custom_profession.clear(); - *path_settings = pathfinding_settings{ 0, 1000, 1000, 0, true, true, true, true, false, true }; + *path_settings = pathfinding_settings{ 0, 1000, 1000, 0, true, true, true, true, false, true, creature_size::medium }; move_mode = move_mode_walk; next_expected_position = std::nullopt; diff --git a/src/map.cpp b/src/map.cpp index 9af98479cd722..886067f0bc50e 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -10810,6 +10810,10 @@ void map::update_pathfinding_cache( const tripoint_bub_ms &p ) const cur_value |= PathfindingFlag::Sharp; } + if( terrain.has_flag( ter_furn_flag::TFLAG_SMALL_PASSAGE ) ) { + cur_value |= ( PathfindingFlag::RestrictLarge | PathfindingFlag::RestrictHuge ); + } + cache.special[p.x()][p.y()] = cur_value; } diff --git a/src/mutation.cpp b/src/mutation.cpp index fdb14e8afa4f8..25a3fe500c414 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -37,6 +37,7 @@ #include "options.h" #include "output.h" #include "overmapbuffer.h" +#include "pathfinding.h" #include "pimpl.h" #include "player_activity.h" #include "rng.h" @@ -555,6 +556,7 @@ void Character::recalculate_size() size_class = creature_size::medium; } } + path_settings->size = size_class; } void Character::mutation_effect( const trait_id &mut, const bool worn_destroyed_override ) diff --git a/src/npc.cpp b/src/npc.cpp index 91bdbe346c4de..a8c96021e3b12 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -261,7 +261,8 @@ npc::npc() patience = 0; attitude = NPCATT_NULL; - *path_settings = pathfinding_settings( 0, 1000, 1000, 10, true, true, true, true, false, true ); + *path_settings = pathfinding_settings( 0, 1000, 1000, 10, true, true, true, true, false, true, + get_size() ); for( direction threat_dir : npc_threat_dir ) { ai_cache.threat_map[ threat_dir ] = 0.0f; } diff --git a/src/pathfinding.cpp b/src/pathfinding.cpp index ab80eafa1fc32..2230af349baf7 100644 --- a/src/pathfinding.cpp +++ b/src/pathfinding.cpp @@ -228,6 +228,15 @@ int map::cost_to_pass( const tripoint_bub_ms &cur, const tripoint_bub_ms &p, return PF_IMPASSABLE; } + // RestrictTiny isn't checked since it's unclear how it would actually work as there's no category smaller than tiny + if( settings.size && ( + ( p_special & PathfindingFlag::RestrictSmall && settings.size > creature_size::tiny ) || + ( p_special & PathfindingFlag::RestrictMedium && settings.size > creature_size::small ) || + ( p_special & PathfindingFlag::RestrictLarge && settings.size > creature_size::medium ) || + ( p_special & PathfindingFlag::RestrictHuge && settings.size > creature_size::large ) ) ) { + return PF_IMPASSABLE; + } + const int bash = settings.bash_strength; const bool allow_open_doors = settings.allow_open_doors; const bool allow_unlock_doors = settings.allow_unlock_doors; @@ -296,6 +305,17 @@ int map::cost_to_pass( const tripoint_bub_ms &cur, const tripoint_bub_ms &p, return climb_cost; } + // If terrain/furniture is openable but we can't fit through the open version, ignore the tile + if( settings.size && allow_open_doors && + ( ( terrain.open && terrain.open->has_flag( ter_furn_flag::TFLAG_SMALL_PASSAGE ) ) || + ( furniture.open && furniture.open->has_flag( ter_furn_flag::TFLAG_SMALL_PASSAGE ) ) || + // Windows with curtains need to be opened twice + ( terrain.open->open && terrain.open->open->has_flag( ter_furn_flag::TFLAG_SMALL_PASSAGE ) ) ) && + settings.size > creature_size::medium + ) { + return PF_IMPASSABLE; + } + // If it's a door and we can open it from the tile we're on, cool. if( allow_open_doors && ( terrain.open || furniture.open ) && ( ( !terrain.has_flag( ter_furn_flag::TFLAG_OPENCLOSE_INSIDE ) && diff --git a/src/pathfinding.h b/src/pathfinding.h index b744371eef444..7b83e3c49e6e1 100644 --- a/src/pathfinding.h +++ b/src/pathfinding.h @@ -2,9 +2,12 @@ #ifndef CATA_SRC_PATHFINDING_H #define CATA_SRC_PATHFINDING_H +#include + #include "coords_fwd.h" #include "game_constants.h" #include "mdarray.h" +#include "character.h" // An attribute of a particular map square that is of interest in pathfinding. // Has a maximum of 32 members. For more, the datatype underlying PathfindingFlags @@ -146,14 +149,16 @@ struct pathfinding_settings { bool avoid_sharp = false; bool avoid_dangerous_fields = false; + std::optional size = std::nullopt; + pathfinding_settings() = default; pathfinding_settings( const pathfinding_settings & ) = default; pathfinding_settings( int bs, int md, int ml, int cc, bool aod, bool aud, bool at, bool acs, - bool art, bool as ) + bool art, bool as, std::optional sz = std::nullopt ) : bash_strength( bs ), max_dist( md ), max_length( ml ), climb_cost( cc ), allow_open_doors( aod ), allow_unlock_doors( aud ), avoid_traps( at ), allow_climb_stairs( acs ), - avoid_rough_terrain( art ), avoid_sharp( as ) {} + avoid_rough_terrain( art ), avoid_sharp( as ), size( sz ) {} pathfinding_settings &operator=( const pathfinding_settings & ) = default; };