stepBetween: named a few things better, and fixed a lot.

develop
expwnent 2012-12-19 20:30:37 -05:00
parent 22837af8d7
commit 7972902c81
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 );
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

@ -30,10 +30,12 @@ distribution.
#include <map>
#include <set>
#include <cstdlib>
#include <iostream>
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<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* 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<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 )
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<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;
}
//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<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;

@ -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)

@ -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.
// 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 <PluginCommand> &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 <std::string> & parameters)
command_result stepBetween (color_ostream &out, std::vector <std::string> & 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;