Added MapExtras, ported dfliquids to MapCache. Fixed vein non-ident bug in dfvdig.

develop
Petr Mrázek 2011-03-11 03:09:45 +01:00
parent b71c1a23c6
commit c223bb858f
12 changed files with 741 additions and 569 deletions

@ -2,7 +2,7 @@
PROJECT (dfhack)
cmake_minimum_required(VERSION 2.6)
SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/Modules)
SET ( DFHACK_VERSION "0.5.2" )
SET ( DFHACK_VERSION "0.5.4" )
# Set this to project source dir. When dfhack is used
# as a submodule, CMAKE_SOURCE_DIR is not pointing to

@ -130,7 +130,7 @@ NormalProcess::NormalProcess(uint32_t pid, VersionInfoFactory * factory)
if(EnumProcessModules(my_handle, &hmod, sizeof(hmod), &needed) == 0)
{
CloseHandle(my_handle);
my_handle=0;
my_handle=0;
// cout << "EnumProcessModules fail'd" << endl;
return; //if enumprocessModules fails, give up
}

@ -880,6 +880,53 @@ namespace DFHack
{"constructed ramp",RAMP,CONSTRUCTED, VAR_1},
{0 ,EMPTY, AIR, VAR_1} // end
};
// tile is missing a floor
inline
bool LowPassable(uint16_t tiletype)
{
switch(DFHack::tileTypeTable[tiletype].c)
{
case DFHack::EMPTY:
case DFHack::STAIR_DOWN:
case DFHack::STAIR_UPDOWN:
case DFHack::RAMP_TOP:
return true;
default:
return false;
}
};
// tile is missing a roof
inline
bool HighPassable(uint16_t tiletype)
{
switch(DFHack::tileTypeTable[tiletype].c)
{
case DFHack::EMPTY:
case DFHack::STAIR_DOWN:
case DFHack::STAIR_UPDOWN:
case DFHack::STAIR_UP:
case DFHack::RAMP:
case DFHack::RAMP_TOP:
case DFHack::FLOOR:
case DFHack::SAPLING_DEAD:
case DFHack::SAPLING_OK:
case DFHack::SHRUB_DEAD:
case DFHack::SHRUB_OK:
case DFHack::BOULDER:
case DFHack::PEBBLES:
return true;
default:
return false;
}
};
inline
bool FlowPassable(uint16_t tiletype)
{
TileClass tc = tileTypeTable[tiletype].c;
return tc != WALL && tc != PILLAR && tc != TREE_DEAD && tc != TREE_OK;
};
inline
bool isWallTerrain(int in)

