Merge branch 'canWalkBetween' into diggingInvaders

develop
expwnent 2012-12-19 20:31:17 -05:00
commit ee4f37ff72
4 changed files with 95 additions and 20 deletions

@ -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 ); 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 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 #endif

@ -30,10 +30,12 @@ distribution.
#include <map> #include <map>
#include <set> #include <set>
#include <cstdlib> #include <cstdlib>
#include <iostream>
using namespace std; using namespace std;
#include "modules/Maps.h" #include "modules/Maps.h"
#include "modules/MapCache.h" #include "modules/MapCache.h"
#include "ColorText.h"
#include "Error.h" #include "Error.h"
#include "VersionInfo.h" #include "VersionInfo.h"
#include "MemAccess.h" #include "MemAccess.h"
@ -59,6 +61,7 @@ using namespace std;
#include "df/z_level_flags.h" #include "df/z_level_flags.h"
#include "df/region_map_entry.h" #include "df/region_map_entry.h"
#include "df/flow_info.h" #include "df/flow_info.h"
#include "df/building_type.h"
using namespace DFHack; using namespace DFHack;
using namespace df::enums; using namespace df::enums;
@ -535,28 +538,35 @@ bool Maps::canPathBetween(df::coord pos1, df::coord pos2)
return tile1 && tile1 == tile2; 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); color_ostream& out = Core::getInstance().getConsole();
if ( !b ) int32_t dx = pos2.x-pos1.x;
return false; int32_t dy = pos2.y-pos1.y;
int32_t dz = pos2.z-pos1.z;
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 ) if ( dx*dx > 1 || dy*dy > 1 || dz*dz > 1 )
return false; return false;
if ( dz == 0 )
return true;
if ( pos2.z < pos1.z ) { if ( pos2.z < pos1.z ) {
df::coord temp = pos1; df::coord temp = pos1;
pos1 = pos2; pos1 = pos2;
pos2 = temp; pos2 = temp;
} }
df::map_block* block1 = getTileBlock(pos1);
df::map_block* block2 = getTileBlock(pos2);
if ( !block1 || !block2 )
return false;
if ( !index_tile<uint16_t>(block1->walkable,pos1) || !index_tile<uint16_t>(block2->walkable,pos2) ) {
return false;
}
if ( dz == 0 )
return true;
df::tiletype* type1 = Maps::getTileType(pos1); df::tiletype* type1 = Maps::getTileType(pos1);
df::tiletype* type2 = Maps::getTileType(pos2); 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); df::tiletype_shape shape2 = ENUM_ATTR(tiletype,shape,*type2);
if ( dx == 0 && dy == 0 ) { if ( dx == 0 && dy == 0 ) {
//check for forbidden hatches and floors and such
df::enums::tile_building_occ::tile_building_occ upOcc = index_tile<df::tile_occupancy>(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 ) if ( shape1 == tiletype_shape::STAIR_UPDOWN && shape2 == shape1 )
return true; return true;
if ( shape1 == tiletype_shape::STAIR_UPDOWN && shape2 == tiletype_shape::STAIR_DOWN ) 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; return true;
if ( shape1 == tiletype_shape::STAIR_UP && shape2 == tiletype_shape::STAIR_DOWN ) if ( shape1 == tiletype_shape::STAIR_UP && shape2 == tiletype_shape::STAIR_DOWN )
return true; 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<df::tile_occupancy>(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; return false;
} }
//diagonal up: has to be a ramp //diagonal up: has to be a ramp
if ( shape1 == tiletype_shape::RAMP /*&& shape2 == tiletype_shape::RAMP*/ ) { if ( shape1 == tiletype_shape::RAMP /*&& shape2 == tiletype_shape::RAMP*/ ) {
df::coord up = df::coord(pos1.x,pos1.y,pos1.z+1); 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* typeUp = Maps::getTileType(up);
df::tiletype_shape shapeUp = ENUM_ATTR(tiletype,shape,*typeUp); 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<df::tile_occupancy>(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; return false;

@ -22,4 +22,4 @@ DFHACK_PLUGIN(eventExample eventExample.cpp)
IF(UNIX) IF(UNIX)
DFHACK_PLUGIN(ref-index ref-index.cpp) DFHACK_PLUGIN(ref-index ref-index.cpp)
ENDIF() ENDIF()
DFHACK_PLUGIN(walkBetween walkBetween.cpp) DFHACK_PLUGIN(stepBetween stepBetween.cpp)

@ -16,19 +16,19 @@ using namespace df::enums;
command_result walkBetween (color_ostream &out, std::vector <std::string> & parameters); command_result stepBetween (color_ostream &out, std::vector <std::string> & parameters);
// A plugin must be able to return its name and version. // 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 // 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. // Mandatory init function. If you have some global state, create it here.
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
// Fill the command list with your commands. // Fill the command list with your commands.
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"walkBetween", "Do nothing, look pretty.", "stepBetween", "Do nothing, look pretty.",
walkBetween, false, /* true means that the command can't be used from non-interactive user interface */ 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: // Extended help string. Used by CR_WRONG_USAGE and the help command:
" This command does nothing at all.\n" " This command does nothing at all.\n"
)); ));
@ -77,10 +77,10 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out )
df::coord prev; df::coord prev;
// A command! It sits around and looks pretty. And it's nice and friendly. // A command! It sits around and looks pretty. And it's nice and friendly.
command_result walkBetween (color_ostream &out, std::vector <std::string> & parameters) command_result stepBetween (color_ostream &out, std::vector <std::string> & parameters)
{ {
df::coord bob = Gui::getCursorPos(); 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; prev = bob;
return CR_OK; return CR_OK;