From 01e5e938257ada98c2582b4b11ab84b8cb0f5035 Mon Sep 17 00:00:00 2001 From: expwnent Date: Sun, 16 Dec 2012 23:26:50 -0500 Subject: [PATCH 1/3] Renamed Maps::canWalkBetween to Maps::canPathBetween and added Maps::canWalkBetween, which does what it says. --- library/LuaApi.cpp | 2 +- library/include/modules/Maps.h | 1 + library/modules/Maps.cpp | 46 +++++++++++++++++- plugins/devel/CMakeLists.txt | 1 + plugins/devel/walkBetween.cpp | 87 ++++++++++++++++++++++++++++++++++ plugins/fix-armory.cpp | 2 +- 6 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 plugins/devel/walkBetween.cpp diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 0151ed404..720ccd21f 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1309,7 +1309,7 @@ static const LuaWrapper::FunctionReg dfhack_maps_module[] = { WRAPM(Maps, enableBlockUpdates), WRAPM(Maps, getGlobalInitFeature), WRAPM(Maps, getLocalInitFeature), - WRAPM(Maps, canWalkBetween), + WRAPM(Maps, canPathBetween), WRAPM(Maps, spawnFlow), WRAPN(hasTileAssignment, hasTileAssignment), WRAPN(getTileAssignment, getTileAssignment), diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h index 632e8ec13..2655268d7 100644 --- a/library/include/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -308,6 +308,7 @@ extern DFHACK_EXPORT bool SortBlockEvents(df::map_block *block, /// remove a block event from the block by address 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); } } diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 482b950ba..0db69ea82 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -521,7 +521,7 @@ bool Maps::ReadGeology(vector > *layer_mats, vector return true; } -bool Maps::canWalkBetween(df::coord pos1, df::coord pos2) +bool Maps::canPathBetween(df::coord pos1, df::coord pos2) { auto block1 = getTileBlock(pos1); auto block2 = getTileBlock(pos2); @@ -535,6 +535,50 @@ bool Maps::canWalkBetween(df::coord pos1, df::coord pos2) return tile1 && tile1 == tile2; } +bool Maps::canWalkBetween(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; + + if ( dx*dx > 1 || dy*dy > 1 || dz*dz > 1 ) + return false; + + if ( dz == 0 ) + return true; + + df::tiletype* type1 = Maps::getTileType(pos1); + df::tiletype* type2 = Maps::getTileType(pos2); + + df::tiletype_shape shape1 = ENUM_ATTR(tiletype,shape,*type1); + df::tiletype_shape shape2 = ENUM_ATTR(tiletype,shape,*type2); + + if ( pos2.z < pos1.z ) { + df::tiletype_shape temp = shape1; + shape1 = shape2; + shape2 = temp; + } + if ( dx == 0 && dy == 0 ) { + if ( shape1 == tiletype_shape::STAIR_UPDOWN && shape2 == shape1 ) + return true; + if ( shape1 == tiletype_shape::STAIR_UPDOWN && shape2 == tiletype_shape::STAIR_DOWN ) + return true; + if ( shape1 == tiletype_shape::STAIR_UP && shape2 == tiletype_shape::STAIR_UPDOWN ) + return true; + return false; + } + + //diagonal up: has to be a ramp + if ( shape1 == tiletype_shape::RAMP && shape2 == tiletype_shape::RAMP ) + return true; + + return false; +} + #define COPY(a,b) memcpy(&a,&b,sizeof(a)) MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent) diff --git a/plugins/devel/CMakeLists.txt b/plugins/devel/CMakeLists.txt index 134d5cb67..41fcd8130 100644 --- a/plugins/devel/CMakeLists.txt +++ b/plugins/devel/CMakeLists.txt @@ -21,3 +21,4 @@ DFHACK_PLUGIN(vshook vshook.cpp) IF(UNIX) DFHACK_PLUGIN(ref-index ref-index.cpp) ENDIF() +DFHACK_PLUGIN(walkBetween walkBetween.cpp) diff --git a/plugins/devel/walkBetween.cpp b/plugins/devel/walkBetween.cpp new file mode 100644 index 000000000..9dafe4bb8 --- /dev/null +++ b/plugins/devel/walkBetween.cpp @@ -0,0 +1,87 @@ + +#include "Core.h" +#include +#include +#include + +// DF data structure definition headers +#include "DataDefs.h" +#include "df/world.h" + +#include "modules/Gui.h" +#include "modules/Maps.h" + +using namespace DFHack; +using namespace df::enums; + + + +command_result walkBetween (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"); + +// 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 */ + // Extended help string. Used by CR_WRONG_USAGE and the help command: + " This command does nothing at all.\n" + )); + return CR_OK; +} + +// This is called right before the plugin library is removed from memory. +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) +{ + // You *MUST* kill all threads you created before this returns. + // If everything fails, just return CR_FAILURE. Your plugin will be + // in a zombie state, but things won't crash. + return CR_OK; +} + +// Called to notify the plugin about important state changes. +// Invoked with DF suspended, and always before the matching plugin_onupdate. +// More event codes may be added in the future. +/* +DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) +{ + switch (event) { + case SC_GAME_LOADED: + // initialize from the world just loaded + break; + case SC_GAME_UNLOADED: + // cleanup + break; + default: + break; + } + return CR_OK; +} +*/ + +// Whatever you put here will be done in each game step. Don't abuse it. +// It's optional, so you can just comment it out like this if you don't need it. +/* +DFhackCExport command_result plugin_onupdate ( color_ostream &out ) +{ + // whetever. You don't need to suspend DF execution here. + return CR_OK; +} +*/ + +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) +{ + 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)); + + prev = bob; + return CR_OK; +} diff --git a/plugins/fix-armory.cpp b/plugins/fix-armory.cpp index b937d40e8..e54639960 100644 --- a/plugins/fix-armory.cpp +++ b/plugins/fix-armory.cpp @@ -475,7 +475,7 @@ static bool try_store_item(df::building *target, df::item *item) df::coord tpos(target->centerx, target->centery, target->z); df::coord ipos = Items::getPosition(item); - if (!Maps::canWalkBetween(tpos, ipos)) + if (!Maps::canPathBetween(tpos, ipos)) return false; // Check if the target has enough space left From d2be8f18e131ac5d2c763703b8fe62c53a420e51 Mon Sep 17 00:00:00 2001 From: expwnent Date: Sun, 16 Dec 2012 23:30:35 -0500 Subject: [PATCH 2/3] canWalkBetween: forgot a case with stairs. --- library/modules/Maps.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 0db69ea82..4b468defc 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -569,6 +569,8 @@ bool Maps::canWalkBetween(df::coord pos1, df::coord pos2) return true; if ( shape1 == tiletype_shape::STAIR_UP && shape2 == tiletype_shape::STAIR_UPDOWN ) return true; + if ( shape1 == tiletype_shape::STAIR_UP && shape2 == tiletype_shape::STAIR_DOWN ) + return true; return false; } From 1a6a09281b8b3e5d6666bec376bfe526d91b47a3 Mon Sep 17 00:00:00 2001 From: expwnent Date: Sun, 16 Dec 2012 23:37:15 -0500 Subject: [PATCH 3/3] canWalkBetween: forgot a case with ramps. --- library/modules/Maps.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 4b468defc..ff02bcf60 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -551,17 +551,18 @@ bool Maps::canWalkBetween(df::coord pos1, df::coord pos2) if ( dz == 0 ) return true; + if ( pos2.z < pos1.z ) { + df::coord temp = pos1; + pos1 = pos2; + pos2 = temp; + } + df::tiletype* type1 = Maps::getTileType(pos1); df::tiletype* type2 = Maps::getTileType(pos2); df::tiletype_shape shape1 = ENUM_ATTR(tiletype,shape,*type1); df::tiletype_shape shape2 = ENUM_ATTR(tiletype,shape,*type2); - if ( pos2.z < pos1.z ) { - df::tiletype_shape temp = shape1; - shape1 = shape2; - shape2 = temp; - } if ( dx == 0 && dy == 0 ) { if ( shape1 == tiletype_shape::STAIR_UPDOWN && shape2 == shape1 ) return true; @@ -575,8 +576,12 @@ bool Maps::canWalkBetween(df::coord pos1, df::coord pos2) } //diagonal up: has to be a ramp - if ( shape1 == tiletype_shape::RAMP && shape2 == tiletype_shape::RAMP ) - return true; + if ( shape1 == tiletype_shape::RAMP && shape2 == tiletype_shape::RAMP ) { + df::coord up = df::coord(pos1.x,pos1.y,pos1.z+1); + df::tiletype* typeUp = Maps::getTileType(up); + df::tiletype_shape shapeUp = ENUM_ATTR(tiletype,shape,*typeUp); + return shapeUp == tiletype_shape::RAMP_TOP; + } return false; }