@ -0,0 +1,342 @@
#ifndef MAPEXTRAS_H
#define MAPEXTRAS_H
#include "../modules/Maps.h"
#include "../DFTileTypes.h"
#include "../DFIntegers.h"
#include <cstring>
namespace MapExtras
{
void SquashVeins (DFHack::Maps *m, DFHack::DFCoord bcoord, DFHack::mapblock40d & mb, DFHack::t_blockmaterials & materials)
{
memset(materials,-1,sizeof(materials));
vector <DFHack::t_vein> veins;
m->ReadVeins(bcoord.x,bcoord.y,bcoord.z,&veins);
//iterate through block rows
for(uint32_t j = 0;j<16;j++)
{
//iterate through columns
for (uint32_t k = 0; k< 16;k++)
{
int16_t tt = mb.tiletypes[k][j];
DFHack::TileMaterial mat = DFHack::tileTypeTable[tt].m;
if(mat == DFHack::VEIN)
{
for(int i = (int) veins.size() - 1; i >= 0;i--)
{
if(!!(((1 << k) & veins[i].assignment[j]) >> k))
{
materials[k][j] = veins[i].type;
i = -1;
}
}
}
}
}
}
class Block
{
public:
Block(DFHack::Maps *_m, DFHack::DFCoord _bcoord)
{
m = _m;
dirty_designations = false;
dirty_tiletypes = false;
dirty_temperatures = false;
dirty_blockflags = false;
valid = false;
bcoord = _bcoord;
if(m->ReadBlock40d(bcoord.x,bcoord.y,bcoord.z,&raw))
{
SquashVeins(m,bcoord,raw,materials);
valid = true;
}
m->ReadTemperatures(bcoord.x,bcoord.y, bcoord.z,&temp1,&temp2);
}
int16_t MaterialAt(DFHack::DFCoord p)
{
return materials[p.x][p.y];
}
void ClearMaterialAt(DFHack::DFCoord p)
{
materials[p.x][p.y] = -1;
}
uint16_t TileTypeAt(DFHack::DFCoord p)
{
return raw.tiletypes[p.x][p.y];
}
bool setTiletypeAt(DFHack::DFCoord p, uint16_t tiletype)
{
if(!valid) return false;
dirty_tiletypes = true;
//printf("setting block %d/%d/%d , %d %d\n",x,y,z, p.x, p.y);
raw.tiletypes[p.x][p.y] = tiletype;
return true;
}
uint16_t temperature1At(DFHack::DFCoord p)
{
return temp1[p.x][p.y];
}
bool setTemp1At(DFHack::DFCoord p, uint16_t temp)
{
if(!valid) return false;
dirty_temperatures = true;
temp1[p.x][p.y] = temp;
return true;
}
uint16_t temperature2At(DFHack::DFCoord p)
{
return temp2[p.x][p.y];
}
bool setTemp2At(DFHack::DFCoord p, uint16_t temp)
{
if(!valid) return false;
dirty_temperatures = true;
temp2[p.x][p.y] = temp;
return true;
}
DFHack::t_designation DesignationAt(DFHack::DFCoord p)
{
return raw.designation[p.x][p.y];
}
bool setDesignationAt(DFHack::DFCoord p, DFHack::t_designation des)
{
if(!valid) return false;
dirty_designations = true;
//printf("setting block %d/%d/%d , %d %d\n",x,y,z, p.x, p.y);
raw.designation[p.x][p.y] = des;
return true;
}
DFHack::t_blockflags BlockFlags()
{
return raw.blockflags;
}
bool setBlockFlags(DFHack::t_blockflags des)
{
if(!valid) return false;
dirty_blockflags = true;
//printf("setting block %d/%d/%d , %d %d\n",x,y,z, p.x, p.y);
raw.blockflags = des;
return true;
}
bool Write ()
{
if(!valid) return false;
if(dirty_designations)
{
m->WriteDesignations(bcoord.x,bcoord.y,bcoord.z, &raw.designation);
m->WriteDirtyBit(bcoord.x,bcoord.y,bcoord.z,true);
dirty_designations = false;
}
if(dirty_tiletypes)
{
m->WriteTileTypes(bcoord.x,bcoord.y,bcoord.z, &raw.tiletypes);
dirty_tiletypes = false;
}
if(dirty_temperatures)
{
m->WriteTemperatures(bcoord.x,bcoord.y,bcoord.z, &temp1, &temp2);
dirty_temperatures = false;
}
if(dirty_blockflags)
{
m->WriteBlockFlags(bcoord.x,bcoord.y,bcoord.z,raw.blockflags);
dirty_blockflags = false;
}
return true;
}
bool valid:1;
bool dirty_designations:1;
bool dirty_tiletypes:1;
bool dirty_temperatures:1;
bool dirty_blockflags:1;
DFHack::Maps * m;
DFHack::mapblock40d raw;
DFHack::DFCoord bcoord;
DFHack::t_blockmaterials materials;
DFHack::t_temperatures temp1;
DFHack::t_temperatures temp2;
};
class MapCache
{
public:
MapCache(DFHack::Maps * Maps)
{
valid = 0;
this->Maps = Maps;
Maps->getSize(x_bmax, y_bmax, z_max);
valid = true;
};
~MapCache()
{
map<DFHack::DFCoord, Block *>::iterator p;
for(p = blocks.begin(); p != blocks.end(); p++)
{
delete p->second;
//cout << stonetypes[p->first].id << " : " << p->second << endl;
}
}
bool isValid ()
{
return valid;
}
/// get the map block at a *block* coord. Block coord = tile coord / 16
Block * BlockAt (DFHack::DFCoord blockcoord)
{
if(!valid)
return 0;
map <DFHack::DFCoord, Block*>::iterator iter = blocks.find(blockcoord);
if(iter != blocks.end())
{
return (*iter).second;
}
else
{
if(blockcoord.x < x_bmax && blockcoord.y < y_bmax && blockcoord.z < z_max)
{
Block * nblo = new Block(Maps,blockcoord);
blocks[blockcoord] = nblo;
return nblo;
}
return 0;
}
}
uint16_t tiletypeAt (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->TileTypeAt(tilecoord % 16);
}
return 0;
}
bool setTiletypeAt(DFHack::DFCoord& tilecoord, uint16_t tiletype)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->setTiletypeAt(tilecoord % 16, tiletype);
return true;
}
return false;
}
uint16_t temperature1At (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->temperature1At(tilecoord % 16);
}
return 0;
}
bool setTemp1At(DFHack::DFCoord& tilecoord, uint16_t temperature)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->setTemp1At(tilecoord % 16, temperature);
return true;
}
return false;
}
uint16_t temperature2At (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->temperature2At(tilecoord % 16);
}
return 0;
}
bool setTemp2At(DFHack::DFCoord& tilecoord, uint16_t temperature)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->setTemp2At(tilecoord % 16, temperature);
return true;
}
return false;
}
int16_t materialAt (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->MaterialAt(tilecoord % 16);
}
return 0;
}
bool clearMaterialAt (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->ClearMaterialAt(tilecoord % 16);
}
return 0;
}
DFHack::t_designation designationAt (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->DesignationAt(tilecoord % 16);
}
DFHack:: t_designation temp;
temp.whole = 0;
return temp;
}
bool setDesignationAt (DFHack::DFCoord tilecoord, DFHack::t_designation des)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->setDesignationAt(tilecoord % 16, des);
return true;
}
return false;
}
bool testCoord (DFHack::DFCoord tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return true;
}
return false;
}
bool WriteAll()
{
map<DFHack::DFCoord, Block *>::iterator p;
for(p = blocks.begin(); p != blocks.end(); p++)
{
p->second->Write();
}
return true;
}
private:
volatile bool valid;
uint32_t x_bmax;
uint32_t y_bmax;
uint32_t x_tmax;
uint32_t y_tmax;
uint32_t z_max;
DFHack::Maps * Maps;
map<DFHack::DFCoord, Block *> blocks;
};
}
#endif

@ -23,21 +23,59 @@ namespace DFHack
};
extern DFHACK_EXPORT const char * sa_feature(int index);
/// used as a key for the local feature map. combines X an Y coords.
union planecoord
class DFCoord
{
uint32_t xy;
struct
public:
DFCoord(uint16_t _x, uint16_t _y, uint16_t _z = 0): x(_x), y(_y), z(_z) {}
DFCoord()
{
uint16_t x;
uint16_t y;
} dim;
bool operator<(const planecoord &other) const
comparate = 0;
}
bool operator==(const DFCoord &other) const
{
return (other.comparate == comparate);
}
// FIXME: <tomprince> peterix_: you could probably get away with not defining operator< if you defined a std::less specialization for Vertex.
bool operator<(const DFCoord &other) const
{
return comparate < other.comparate;
}
DFCoord operator/(int number) const
{
return DFCoord(x/number, y/number, z);
}
DFCoord operator*(int number) const
{
if(other.xy < xy) return true;
return false;
return DFCoord(x*number, y*number, z);
}
DFCoord operator%(int number) const
{
return DFCoord(x%number, y%number, z);
}
DFCoord operator-(int number) const
{
return DFCoord(x,y,z-number);
}
DFCoord operator+(int number) const
{
return DFCoord(x,y,z+number);
}
// this is a clever hack. beware.
// x,y,z share the same space with comparate. comparate can be used for fast comparisons
union
{
#pragma pack(push) /* push current alignment to stack */
#pragma pack(2) /* set alignment to 2 byte boundary */
struct
{
uint16_t x;
uint16_t y;
uint32_t z;
};
#pragma pack (pop) /* restore alignment */
uint64_t comparate;
};
};
struct t_feature
@ -217,6 +255,7 @@ namespace DFHack
};
// occupancy flags (rat,dwarf,horse,built wall,not build wall,etc)
//FIXME: THIS IS NOT VALID FOR 31.xx versions!!!!
struct naked_occupancy
{
// building type... should be an enum?
@ -296,6 +335,7 @@ namespace DFHack
};
typedef int16_t tiletypes40d [16][16];
typedef int16_t t_blockmaterials [16][16]; ///< used for squashed block materials
typedef DFHack::t_designation designations40d [16][16];
typedef DFHack::t_occupancy occupancies40d [16][16];
typedef uint8_t biome_indices40d [16];
@ -373,7 +413,7 @@ namespace DFHack
// map between mangled coords and pointer to feature
bool ReadGlobalFeatures( std::vector <t_feature> & features);
bool ReadLocalFeatures( std::map <planecoord, std::vector<t_feature *> > & local_features );
bool ReadLocalFeatures( std::map <DFCoord, std::vector<t_feature *> > & local_features );
/*
* BLOCK DATA
*/

