From 7972902c81408526d77821d31bb12d355f85a8ed Mon Sep 17 00:00:00 2001 From: expwnent Date: Wed, 19 Dec 2012 20:30:37 -0500 Subject: [PATCH] stepBetween: named a few things better, and fixed a lot. --- library/include/modules/Maps.h | 2 +- library/modules/Maps.cpp | 99 ++++++++++++++++--- plugins/devel/CMakeLists.txt | 2 +- .../{walkBetween.cpp => stepBetween.cpp} | 12 +-- 4 files changed, 95 insertions(+), 20 deletions(-) rename plugins/devel/{walkBetween.cpp => stepBetween.cpp} (87%) diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h index 2655268d7..29d3d69ba 100644 --- a/library/include/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -309,7 +309,7 @@ extern DFHACK_EXPORT bool SortBlockEvents(df::map_block *block, extern DFHACK_EXPORT bool RemoveBlockEvent(uint32_t x, uint32_t y, uint32_t z, df::block_square_event * which ); DFHACK_EXPORT bool canPathBetween(df::coord pos1, df::coord pos2); -DFHACK_EXPORT bool canWalkBetween(df::coord pos1, df::coord pos2); +DFHACK_EXPORT bool canStepBetween(df::coord pos1, df::coord pos2); } } #endif diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index f736d385a..6517331ee 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -30,10 +30,12 @@ distribution. #include #include #include +#include using namespace std; #include "modules/Maps.h" #include "modules/MapCache.h" +#include "ColorText.h" #include "Error.h" #include "VersionInfo.h" #include "MemAccess.h" @@ -59,6 +61,7 @@ using namespace std; #include "df/z_level_flags.h" #include "df/region_map_entry.h" #include "df/flow_info.h" +#include "df/building_type.h" using namespace DFHack; using namespace df::enums; @@ -535,28 +538,35 @@ bool Maps::canPathBetween(df::coord pos1, df::coord pos2) return tile1 && tile1 == tile2; } -bool Maps::canWalkBetween(df::coord pos1, df::coord pos2) +bool Maps::canStepBetween(df::coord pos1, df::coord pos2) { - bool b = canPathBetween(pos1, pos2); - if ( !b ) - return false; - - int32_t dx = pos1.x-pos2.x; - int32_t dy = pos1.y-pos2.y; - int32_t dz = pos1.z-pos2.z; + color_ostream& out = Core::getInstance().getConsole(); + int32_t dx = pos2.x-pos1.x; + int32_t dy = pos2.y-pos1.y; + int32_t dz = pos2.z-pos1.z; if ( dx*dx > 1 || dy*dy > 1 || dz*dz > 1 ) return false; - if ( dz == 0 ) - return true; - if ( pos2.z < pos1.z ) { df::coord temp = pos1; pos1 = pos2; pos2 = temp; } + df::map_block* block1 = getTileBlock(pos1); + df::map_block* block2 = getTileBlock(pos2); + + if ( !block1 || !block2 ) + return false; + + if ( !index_tile(block1->walkable,pos1) || !index_tile(block2->walkable,pos2) ) { + return false; + } + + if ( dz == 0 ) + return true; + df::tiletype* type1 = Maps::getTileType(pos1); df::tiletype* type2 = Maps::getTileType(pos2); @@ -564,6 +574,11 @@ bool Maps::canWalkBetween(df::coord pos1, df::coord pos2) df::tiletype_shape shape2 = ENUM_ATTR(tiletype,shape,*type2); if ( dx == 0 && dy == 0 ) { + //check for forbidden hatches and floors and such + df::enums::tile_building_occ::tile_building_occ upOcc = index_tile(block2->occupancy,pos2).bits.building; + if ( upOcc == df::enums::tile_building_occ::Impassable || upOcc == df::enums::tile_building_occ::Obstacle || upOcc == df::enums::tile_building_occ::Floored ) + return false; + if ( shape1 == tiletype_shape::STAIR_UPDOWN && shape2 == shape1 ) return true; if ( shape1 == tiletype_shape::STAIR_UPDOWN && shape2 == tiletype_shape::STAIR_DOWN ) @@ -572,15 +587,75 @@ bool Maps::canWalkBetween(df::coord pos1, df::coord pos2) return true; if ( shape1 == tiletype_shape::STAIR_UP && shape2 == tiletype_shape::STAIR_DOWN ) return true; + if ( shape1 == tiletype_shape::RAMP && shape2 == tiletype_shape::RAMP_TOP ) { + //it depends + //there has to be a wall next to the ramp + bool foundWall = false; + for ( int32_t x = -1; x <= 1; x++ ) { + for ( int32_t y = -1; y <= 1; y++ ) { + if ( x == 0 && y == 0 ) + continue; + df::tiletype* type = Maps::getTileType(df::coord(pos1.x+x,pos1.y+y,pos1.z)); + df::tiletype_shape shape1 = ENUM_ATTR(tiletype,shape,*type); + if ( shape1 == tiletype_shape::WALL ) { + foundWall = true; + x = 2; + break; + } + } + } + if ( !foundWall ) + return false; //unusable ramp + + //there has to be an unforbidden hatch above the ramp + if ( index_tile(block2->occupancy,pos2).bits.building != df::enums::tile_building_occ::Dynamic ) + return false; + //note that forbidden hatches have Floored occupancy. unforbidden ones have dynamic occupancy + df::building* building = Buildings::findAtTile(pos2); + if ( building == NULL ) { + out << __FILE__ << ", line " << __LINE__ << ": couldn't find hatch.\n"; + return false; + } + if ( building->getType() != df::enums::building_type::Hatch ) { + return false; + } + return true; + } return false; } //diagonal up: has to be a ramp if ( shape1 == tiletype_shape::RAMP /*&& shape2 == tiletype_shape::RAMP*/ ) { df::coord up = df::coord(pos1.x,pos1.y,pos1.z+1); + bool foundWall = false; + for ( int32_t x = -1; x <= 1; x++ ) { + for ( int32_t y = -1; y <= 1; y++ ) { + if ( x == 0 && y == 0 ) + continue; + df::tiletype* type = Maps::getTileType(df::coord(pos1.x+x,pos1.y+y,pos1.z)); + df::tiletype_shape shape1 = ENUM_ATTR(tiletype,shape,*type); + if ( shape1 == tiletype_shape::WALL ) { + foundWall = true; + x = 2; + break; + } + } + } + if ( !foundWall ) + return false; //unusable ramp df::tiletype* typeUp = Maps::getTileType(up); df::tiletype_shape shapeUp = ENUM_ATTR(tiletype,shape,*typeUp); - return shapeUp == tiletype_shape::RAMP_TOP; + if ( shapeUp != tiletype_shape::RAMP_TOP ) + return false; + + df::map_block* blockUp = getTileBlock(up); + if ( !blockUp ) + return false; + + df::enums::tile_building_occ::tile_building_occ occupancy = index_tile(blockUp->occupancy,up).bits.building; + if ( occupancy == df::enums::tile_building_occ::Obstacle || occupancy == df::enums::tile_building_occ::Floored || occupancy == df::enums::tile_building_occ::Impassable ) + return false; + return true; } return false; diff --git a/plugins/devel/CMakeLists.txt b/plugins/devel/CMakeLists.txt index 41fcd8130..8b0778f86 100644 --- a/plugins/devel/CMakeLists.txt +++ b/plugins/devel/CMakeLists.txt @@ -21,4 +21,4 @@ DFHACK_PLUGIN(vshook vshook.cpp) IF(UNIX) DFHACK_PLUGIN(ref-index ref-index.cpp) ENDIF() -DFHACK_PLUGIN(walkBetween walkBetween.cpp) +DFHACK_PLUGIN(stepBetween stepBetween.cpp) diff --git a/plugins/devel/walkBetween.cpp b/plugins/devel/stepBetween.cpp similarity index 87% rename from plugins/devel/walkBetween.cpp rename to plugins/devel/stepBetween.cpp index 9dafe4bb8..c1bc3fa1a 100644 --- a/plugins/devel/walkBetween.cpp +++ b/plugins/devel/stepBetween.cpp @@ -16,19 +16,19 @@ using namespace df::enums; -command_result walkBetween (color_ostream &out, std::vector & parameters); +command_result stepBetween (color_ostream &out, std::vector & parameters); // A plugin must be able to return its name and version. // The name string provided must correspond to the filename - skeleton.plug.so or skeleton.plug.dll in this case -DFHACK_PLUGIN("walkBetween"); +DFHACK_PLUGIN("stepBetween"); // Mandatory init function. If you have some global state, create it here. DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { // Fill the command list with your commands. commands.push_back(PluginCommand( - "walkBetween", "Do nothing, look pretty.", - walkBetween, false, /* true means that the command can't be used from non-interactive user interface */ + "stepBetween", "Do nothing, look pretty.", + stepBetween, false, /* true means that the command can't be used from non-interactive user interface */ // Extended help string. Used by CR_WRONG_USAGE and the help command: " This command does nothing at all.\n" )); @@ -77,10 +77,10 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) df::coord prev; // A command! It sits around and looks pretty. And it's nice and friendly. -command_result walkBetween (color_ostream &out, std::vector & parameters) +command_result stepBetween (color_ostream &out, std::vector & parameters) { df::coord bob = Gui::getCursorPos(); - out.print("(%d,%d,%d), (%d,%d,%d): canWalkBetween = %d, canPathBetween = %d\n", prev.x, prev.y, prev.z, bob.x, bob.y, bob.z, Maps::canWalkBetween(prev, bob), Maps::canPathBetween(prev,bob)); + out.print("(%d,%d,%d), (%d,%d,%d): canWalkBetween = %d, canPathBetween = %d\n", prev.x, prev.y, prev.z, bob.x, bob.y, bob.z, Maps::canStepBetween(prev, bob), Maps::canPathBetween(prev,bob)); prev = bob; return CR_OK;