From f56aaa208dc1f24184ea4bed40a40cfd7bae6bff Mon Sep 17 00:00:00 2001 From: Antti Riikonen Date: Wed, 30 Oct 2024 09:16:58 +0200 Subject: [PATCH 1/7] Add size pathfinding setting, update calls --- src/character.cpp | 2 +- src/game.cpp | 2 +- src/map.cpp | 7 ++++++- src/monattack.cpp | 2 +- src/npc.cpp | 3 ++- src/pathfinding.cpp | 9 +++++++++ src/pathfinding.h | 7 +++++-- 7 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 1bf6c2c82cae1..402b658a8f58d 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/game.cpp b/src/game.cpp index 6c6369c65c8fb..81db9411cba56 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -4328,7 +4328,7 @@ Creature *game::is_hostile_within( int distance, bool dangerous ) return critter; } - const pathfinding_settings pf_settings = pathfinding_settings{ 8, distance, distance * 2, 4, true, true, false, true, false, false }; + const pathfinding_settings pf_settings = pathfinding_settings{ 8, distance, distance * 2, 4, true, true, false, true, false, false, critter->get_size() }; if( !get_map().route( u.pos_bub(), critter->pos_bub(), pf_settings ).empty() ) { return critter; diff --git a/src/map.cpp b/src/map.cpp index 0f816d86a3634..bd03b15a76391 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -5482,7 +5482,7 @@ std::pair map::_add_item_or_charges( const tripoint_bub tiles.erase( tiles.begin() ); // we already tried this position const int max_path_length = 4 * max_dist; const pathfinding_settings setting( 0, max_dist, max_path_length, 0, false, false, true, false, - false, false ); + false, false, creature_size::medium ); for( const tripoint_bub_ms &e : tiles ) { if( copies_remaining <= 0 ) { break; @@ -10776,6 +10776,11 @@ 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/monattack.cpp b/src/monattack.cpp index bb2cf033a050e..68ffecc9bfb58 100644 --- a/src/monattack.cpp +++ b/src/monattack.cpp @@ -1576,7 +1576,7 @@ bool mattack::triffid_heartbeat( monster *z ) map &here = get_map(); creature_tracker &creatures = get_creature_tracker(); static pathfinding_settings root_pathfind( 10, 20, 50, 0, false, false, false, false, false, - false ); + false, z->get_size() ); if( rl_dist( z->pos_bub(), player_character.pos_bub() ) > 5 && !here.route( player_character.pos_bub(), z->pos_bub(), root_pathfind ).empty() ) { add_msg( m_warning, _( "The root walls creak around you." ) ); diff --git a/src/npc.cpp b/src/npc.cpp index 15e280ae60ca0..d43401f1c07f1 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -253,7 +253,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..549cc036a365c 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; } + // what to do with p_special & PathfindingFlag::RestrictTiny? + if( ( p_special & PathfindingFlag::RestrictSmall && + settings.creature_size > creature_size::tiny ) || ( p_special & PathfindingFlag::RestrictMedium && + settings.creature_size > creature_size::small ) || ( p_special & PathfindingFlag::RestrictLarge && + settings.creature_size > creature_size::medium ) || ( p_special & PathfindingFlag::RestrictHuge && + settings.creature_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; diff --git a/src/pathfinding.h b/src/pathfinding.h index b744371eef444..e0698affaec0f 100644 --- a/src/pathfinding.h +++ b/src/pathfinding.h @@ -5,6 +5,7 @@ #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 +147,16 @@ struct pathfinding_settings { bool avoid_sharp = false; bool avoid_dangerous_fields = false; + creature_size creature_size = creature_size::medium; + 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, enum creature_size cs ) : 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 ), creature_size( cs ) {} pathfinding_settings &operator=( const pathfinding_settings & ) = default; }; From c3723edbac1f7a1bc293f5e272243be40fd62741 Mon Sep 17 00:00:00 2001 From: Antti Riikonen Date: Wed, 30 Oct 2024 09:27:29 +0200 Subject: [PATCH 2/7] Update size class when size changes --- src/character.cpp | 2 +- src/map.cpp | 3 ++- src/mutation.cpp | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 402b658a8f58d..0469663302bdc 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, creature_size::medium }; + *path_settings = pathfinding_settings{ 0, 1000, 1000, 0, true, true, true, true, false, true, get_size() }; move_mode = move_mode_walk; next_expected_position = std::nullopt; diff --git a/src/map.cpp b/src/map.cpp index bd03b15a76391..ef58bfa4cf903 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -5481,8 +5481,9 @@ std::pair map::_add_item_or_charges( const tripoint_bub std::vector tiles = closest_points_first( pos, max_dist ); tiles.erase( tiles.begin() ); // we already tried this position const int max_path_length = 4 * max_dist; + // TODO need to make creature size nullable so it can be ignored when not pathing for creature const pathfinding_settings setting( 0, max_dist, max_path_length, 0, false, false, true, false, - false, false, creature_size::medium ); + false, false, creature_size::huge ); for( const tripoint_bub_ms &e : tiles ) { if( copies_remaining <= 0 ) { break; diff --git a/src/mutation.cpp b/src/mutation.cpp index fdb14e8afa4f8..3fa9d955b1872 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->creature_size = size_class; } void Character::mutation_effect( const trait_id &mut, const bool worn_destroyed_override ) From 43d1363fce883a657c6d353de6cd60052aa4a6ed Mon Sep 17 00:00:00 2001 From: Antti Riikonen Date: Wed, 30 Oct 2024 23:56:00 +0200 Subject: [PATCH 3/7] make pathfinding setting size optional, try to account for openables --- src/character.cpp | 2 +- src/game.cpp | 2 +- src/map.cpp | 2 +- src/monattack.cpp | 2 +- src/mutation.cpp | 2 +- src/pathfinding.cpp | 22 ++++++++++++++++------ src/pathfinding.h | 8 +++++--- 7 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 0469663302bdc..402b658a8f58d 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, get_size() }; + *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/game.cpp b/src/game.cpp index 81db9411cba56..6c6369c65c8fb 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -4328,7 +4328,7 @@ Creature *game::is_hostile_within( int distance, bool dangerous ) return critter; } - const pathfinding_settings pf_settings = pathfinding_settings{ 8, distance, distance * 2, 4, true, true, false, true, false, false, critter->get_size() }; + const pathfinding_settings pf_settings = pathfinding_settings{ 8, distance, distance * 2, 4, true, true, false, true, false, false }; if( !get_map().route( u.pos_bub(), critter->pos_bub(), pf_settings ).empty() ) { return critter; diff --git a/src/map.cpp b/src/map.cpp index ef58bfa4cf903..444eab14569b8 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -5483,7 +5483,7 @@ std::pair map::_add_item_or_charges( const tripoint_bub const int max_path_length = 4 * max_dist; // TODO need to make creature size nullable so it can be ignored when not pathing for creature const pathfinding_settings setting( 0, max_dist, max_path_length, 0, false, false, true, false, - false, false, creature_size::huge ); + false, false ); for( const tripoint_bub_ms &e : tiles ) { if( copies_remaining <= 0 ) { break; diff --git a/src/monattack.cpp b/src/monattack.cpp index 68ffecc9bfb58..bb2cf033a050e 100644 --- a/src/monattack.cpp +++ b/src/monattack.cpp @@ -1576,7 +1576,7 @@ bool mattack::triffid_heartbeat( monster *z ) map &here = get_map(); creature_tracker &creatures = get_creature_tracker(); static pathfinding_settings root_pathfind( 10, 20, 50, 0, false, false, false, false, false, - false, z->get_size() ); + false ); if( rl_dist( z->pos_bub(), player_character.pos_bub() ) > 5 && !here.route( player_character.pos_bub(), z->pos_bub(), root_pathfind ).empty() ) { add_msg( m_warning, _( "The root walls creak around you." ) ); diff --git a/src/mutation.cpp b/src/mutation.cpp index 3fa9d955b1872..25a3fe500c414 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -556,7 +556,7 @@ void Character::recalculate_size() size_class = creature_size::medium; } } - path_settings->creature_size = size_class; + path_settings->size = size_class; } void Character::mutation_effect( const trait_id &mut, const bool worn_destroyed_override ) diff --git a/src/pathfinding.cpp b/src/pathfinding.cpp index 549cc036a365c..c62d9262c7b51 100644 --- a/src/pathfinding.cpp +++ b/src/pathfinding.cpp @@ -229,14 +229,17 @@ int map::cost_to_pass( const tripoint_bub_ms &cur, const tripoint_bub_ms &p, } // what to do with p_special & PathfindingFlag::RestrictTiny? - if( ( p_special & PathfindingFlag::RestrictSmall && - settings.creature_size > creature_size::tiny ) || ( p_special & PathfindingFlag::RestrictMedium && - settings.creature_size > creature_size::small ) || ( p_special & PathfindingFlag::RestrictLarge && - settings.creature_size > creature_size::medium ) || ( p_special & PathfindingFlag::RestrictHuge && - settings.creature_size > creature_size::large ) ) { + 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; @@ -306,7 +309,14 @@ int map::cost_to_pass( const tripoint_bub_ms &cur, const tripoint_bub_ms &p, } // 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 ) && + // The open version of terrain/furniture also needs to be passable for our size. + if( allow_open_doors && + ( ( terrain.open && + ( terrain.open->has_flag( ter_furn_flag::TFLAG_SMALL_PASSAGE ) ? settings.size < + creature_size::large : true ) ) || + ( furniture.open && + ( furniture.open->has_flag( ter_furn_flag::TFLAG_SMALL_PASSAGE ) ? settings.size < + creature_size::large : true ) ) ) && ( ( !terrain.has_flag( ter_furn_flag::TFLAG_OPENCLOSE_INSIDE ) && !furniture.has_flag( ter_furn_flag::TFLAG_OPENCLOSE_INSIDE ) ) || !is_outside( cur ) ) ) { diff --git a/src/pathfinding.h b/src/pathfinding.h index e0698affaec0f..7b83e3c49e6e1 100644 --- a/src/pathfinding.h +++ b/src/pathfinding.h @@ -2,6 +2,8 @@ #ifndef CATA_SRC_PATHFINDING_H #define CATA_SRC_PATHFINDING_H +#include + #include "coords_fwd.h" #include "game_constants.h" #include "mdarray.h" @@ -147,16 +149,16 @@ struct pathfinding_settings { bool avoid_sharp = false; bool avoid_dangerous_fields = false; - creature_size creature_size = creature_size::medium; + 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, enum creature_size cs ) + 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 ), creature_size( cs ) {} + avoid_rough_terrain( art ), avoid_sharp( as ), size( sz ) {} pathfinding_settings &operator=( const pathfinding_settings & ) = default; }; From 5dc278a7118007a2a4cc20435a60c808ba7af84a Mon Sep 17 00:00:00 2001 From: Antti Riikonen Date: Sun, 3 Nov 2024 09:28:20 +0200 Subject: [PATCH 4/7] Move checking for size passability into its own condition block --- src/pathfinding.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/pathfinding.cpp b/src/pathfinding.cpp index c62d9262c7b51..7fc8a54d02d62 100644 --- a/src/pathfinding.cpp +++ b/src/pathfinding.cpp @@ -308,15 +308,19 @@ int map::cost_to_pass( const tripoint_bub_ms &cur, const tripoint_bub_ms &p, return climb_cost; } - // If it's a door and we can open it from the tile we're on, cool. - // The open version of terrain/furniture also needs to be passable for our size. + // If terrain/furniture is openable but we can't fit through the open version, ignore the tile if( allow_open_doors && - ( ( terrain.open && - ( terrain.open->has_flag( ter_furn_flag::TFLAG_SMALL_PASSAGE ) ? settings.size < - creature_size::large : true ) ) || - ( furniture.open && - ( furniture.open->has_flag( ter_furn_flag::TFLAG_SMALL_PASSAGE ) ? settings.size < - creature_size::large : true ) ) ) && + ( ( 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 ) && !furniture.has_flag( ter_furn_flag::TFLAG_OPENCLOSE_INSIDE ) ) || !is_outside( cur ) ) ) { From 23bab5b92757ec27e18de8c6cbb55c8a2ed71cf0 Mon Sep 17 00:00:00 2001 From: Antti Riikonen Date: Sun, 3 Nov 2024 09:32:54 +0200 Subject: [PATCH 5/7] Clarify comment about why tiny isn't checked for, remove obsolete comment --- src/map.cpp | 1 - src/pathfinding.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index 444eab14569b8..fb6b969c5eafd 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -5481,7 +5481,6 @@ std::pair map::_add_item_or_charges( const tripoint_bub std::vector tiles = closest_points_first( pos, max_dist ); tiles.erase( tiles.begin() ); // we already tried this position const int max_path_length = 4 * max_dist; - // TODO need to make creature size nullable so it can be ignored when not pathing for creature const pathfinding_settings setting( 0, max_dist, max_path_length, 0, false, false, true, false, false, false ); for( const tripoint_bub_ms &e : tiles ) { diff --git a/src/pathfinding.cpp b/src/pathfinding.cpp index 7fc8a54d02d62..09c0eef861992 100644 --- a/src/pathfinding.cpp +++ b/src/pathfinding.cpp @@ -228,7 +228,7 @@ int map::cost_to_pass( const tripoint_bub_ms &cur, const tripoint_bub_ms &p, return PF_IMPASSABLE; } - // what to do with p_special & PathfindingFlag::RestrictTiny? + // 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 ) || From cf71ee5aeec14529965ceadb3da11f45a5c18f50 Mon Sep 17 00:00:00 2001 From: Antti Riikonen Date: Sun, 3 Nov 2024 10:06:03 +0200 Subject: [PATCH 6/7] Bail out from openable passable check if we don't care about size --- src/pathfinding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pathfinding.cpp b/src/pathfinding.cpp index 09c0eef861992..0a6b26d3c6090 100644 --- a/src/pathfinding.cpp +++ b/src/pathfinding.cpp @@ -309,7 +309,7 @@ int map::cost_to_pass( const tripoint_bub_ms &cur, const tripoint_bub_ms &p, } // If terrain/furniture is openable but we can't fit through the open version, ignore the tile - if( allow_open_doors && + 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 From a4befb621678164d6961aa96d03c6aa7ad90dca0 Mon Sep 17 00:00:00 2001 From: Antti Riikonen Date: Sun, 3 Nov 2024 14:13:25 +0200 Subject: [PATCH 7/7] Clean up extraneous newlines --- src/map.cpp | 1 - src/pathfinding.cpp | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index fb6b969c5eafd..d2cd1150645f1 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -10778,7 +10778,6 @@ void map::update_pathfinding_cache( const tripoint_bub_ms &p ) const 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/pathfinding.cpp b/src/pathfinding.cpp index 0a6b26d3c6090..2230af349baf7 100644 --- a/src/pathfinding.cpp +++ b/src/pathfinding.cpp @@ -235,11 +235,8 @@ int map::cost_to_pass( const tripoint_bub_ms &cur, const tripoint_bub_ms &p, ( 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;