@ -635,6 +635,7 @@ bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector <t_vein>* veins,
// read all veins
for (uint32_t i = 0; i < size;i++)
{
retry:
// read the vein pointer from the vector
uint32_t temp = p_veins[i];
uint32_t type = p->readDWord(temp);
@ -681,26 +682,32 @@ bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector <t_vein>* veins,
else
{
string cname = p->readClassName(type);
if(cname == "block_square_event_frozen_liquidst")
if(!off.vein_ice_vptr && cname == "block_square_event_frozen_liquidst")
{
off.vein_ice_vptr = type;
goto retry;
}
else if(cname == "block_square_event_mineralst")
else if(!off.vein_mineral_vptr &&cname == "block_square_event_mineralst")
{
off.vein_mineral_vptr = type;
goto retry;
}
else if(cname == "block_square_event_material_spatterst")
else if(!off.vein_spatter_vptr && cname == "block_square_event_material_spatterst")
{
off.vein_spatter_vptr = type;
goto retry;
}
else if(cname=="block_square_event_grassst")
else if(!off.vein_grass_vptr && cname=="block_square_event_grassst")
{
off.vein_grass_vptr = type;
goto retry;
}
else if(cname=="block_square_event_world_constructionst")
else if(!off.vein_worldconstruction_vptr && cname=="block_square_event_world_constructionst")
{
off.vein_worldconstruction_vptr = type;
goto retry;
}
#ifdef DEBUG
else // this is something we've never seen before
{
if(!d->unknown_veins.count(type))
@ -709,6 +716,7 @@ bool Maps::ReadVeins(uint32_t x, uint32_t y, uint32_t z, vector <t_vein>* veins,
d->unknown_veins.insert(type);
}
}
#endif
}
}
return true;
@ -854,7 +862,7 @@ bool Maps::ReadGeology (vector < vector <uint16_t> >& assign)
return true;
}
bool Maps::ReadLocalFeatures( std::map <planecoord, std::vector<t_feature *> > & local_features )
bool Maps::ReadLocalFeatures( std::map <DFCoord, std::vector<t_feature *> > & local_features )
{
MAPS_GUARD
if(!d->hasFeatures) return false;
@ -905,9 +913,7 @@ bool Maps::ReadLocalFeatures( std::map <planecoord, std::vector<t_feature *> > &
uint32_t feat_vector = wtf + sizeof_vec * (16 * (region_x_local % 16) + (region_y_local % 16));
DfVector<uint32_t> p_features(p, feat_vector);
uint32_t size = p_features.size();
planecoord pc;
pc.dim.x = blockX;
pc.dim.y = blockY;
DFCoord pc(blockX,blockY);
std::vector<t_feature *> tempvec;
for(uint32_t i = 0; i < size; i++)
{

@ -320,8 +320,8 @@ void settileat(unsigned char pattern[16][16], const unsigned char needle, const
//Is a given feature present at the given tile?
int isfeature(
vector<DFHack::t_feature> global_features,
std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features,
const mapblock40d &block, const planecoord &pc, const int x, const int y, const e_feature Feat
std::map <DFHack::DFCoord, std::vector<DFHack::t_feature *> > local_features,
const mapblock40d &block, const DFCoord &pc, const int x, const int y, const e_feature Feat
)
{
//const TileRow * tp;
@ -681,7 +681,7 @@ int main (void)
return 1;
}
std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features;
std::map <DFHack::DFCoord, std::vector<DFHack::t_feature *> > local_features;
if (!Mapz->ReadLocalFeatures(local_features))
{
cout << "Couldn't load local features! Probably a version problem." << endl;
@ -695,9 +695,7 @@ int main (void)
mapblock40d topblock;
Mapz->ReadBlock40d( bx, by, bz , &topblock );
//Related block info
planecoord pc;
pc.dim.x=bx;
pc.dim.y=by;
DFCoord pc(bx,by);
mapblock40d block;
const TileRow * tp;
t_designation * d;

@ -7,7 +7,128 @@
using namespace std;
#include <DFHack.h>
#include <dfhack/DFTileTypes.h>
#include <dfhack/extra/MapExtras.h>
#include <set>
using namespace MapExtras;
typedef vector <DFHack::DFCoord> coord_vec;
class Brush
{
public:
virtual ~Brush(){};
virtual coord_vec points(MapCache & mc,DFHack::DFCoord start) = 0;
};
/**
* generic 2D rectangle brush. you can specify the dimensions of
* the rectangle and optionally which tile is its 'center'
*/
class RectangleBrush : public Brush
{
public:
RectangleBrush(int x, int y, int z = 1, int centerx = -1, int centery = -1, int centerz = -1)
{
if(centerx == -1)
cx_ = x/2;
else
cx_ = centerx;
if(centery == -1)
cy_ = y/2;
else
cy_ = centery;
if(centerz == -1)
cz_ = y/2;
else
cz_ = centerz;
x_ = x;
y_ = y;
z_ = z;
};
coord_vec points(MapCache & mc, DFHack::DFCoord start)
{
coord_vec v;
DFHack::DFCoord iterstart(start.x - cx_, start.y - cy_, start.z - cz_);
DFHack::DFCoord iter = iterstart;
for(int xi = 0; xi < x_; xi++)
{
for(int yi = 0; yi < y_; yi++)
{
for(int zi = 0; zi < z_; zi++)
{
if(mc.testCoord(iter))
v.push_back(iter);
iter.z++;
}
iter.z = iterstart.z;
iter.y++;
}
iter.y = iterstart.y;
iter.x ++;
}
return v;
};
~RectangleBrush(){};
private:
int x_, y_, z_;
int cx_, cy_, cz_;
};
/**
* stupid block brush, legacy. use when you want to apply something to a whole DF map block.
*/
class BlockBrush : public Brush
{
public:
BlockBrush(){};
~BlockBrush(){};
coord_vec points(MapCache & mc, DFHack::DFCoord start)
{
coord_vec v;
DFHack::DFCoord blockc = start % 16;
DFHack::DFCoord iterc = blockc * 16;
if( !mc.testCoord(start) )
return v;
for(int xi = 0; xi < 16; xi++)
{
for(int yi = 0; yi < 16; yi++)
{
v.push_back(iterc);
iterc.y++;
}
iterc.x ++;
}
return v;
};
};
/**
* Column from a position through open space tiles
* example: create a column of magma
*/
class ColumnBrush : public Brush
{
public:
ColumnBrush(){};
~ColumnBrush(){};
coord_vec points(MapCache & mc, DFHack::DFCoord start)
{
coord_vec v;
bool juststarted = true;
while (mc.testCoord(start))
{
uint16_t tt = mc.tiletypeAt(start);
if(DFHack::LowPassable(tt) || juststarted && DFHack::HighPassable(tt))
{
v.push_back(start);
juststarted = false;
start.z++;
}
else break;
}
return v;
};
};
int main (int argc, char** argv)
{
@ -21,15 +142,18 @@ int main (int argc, char** argv)
}
}
int32_t x,y,z;
/*
DFHack::designations40d designations;
DFHack::tiletypes40d tiles;
DFHack::t_temperatures temp1,temp2;
*/
uint32_t x_max,y_max,z_max;
DFHack::ContextManager DFMgr("Memory.xml");
DFHack::Context *DF;
DFHack::Maps * Maps;
DFHack::Position * Position;
Brush * brush = new RectangleBrush(1,1);
try
{
DF=DFMgr.getSingleContext();
@ -50,12 +174,11 @@ int main (int argc, char** argv)
bool end = false;
cout << "Welcome to the liquid spawner. type 'help' for a list of available commands, 'q' to quit." << endl;
string mode="magma";
string brush="point";
string flowmode="f+";
string setmode ="s.";
int amount = 7;
int width = 1;
int height = 1;
int width = 1, height = 1, z_levels = 1;
while(!end)
{
DF->Resume();
@ -68,6 +191,8 @@ int main (int argc, char** argv)
<< "m - switch to magma" << endl
<< "w - switch to water" << endl
<< "o - make obsidian wall instead" << endl
<< "of - make obsidian floors" << endl
<< "rs - make a river source" << endl
<< "f - flow bits only" << endl
<< "Set-Modes:" << endl
<< "s+ - only add" << endl
@ -80,8 +205,9 @@ int main (int argc, char** argv)
<< "0-7 - set liquid amount" << endl
<< "Brush:" << endl
<< "point - single tile [p]" << endl
<< "range - rectangle with cursor at top left [r]" << endl
<< "block - block with cursor in it" << endl
<< "range - block with cursor at bottom north-west [r]" << endl
<< "block - DF map block with cursor in it" << endl
<< "column - Column up through free space" << endl
<< "Other:" << endl
<< "q - quit" << endl
<< "help - print this list of commands" << endl
@ -98,17 +224,9 @@ int main (int argc, char** argv)
{
mode = "obsidian";
}
else if(command == "clmn")
else if(command == "of")
{
mode = "column";
}
else if(command == "starruby")
{
mode = "starruby";
}
else if(command == "darkhide")
{
mode = "darkhide";
mode = "obsidian_floor";
}
else if(command == "w")
{
@ -118,9 +236,14 @@ int main (int argc, char** argv)
{
mode = "flowbits";
}
else if(command == "rs")
{
mode = "riversource";
}
else if(command == "point" || command == "p")
{
brush = "point";
delete brush;
brush = new RectangleBrush(1,1);
}
else if(command == "range" || command == "r")
{
@ -128,15 +251,28 @@ int main (int argc, char** argv)
getline(cin, command);
width = command == "" ? width : atoi (command.c_str());
if(width < 1) width = 1;
cout << " :set range height<" << height << "># ";
getline(cin, command);
height = command == "" ? height : atoi (command.c_str());
if(height < 1) height = 1;
brush = "range";
cout << " :set range z-levels<" << z_levels << "># ";
getline(cin, command);
z_levels = command == "" ? z_levels : atoi (command.c_str());
if(z_levels < 1) z_levels = 1;
delete brush;
brush = new RectangleBrush(width,height,z_levels,0,0,0);
}
else if(command == "block")
{
brush = "block";
delete brush;
brush = new BlockBrush();
}
else if(command == "column")
{
delete brush;
brush = new ColumnBrush();
}
else if(command == "q")
{
@ -199,273 +335,134 @@ int main (int argc, char** argv)
break;
}
cout << "cursor coords: " << x << "/" << y << "/" << z << endl;
if(!Maps->isValidBlock(x/16,y/16,z))
{
cout << "Not a valid block." << endl;
break;
}
MapCache mcache(Maps);
cout << "getting tiles from brush" << endl;
DFHack::DFCoord cursor(x,y,z);
coord_vec all_tiles = brush->points(mcache,cursor);
cout << "doing things" << endl;
if(mode == "obsidian")
{
Maps->ReadTileTypes((x/16),(y/16),z, &tiles);
tiles[x%16][y%16] = 331;
Maps->WriteTileTypes((x/16),(y/16),z, &tiles);
}
else if(mode == "column")
{
int zzz = z;
int16_t tile;
while ( zzz < z_max )
coord_vec::iterator iter = all_tiles.begin();
while (iter != all_tiles.end())
{
Maps->ReadTileTypes((x/16),(y/16),zzz, &tiles);
tile = tiles[x%16][y%16];
if (DFHack::tileTypeTable[tile].c == DFHack::WALL)
break;
tiles[x%16][y%16] = 331;
Maps->WriteTileTypes((x/16),(y/16),zzz, &tiles);
zzz++;
}
mcache.setTiletypeAt(*iter, 331);
iter ++;
}
}
// quick hack, do not use for serious stuff
/*
else if(mode == "starruby")
if(mode == "obsidian_floor")
{
if(Maps->isValidBlock((x/16),(y/16),z))
coord_vec::iterator iter = all_tiles.begin();
while (iter != all_tiles.end())
{
Maps->ReadTileTypes((x/16),(y/16),z, &tiles);
Maps->ReadDesignations((x/16),(y/16),z, &designations);
Maps->ReadTemperatures((x/16),(y/16),z, &temp1, &temp2);
cout << "sizeof(designations) = " << sizeof(designations) << endl;
cout << "sizeof(tiletypes) = " << sizeof(tiles) << endl;
for(uint32_t xx = 0; xx < 16; xx++) for(uint32_t yy = 0; yy < 16; yy++)
{
cout<< xx << " " << yy <<": " << tiles[xx][yy] << endl;
tiles[xx][yy] = 335;// 45
DFHack::naked_designation & des = designations[xx][yy].bits;
des.feature_local = true;
des.feature_global = false;
des.flow_size = 0;
des.skyview = 0;
des.light = 0;
des.subterranean = 1;
temp1[xx][yy] = 10015;
temp2[xx][yy] = 10015;
}
Maps->WriteTemperatures((x/16),(y/16),z, &temp1, &temp2);
Maps->WriteDesignations((x/16),(y/16),z, &designations);
Maps->WriteTileTypes((x/16),(y/16),z, &tiles);
Maps->WriteLocalFeature((x/16),(y/16),z, 36);
mcache.setTiletypeAt(*iter, 340);
iter ++;
}
}
else if(mode == "darkhide")
else if(mode == "riversource")
{
int16_t zzz = z;
while ( zzz >=0 )
set <Block *> seen_blocks;
coord_vec::iterator iter = all_tiles.begin();
while (iter != all_tiles.end())
{
if(Maps->isValidBlock((x/16),(y/16),zzz))
{
int xx = x %16;
int yy = y %16;
Maps->ReadDesignations((x/16),(y/16),zzz, &designations);
designations[xx][yy].bits.skyview = 0;
designations[xx][yy].bits.light = 0;
designations[xx][yy].bits.subterranean = 1;
Maps->WriteDesignations((x/16),(y/16),zzz, &designations);
}
zzz --;
mcache.setTiletypeAt(*iter, 90);
DFHack::t_designation a = mcache.designationAt(*iter);
a.bits.liquid_type = DFHack::liquid_water;
a.bits.liquid_static = false;
a.bits.flow_size = 7;
mcache.setDesignationAt(*iter,a);
Block * b = mcache.BlockAt((*iter)/16);
DFHack::t_blockflags bf = b->BlockFlags();
bf.bits.liquid_1 = true;
bf.bits.liquid_2 = true;
b->setBlockFlags(bf);
iter++;
}
}
*/
else
else if(mode== "magma" || mode== "water" || mode == "flowbits")
{
// place the magma
if(brush != "range")
set <Block *> seen_blocks;
coord_vec::iterator iter = all_tiles.begin();
while (iter != all_tiles.end())
{
Maps->ReadDesignations((x/16),(y/16),z, &designations);
Maps->ReadTemperatures((x/16),(y/16),z, &temp1, &temp2);
if(brush == "point")
DFHack::DFCoord current = *iter;
DFHack::t_designation des = mcache.designationAt(current);
uint16_t tt = mcache.tiletypeAt(current);
DFHack::naked_designation & flow = des.bits;
if(mode != "flowbits")
{
if(mode != "flowbits")
if(!DFHack::FlowPassable(tt))
{
iter++;
continue;
}
// if we are setting the levels to 0 or changing magma into water
if(amount == 0 || des.bits.liquid_type == DFHack::liquid_magma && mode == "water")
{
// reset temperature to sane default
mcache.setTemp1At(current,10015);
mcache.setTemp2At(current,10015);
}
if(setmode == "s.")
{
// fix temperatures so we don't produce lethal heat traps
if(amount == 0 || designations[x%16][y%16].bits.liquid_type == DFHack::liquid_magma && mode == "water")
temp1[x%16][y%16] = temp2[x%16][y%16] = 10015;
DFHack::naked_designation & flow = designations[x%16][y%16].bits;
if(setmode == "s.")
{
flow.flow_size = amount;
}
else if(setmode == "s+")
{
if(flow.flow_size < amount)
flow.flow_size = amount;
}
else if(setmode == "s+")
{
if(flow.flow_size < amount)
flow.flow_size = amount;
}
else if(setmode == "s-")
{
if (flow.flow_size > amount)
flow.flow_size = amount;
}
}
if(mode == "magma")
designations[x%16][y%16].bits.liquid_type = DFHack::liquid_magma;
else if(mode == "water")
designations[x%16][y%16].bits.liquid_type = DFHack::liquid_water;
}
else
{
for(uint32_t xx = 0; xx < 16; xx++) for(uint32_t yy = 0; yy < 16; yy++)
else if(setmode == "s-")
{
if(mode != "flowbits")
{
// fix temperatures so we don't produce lethal heat traps
if(amount == 0 || designations[xx][yy].bits.liquid_type == DFHack::liquid_magma && mode == "water")
temp1[xx%16][yy%16] = temp2[xx%16][yy%16] = 10015;
DFHack::naked_designation & flow= designations[xx][yy].bits;
if(setmode == "s.")
{
flow.flow_size = amount;
}
else if(setmode == "s+")
{
if(flow.flow_size < amount)
flow.flow_size = amount;
}
else if(setmode == "s-")
{
if (flow.flow_size > amount)
flow.flow_size = amount;
}
}
if(mode == "magma")
designations[xx][yy].bits.liquid_type = DFHack::liquid_magma;
else if(mode == "water")
designations[xx][yy].bits.liquid_type = DFHack::liquid_water;
if (flow.flow_size > amount)
flow.flow_size = amount;
}
if(mode == "magma")
flow.liquid_type = DFHack::liquid_magma;
else if(mode == "water")
flow.liquid_type = DFHack::liquid_water;
mcache.setDesignationAt(current,des);
}
Maps->WriteTemperatures((x/16),(y/16),z, &temp1, &temp2);
Maps->WriteDesignations(x/16,y/16,z, &designations);
// make the magma flow :)
DFHack::t_blockflags bflags;
Maps->ReadBlockFlags((x/16),(y/16),z,bflags);
// 0x00000001 = job-designated
// 0x0000000C = run flows? - both bit 3 and 4 required for making magma placed on a glacier flow
seen_blocks.insert(mcache.BlockAt((*iter) / 16));
iter++;
}
set <Block *>::iterator biter = seen_blocks.begin();
while (biter != seen_blocks.end())
{
DFHack::t_blockflags bflags = (*biter)->BlockFlags();
if(flowmode == "f+")
{
bflags.bits.liquid_1 = true;
bflags.bits.liquid_2 = true;
(*biter)->setBlockFlags(bflags);
}
else if(flowmode == "f-")
{
bflags.bits.liquid_1 = false;
bflags.bits.liquid_2 = false;
(*biter)->setBlockFlags(bflags);
}
else
{
cout << "flow bit 1 = " << bflags.bits.liquid_1 << endl;
cout << "flow bit 2 = " << bflags.bits.liquid_2 << endl;
}
Maps->WriteBlockFlags((x/16),(y/16),z,bflags);
biter ++;
}
else if (brush == "range")
{
// Crop the range into each block if necessary
int beginxblock = x/16;
int endxblock = (x+width)/16;
int beginyblock = y/16;
int endyblock = (y+height)/16;
for(uint32_t bx = beginxblock; bx < endxblock+1; bx++) for(uint32_t by = beginyblock; by < endyblock+1; by++)
{
if(Maps->isValidBlock(bx,by,z))
{
Maps->ReadDesignations(bx,by,z, &designations);
Maps->ReadTemperatures(bx,by,z, &temp1, &temp2);
// Take original range and crop it into current block
int nx = x;
int ny = y;
int nwidth = width;
int nheight = height;
if(x/16 < bx) //Start point is left of block
{
nx = bx*16;
nwidth -= nx - x;
}
if (nx/16 < (nx+nwidth-1)/16)// End point is right of block
{
nwidth = (bx*16)+16-nx;
}
if(y/16 < by) //Start point is above block
{
ny = by*16;
nheight -= ny - y;
}
if (ny/16 < (ny+nheight-1)/16) // End point is below block
{
nheight = (by*16)+16-ny;
}
cout << " Block:" << bx << "," << by << ":" << endl;
cout << " Start:" << nx << "," << ny << ":" << endl;
cout << " Area: " << nwidth << "," << nheight << ":" << endl;
for(uint32_t xx = nx; xx < nx+nwidth; xx++) for(uint32_t yy = ny; yy < ny+nheight; yy++)
{
if(mode != "flowbits")
{
// fix temperatures so we don't produce lethal heat traps
if(amount == 0 || designations[xx%16][yy%16].bits.liquid_type == DFHack::liquid_magma && mode == "water")
temp1[xx%16][yy%16] = temp2[xx%16][yy%16] = 10015;
DFHack::naked_designation & flow= designations[xx%16][yy%16].bits;
if(setmode == "s.")
{
flow.flow_size = amount;
}
else if(setmode == "s+")
{
if(flow.flow_size < amount)
flow.flow_size = amount;
}
else if(setmode == "s-")
{
if (flow.flow_size > amount)
flow.flow_size = amount;
}
}
if(mode == "magma")
designations[xx%16][yy%16].bits.liquid_type = DFHack::liquid_magma;
else if(mode == "water")
designations[xx%16][yy%16].bits.liquid_type = DFHack::liquid_water;
}
Maps->WriteTemperatures(bx,by,z, &temp1, &temp2);
Maps->WriteDesignations(bx,by,z, &designations);
// make the magma flow :)
DFHack::t_blockflags bflags;
Maps->ReadBlockFlags(bx,by,z,bflags);
// 0x00000001 = job-designated
// 0x0000000C = run flows? - both bit 3 and 4 required for making magma placed on a glacier flow
if(flowmode == "f+")
{
bflags.bits.liquid_1 = true;
bflags.bits.liquid_2 = true;
}
else if(flowmode == "f-")
{
bflags.bits.liquid_1 = false;
bflags.bits.liquid_2 = false;
}
else
{
cout << "flow bit 1 = " << bflags.bits.liquid_1 << endl;
cout << "flow bit 2 = " << bflags.bits.liquid_2 << endl;
}
Maps->WriteBlockFlags(bx,by,z,bflags);
}
}
}
}
cout << "OK" << endl;
if(mcache.WriteAll())
cout << "OK" << endl;
else
cout << "Something failed horribly! RUN!" << endl;
Maps->Finish();
} while (0);
}
else
{
cout << command << " : unknown command." << endl;
}
}
DF->Detach();
#ifndef LINUX_BUILD

@ -59,7 +59,7 @@ int main (int numargs, const char ** args)
Maps->Start();
vector<DFHack::t_feature> global_features;
std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features;
std::map <DFHack::DFCoord, std::vector<DFHack::t_feature *> > local_features;
bool have_local = Maps->ReadLocalFeatures(local_features);
bool have_global = Maps->ReadGlobalFeatures(global_features);
@ -133,9 +133,7 @@ int main (int numargs, const char ** args)
PRINT_FLAG( water_table );
PRINT_FLAG( rained );
planecoord pc;
pc.dim.x=blockX; pc.dim.y=blockY;
DFCoord pc(blockX, blockY);
PRINT_FLAG( feature_local );
if( des.feature_local && have_local )

@ -74,7 +74,7 @@ int main (int argc, const char* argv[])
map <int16_t, uint32_t> materials;
materials.clear();
vector<DFHack::t_feature> global_features;
std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features;
std::map <DFHack::DFCoord, std::vector<DFHack::t_feature *> > local_features;
vector< vector <uint16_t> > layerassign;
@ -236,15 +236,14 @@ int main (int argc, const char* argv[])
idx = Block.local_feature;
if( idx != -1 )
{
DFHack::planecoord pc;
pc.dim.x = x;
pc.dim.y = y;
std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> >::iterator it;
DFHack::DFCoord pc(x,y);
std::map <DFHack::DFCoord, std::vector<DFHack::t_feature *> >::iterator it;
it = local_features.find(pc);
if(it != local_features.end())
{
std::vector<DFHack::t_feature *>& vectr = (*it).second;
if(uint16_t(idx) < vectr.size() && vectr[idx]->type == DFHack::feature_Adamantine_Tube)
{
for(uint32_t xi = 0 ; xi< 16 ; xi++) for(uint32_t yi = 0 ; yi< 16 ; yi++)
{
if(Block.designation[xi][yi].bits.feature_local && DFHack::isWallTerrain(Block.tiletypes[xi][yi]))
@ -259,6 +258,7 @@ int main (int argc, const char* argv[])
}
}
}
}
}
}

@ -9,264 +9,10 @@
using namespace std;
#include <DFHack.h>
#include <dfhack/DFTileTypes.h>
#include <dfhack/extra/MapExtras.h>
using namespace MapExtras;
//#include <argstream.h>
#define MAX_DIM 0x300
//TODO: turn into the official coord class for DFHack/DF
class Vertex
{
public:
Vertex(uint32_t _x, uint32_t _y, uint32_t _z):x(_x),y(_y),z(_z) {}
Vertex()
{
x = y = z = 0;
}
bool operator==(const Vertex &other) const
{
return (other.x == x && other.y == y && other.z == z);
}
// FIXME: <tomprince> peterix_: you could probably get away with not defining operator< if you defined a std::less specialization for Vertex.
bool operator<(const Vertex &other) const
{
// FIXME: could be changed to eliminate MAX_DIM and make std::map lookups faster?
return ( (z*MAX_DIM*MAX_DIM + y*MAX_DIM + x) < (other.z*MAX_DIM*MAX_DIM + other.y*MAX_DIM + other.x));
}
Vertex operator/(int number) const
{
return Vertex(x/number, y/number, z);
}
Vertex operator%(int number) const
{
return Vertex(x%number, y%number, z);
}
Vertex operator-(int number) const
{
return Vertex(x,y,z-number);
}
Vertex operator+(int number) const
{
return Vertex(x,y,z+number);
}
uint32_t x;
uint32_t y;
uint32_t z;
};
class Block
{
public:
Block(DFHack::Maps *_m, Vertex _bcoord)
{
vector <DFHack::t_vein> veins;
m = _m;
dirty = false;
valid = false;
bcoord = _bcoord;
if(m->ReadBlock40d(bcoord.x,bcoord.y,bcoord.z,&raw))
{
memset(materials,-1,sizeof(materials));
memset(bitmap,0,sizeof(bitmap));
m->ReadVeins(bcoord.x,bcoord.y,bcoord.z,&veins);
// for each vein
for(int i = 0; i < (int)veins.size();i++)
{
//iterate through vein rows
for(uint32_t j = 0;j<16;j++)
{
//iterate through the bits
for (uint32_t k = 0; k< 16;k++)
{
// check if it's really a vein (FIXME: doing this too many times)
int16_t tt = raw.tiletypes[k][j];
if(DFHack::isWallTerrain(tt) && DFHack::tileTypeTable[tt].m == DFHack::VEIN)
{
// and the bit array with a one-bit mask, check if the bit is set
bool set = !!(((1 << k) & veins[i].assignment[j]) >> k);
if(set)
{
// store matgloss
materials[k][j] = veins[i].type;
}
}
}
}
}
valid = true;
}
}
int16_t MaterialAt(Vertex p)
{
return materials[p.x][p.y];
}
void ClearMaterialAt(Vertex p)
{
materials[p.x][p.y] = -1;
}
int16_t TileTypeAt(Vertex p)
{
return raw.tiletypes[p.x][p.y];
}
DFHack::t_designation DesignationAt(Vertex p)
{
return raw.designation[p.x][p.y];
}
bool setDesignationAt(Vertex p, DFHack::t_designation des)
{
if(!valid) return false;
dirty = true;
//printf("setting block %d/%d/%d , %d %d\n",x,y,z, p.x, p.y);
raw.designation[p.x][p.y] = des;
return true;
}
bool WriteDesignations ()
{
if(!valid) return false;
if(dirty)
{
//printf("writing %d/%d/%d\n",x,y,z);
m->WriteDesignations(bcoord.x,bcoord.y,bcoord.z, &raw.designation);
m->WriteDirtyBit(bcoord.x,bcoord.y,bcoord.z,true);
}
return true;
}
volatile bool valid;
volatile bool dirty;
DFHack::Maps * m;
DFHack::mapblock40d raw;
Vertex bcoord;
int16_t materials[16][16];
int8_t bitmap[16][16];
};
class MapCache
{
public:
MapCache(DFHack::Maps * Maps)
{
valid = 0;
this->Maps = Maps;
Maps->getSize(x_bmax, y_bmax, z_max);
valid = true;
};
~MapCache()
{
map<Vertex, Block *>::iterator p;
for(p = blocks.begin(); p != blocks.end(); p++)
{
delete p->second;
//cout << stonetypes[p->first].id << " : " << p->second << endl;
}
}
bool isValid ()
{
return valid;
}
Block * BlockAt (Vertex blockcoord)
{
if(!valid) return 0;
map <Vertex, Block*>::iterator iter = blocks.find(blockcoord);
if(iter != blocks.end())
{
return (*iter).second;
}
else
{
if(blockcoord.x < x_bmax && blockcoord.y < y_bmax && blockcoord.z < z_max)
{
Block * nblo = new Block(Maps,blockcoord);
blocks[blockcoord] = nblo;
return nblo;
}
return 0;
}
}
uint16_t tiletypeAt (Vertex tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->TileTypeAt(tilecoord % 16);
}
return 0;
}
int16_t materialAt (Vertex tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->MaterialAt(tilecoord % 16);
}
return 0;
}
bool clearMaterialAt (Vertex tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->ClearMaterialAt(tilecoord % 16);
}
return 0;
}
DFHack::t_designation designationAt (Vertex tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return b->DesignationAt(tilecoord % 16);
}
DFHack:: t_designation temp;
temp.whole = 0;
return temp;
}
bool setDesignationAt (Vertex tilecoord, DFHack::t_designation des)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
b->setDesignationAt(tilecoord % 16, des);
return true;
}
return false;
}
bool testCoord (Vertex tilecoord)
{
Block * b= BlockAt(tilecoord / 16);
if(b && b->valid)
{
return true;
}
return false;
}
bool WriteAll()
{
map<Vertex, Block *>::iterator p;
for(p = blocks.begin(); p != blocks.end(); p++)
{
p->second->WriteDesignations();
//cout << stonetypes[p->first].id << " : " << p->second << endl;
}
return true;
}
private:
volatile bool valid;
uint32_t x_bmax;
uint32_t y_bmax;
uint32_t x_tmax;
uint32_t y_tmax;
uint32_t z_max;
DFHack::Maps * Maps;
map<Vertex, Block *> blocks;
};
int main (int argc, char* argv[])
{
// Command line options
@ -333,7 +79,7 @@ int main (int argc, char* argv[])
DF->Suspend();
Pos->getCursorCoords(cx,cy,cz);
}
Vertex xy ((uint32_t)cx,(uint32_t)cy,cz);
DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1)
{
cerr << "I won't dig the borders. That would be cheating!" << endl;
@ -344,12 +90,11 @@ int main (int argc, char* argv[])
return 1;
}
MapCache * MCache = new MapCache(Maps);
DFHack::t_designation des = MCache->designationAt(xy);
int16_t tt = MCache->tiletypeAt(xy);
int16_t veinmat = MCache->materialAt(xy);
if( veinmat == -1 )
{
cerr << "This tile is non-vein. Bye :)" << endl;
@ -361,21 +106,22 @@ int main (int argc, char* argv[])
return 1;
}
printf("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole);
stack <Vertex> flood;
stack <DFHack::DFCoord> flood;
flood.push(xy);
while( !flood.empty() )
{
Vertex current = flood.top();
while( !flood.empty() )
{
DFHack::DFCoord current = flood.top();
flood.pop();
int16_t vmat2 = MCache->materialAt(current);
tt = MCache->tiletypeAt(current);
if(!DFHack::isWallTerrain(tt))
continue;
if(vmat2!=veinmat)
continue;
// found a good tile, dig+unset material
DFHack::t_designation des = MCache->designationAt(current);
DFHack::t_designation des_minus;
DFHack::t_designation des_plus;
@ -392,7 +138,7 @@ int main (int argc, char* argv[])
des_minus = MCache->designationAt(current-1);
vmat_minus = MCache->materialAt(current-1);
}
if(MCache->testCoord(current+1))
{
above = 1;
@ -405,30 +151,30 @@ int main (int argc, char* argv[])
MCache->clearMaterialAt(current);
if(current.x < tx_max - 2)
{
flood.push(Vertex(current.x + 1, current.y, current.z));
flood.push(DFHack::DFCoord(current.x + 1, current.y, current.z));
if(current.y < ty_max - 2)
{
flood.push(Vertex(current.x + 1, current.y + 1,current.z));
flood.push(Vertex(current.x, current.y + 1,current.z));
flood.push(DFHack::DFCoord(current.x + 1, current.y + 1,current.z));
flood.push(DFHack::DFCoord(current.x, current.y + 1,current.z));
}
if(current.y > 1)
{
flood.push(Vertex(current.x + 1, current.y - 1,current.z));
flood.push(Vertex(current.x, current.y - 1,current.z));
flood.push(DFHack::DFCoord(current.x + 1, current.y - 1,current.z));
flood.push(DFHack::DFCoord(current.x, current.y - 1,current.z));
}
}
if(current.x > 1)
{
flood.push(Vertex(current.x - 1, current.y,current.z));
flood.push(DFHack::DFCoord(current.x - 1, current.y,current.z));
if(current.y < ty_max - 2)
{
flood.push(Vertex(current.x - 1, current.y + 1,current.z));
flood.push(Vertex(current.x, current.y + 1,current.z));
flood.push(DFHack::DFCoord(current.x - 1, current.y + 1,current.z));
flood.push(DFHack::DFCoord(current.x, current.y + 1,current.z));
}
if(current.y > 1)
{
flood.push(Vertex(current.x - 1, current.y - 1,current.z));
flood.push(Vertex(current.x, current.y - 1,current.z));
flood.push(DFHack::DFCoord(current.x - 1, current.y - 1,current.z));
flood.push(DFHack::DFCoord(current.x, current.y - 1,current.z));
}
}
if(updown)
@ -436,25 +182,25 @@ int main (int argc, char* argv[])
if(current.z > 0 && below && vmat_minus == vmat2)
{
flood.push(current-1);
if(des_minus.bits.dig == DFHack::designation_d_stair)
des_minus.bits.dig = DFHack::designation_ud_stair;
else
des_minus.bits.dig = DFHack::designation_u_stair;
MCache->setDesignationAt(current-1,des_minus);
des.bits.dig = DFHack::designation_d_stair;
}
if(current.z < z_max - 1 && above && vmat_plus == vmat2)
{
flood.push(current+ 1);
if(des_plus.bits.dig == DFHack::designation_u_stair)
des_plus.bits.dig = DFHack::designation_ud_stair;
else
des_plus.bits.dig = DFHack::designation_d_stair;
MCache->setDesignationAt(current+1,des_plus);
if(des.bits.dig == DFHack::designation_d_stair)
des.bits.dig = DFHack::designation_ud_stair;
else

@ -413,15 +413,13 @@ void do_features(Context* DF, mapblock40d * block, uint32_t blockX, uint32_t blo
if(!Maps)
return;
vector<DFHack::t_feature> global_features;
std::map <DFHack::planecoord, std::vector<DFHack::t_feature *> > local_features;
std::map <DFHack::DFCoord, std::vector<DFHack::t_feature *> > local_features;
if(!Maps->ReadGlobalFeatures(global_features))
return;
if(!Maps->ReadLocalFeatures(local_features))
return;
planecoord pc;
pc.dim.x = blockX;
pc.dim.y = blockY;
DFCoord pc(blockX, blockY);
int16_t idx =block->global_feature;
if(idx != -1)
{