|
|
@ -113,55 +113,72 @@ struct tile_context {
|
|
|
|
df::building* b = NULL;
|
|
|
|
df::building* b = NULL;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static pair<uint32_t, uint32_t> get_building_size(df::building *b) {
|
|
|
|
// the number of different strings we use is very small so we use a string cache
|
|
|
|
return pair<uint32_t, uint32_t>(b->x2 - b->x1 + 1, b->y2 - b->y1 + 1);
|
|
|
|
// to limit the number of memory allocations we make. this significantly speeds
|
|
|
|
}
|
|
|
|
// up processing and allows us to handle very large maps (e.g. 16x16 embarks)
|
|
|
|
|
|
|
|
// without running out of memory.
|
|
|
|
static const char * if_pretty(const tile_context &ctx, const char *c) {
|
|
|
|
// if NULL is passed as the str, the cache is cleared
|
|
|
|
return ctx.pretty ? c : "";
|
|
|
|
static const char * cache(const char *str) {
|
|
|
|
}
|
|
|
|
// this local static assumes that no two blueprints are being generated at
|
|
|
|
|
|
|
|
// the same time, which is currently ensured by the higher-level DFHack
|
|
|
|
static void get_tile_dig(const df::coord &pos, const tile_context &,
|
|
|
|
// command handling code. if this assumption ever becomes untrue, we'll
|
|
|
|
string &str) {
|
|
|
|
// need to protect the cache with thread synchronization primitives.
|
|
|
|
|
|
|
|
static std::set<string> _cache;
|
|
|
|
|
|
|
|
if (!str) {
|
|
|
|
|
|
|
|
_cache.clear();
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return _cache.emplace(str).first->c_str();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char * get_tile_dig(const df::coord &pos, const tile_context &) {
|
|
|
|
df::tiletype *tt = Maps::getTileType(pos);
|
|
|
|
df::tiletype *tt = Maps::getTileType(pos);
|
|
|
|
switch (tileShape(tt ? *tt : tiletype::Void))
|
|
|
|
switch (tileShape(tt ? *tt : tiletype::Void))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
case tiletype_shape::EMPTY:
|
|
|
|
case tiletype_shape::EMPTY:
|
|
|
|
case tiletype_shape::RAMP_TOP:
|
|
|
|
case tiletype_shape::RAMP_TOP:
|
|
|
|
str = "h"; break;
|
|
|
|
return "h";
|
|
|
|
case tiletype_shape::FLOOR:
|
|
|
|
case tiletype_shape::FLOOR:
|
|
|
|
case tiletype_shape::BOULDER:
|
|
|
|
case tiletype_shape::BOULDER:
|
|
|
|
case tiletype_shape::PEBBLES:
|
|
|
|
case tiletype_shape::PEBBLES:
|
|
|
|
case tiletype_shape::BROOK_TOP:
|
|
|
|
case tiletype_shape::BROOK_TOP:
|
|
|
|
str = "d"; break;
|
|
|
|
return "d";
|
|
|
|
case tiletype_shape::FORTIFICATION:
|
|
|
|
case tiletype_shape::FORTIFICATION:
|
|
|
|
str = "F"; break;
|
|
|
|
return "F";
|
|
|
|
case tiletype_shape::STAIR_UP:
|
|
|
|
case tiletype_shape::STAIR_UP:
|
|
|
|
str = "u"; break;
|
|
|
|
return "u";
|
|
|
|
case tiletype_shape::STAIR_DOWN:
|
|
|
|
case tiletype_shape::STAIR_DOWN:
|
|
|
|
str = "j"; break;
|
|
|
|
return "j";
|
|
|
|
case tiletype_shape::STAIR_UPDOWN:
|
|
|
|
case tiletype_shape::STAIR_UPDOWN:
|
|
|
|
str = "i"; break;
|
|
|
|
return "i";
|
|
|
|
case tiletype_shape::RAMP:
|
|
|
|
case tiletype_shape::RAMP:
|
|
|
|
str = "r"; break;
|
|
|
|
return "r";
|
|
|
|
case tiletype_shape::WALL:
|
|
|
|
case tiletype_shape::WALL:
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void do_block_building(const tile_context &ctx, string &str, string s,
|
|
|
|
static pair<uint32_t, uint32_t> get_building_size(df::building *b) {
|
|
|
|
bool at_target_pos, bool *add_size = NULL) {
|
|
|
|
return pair<uint32_t, uint32_t>(b->x2 - b->x1 + 1, b->y2 - b->y1 + 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char * if_pretty(const tile_context &ctx, const char *c) {
|
|
|
|
|
|
|
|
return ctx.pretty ? c : "";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char * do_block_building(const tile_context &ctx, const char *s,
|
|
|
|
|
|
|
|
bool at_target_pos,
|
|
|
|
|
|
|
|
bool *add_size = NULL) {
|
|
|
|
if(!at_target_pos) {
|
|
|
|
if(!at_target_pos) {
|
|
|
|
str = if_pretty(ctx, "`");
|
|
|
|
return if_pretty(ctx, "`");
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
str = s;
|
|
|
|
|
|
|
|
if (add_size)
|
|
|
|
if (add_size)
|
|
|
|
*add_size = true;
|
|
|
|
*add_size = true;
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static string get_bridge_str(df::building *b) {
|
|
|
|
static const char * get_bridge_str(df::building *b) {
|
|
|
|
df::building_bridgest *bridge = virtual_cast<df::building_bridgest>(b);
|
|
|
|
df::building_bridgest *bridge = virtual_cast<df::building_bridgest>(b);
|
|
|
|
if (!bridge)
|
|
|
|
if (!bridge)
|
|
|
|
return "g";
|
|
|
|
return "g";
|
|
|
@ -177,13 +194,13 @@ static string get_bridge_str(df::building *b) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static string get_siege_str(df::building *b) {
|
|
|
|
static const char * get_siege_str(df::building *b) {
|
|
|
|
df::building_siegeenginest *se =
|
|
|
|
df::building_siegeenginest *se =
|
|
|
|
virtual_cast<df::building_siegeenginest>(b);
|
|
|
|
virtual_cast<df::building_siegeenginest>(b);
|
|
|
|
return !se || se->type == df::siegeengine_type::Catapult ? "ic" : "ib";
|
|
|
|
return !se || se->type == df::siegeengine_type::Catapult ? "ic" : "ib";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static string get_workshop_str(df::building *b) {
|
|
|
|
static const char * get_workshop_str(df::building *b) {
|
|
|
|
df::building_workshopst *ws = virtual_cast<df::building_workshopst>(b);
|
|
|
|
df::building_workshopst *ws = virtual_cast<df::building_workshopst>(b);
|
|
|
|
if (!ws)
|
|
|
|
if (!ws)
|
|
|
|
return "~";
|
|
|
|
return "~";
|
|
|
@ -219,7 +236,7 @@ static string get_workshop_str(df::building *b) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static string get_furnace_str(df::building *b) {
|
|
|
|
static const char * get_furnace_str(df::building *b) {
|
|
|
|
df::building_furnacest *furnace = virtual_cast<df::building_furnacest>(b);
|
|
|
|
df::building_furnacest *furnace = virtual_cast<df::building_furnacest>(b);
|
|
|
|
if (!furnace)
|
|
|
|
if (!furnace)
|
|
|
|
return "~";
|
|
|
|
return "~";
|
|
|
@ -238,7 +255,7 @@ static string get_furnace_str(df::building *b) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static string get_construction_str(df::building *b) {
|
|
|
|
static const char * get_construction_str(df::building *b) {
|
|
|
|
df::building_constructionst *cons =
|
|
|
|
df::building_constructionst *cons =
|
|
|
|
virtual_cast<df::building_constructionst>(b);
|
|
|
|
virtual_cast<df::building_constructionst>(b);
|
|
|
|
if (!cons)
|
|
|
|
if (!cons)
|
|
|
@ -288,7 +305,7 @@ static string get_construction_str(df::building *b) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static string get_trap_str(df::building *b) {
|
|
|
|
static const char * get_trap_str(df::building *b) {
|
|
|
|
df::building_trapst *trap = virtual_cast<df::building_trapst>(b);
|
|
|
|
df::building_trapst *trap = virtual_cast<df::building_trapst>(b);
|
|
|
|
if (!trap)
|
|
|
|
if (!trap)
|
|
|
|
return "~";
|
|
|
|
return "~";
|
|
|
@ -322,14 +339,14 @@ static string get_trap_str(df::building *b) {
|
|
|
|
case 500: buf << "a";
|
|
|
|
case 500: buf << "a";
|
|
|
|
case 10000: buf << "a";
|
|
|
|
case 10000: buf << "a";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return buf.str();
|
|
|
|
return cache(buf.str().c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
return "~";
|
|
|
|
return "~";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static string get_screw_pump_str(df::building *b) {
|
|
|
|
static const char * get_screw_pump_str(df::building *b) {
|
|
|
|
df::building_screw_pumpst *sp = virtual_cast<df::building_screw_pumpst>(b);
|
|
|
|
df::building_screw_pumpst *sp = virtual_cast<df::building_screw_pumpst>(b);
|
|
|
|
if (!sp)
|
|
|
|
if (!sp)
|
|
|
|
return "~";
|
|
|
|
return "~";
|
|
|
@ -345,7 +362,7 @@ static string get_screw_pump_str(df::building *b) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static string get_water_wheel_str(df::building *b) {
|
|
|
|
static const char * get_water_wheel_str(df::building *b) {
|
|
|
|
df::building_water_wheelst *ww =
|
|
|
|
df::building_water_wheelst *ww =
|
|
|
|
virtual_cast<df::building_water_wheelst>(b);
|
|
|
|
virtual_cast<df::building_water_wheelst>(b);
|
|
|
|
if (!ww)
|
|
|
|
if (!ww)
|
|
|
@ -354,7 +371,7 @@ static string get_water_wheel_str(df::building *b) {
|
|
|
|
return ww->is_vertical ? "Mw" : "Mws";
|
|
|
|
return ww->is_vertical ? "Mw" : "Mws";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static string get_axle_str(df::building *b) {
|
|
|
|
static const char * get_axle_str(df::building *b) {
|
|
|
|
df::building_axle_horizontalst *ah =
|
|
|
|
df::building_axle_horizontalst *ah =
|
|
|
|
virtual_cast<df::building_axle_horizontalst>(b);
|
|
|
|
virtual_cast<df::building_axle_horizontalst>(b);
|
|
|
|
if (!ah)
|
|
|
|
if (!ah)
|
|
|
@ -363,7 +380,7 @@ static string get_axle_str(df::building *b) {
|
|
|
|
return ah->is_vertical ? "Mhs" : "Mh";
|
|
|
|
return ah->is_vertical ? "Mhs" : "Mh";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static string get_roller_str(df::building *b) {
|
|
|
|
static const char * get_roller_str(df::building *b) {
|
|
|
|
df::building_rollersst *r = virtual_cast<df::building_rollersst>(b);
|
|
|
|
df::building_rollersst *r = virtual_cast<df::building_rollersst>(b);
|
|
|
|
if (!r)
|
|
|
|
if (!r)
|
|
|
|
return "~";
|
|
|
|
return "~";
|
|
|
@ -378,192 +395,192 @@ static string get_roller_str(df::building *b) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static string get_expansion_str(df::building *b) {
|
|
|
|
static const char * get_build_keys(const df::coord &pos,
|
|
|
|
pair<uint32_t, uint32_t> size = get_building_size(b);
|
|
|
|
const tile_context &ctx,
|
|
|
|
std::ostringstream s;
|
|
|
|
bool &add_size) {
|
|
|
|
s << "(" << size.first << "x" << size.second << ")";
|
|
|
|
|
|
|
|
return s.str();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void get_tile_build(const df::coord &pos, const tile_context &ctx,
|
|
|
|
|
|
|
|
string &str) {
|
|
|
|
|
|
|
|
if (!ctx.b || ctx.b->getType() == building_type::Stockpile) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool at_nw_corner = static_cast<int32_t>(pos.x) == ctx.b->x1
|
|
|
|
bool at_nw_corner = static_cast<int32_t>(pos.x) == ctx.b->x1
|
|
|
|
&& static_cast<int32_t>(pos.y) == ctx.b->y1;
|
|
|
|
&& static_cast<int32_t>(pos.y) == ctx.b->y1;
|
|
|
|
bool at_se_corner = static_cast<int32_t>(pos.x) == ctx.b->x2
|
|
|
|
bool at_se_corner = static_cast<int32_t>(pos.x) == ctx.b->x2
|
|
|
|
&& static_cast<int32_t>(pos.y) == ctx.b->y2;
|
|
|
|
&& static_cast<int32_t>(pos.y) == ctx.b->y2;
|
|
|
|
bool at_center = static_cast<int32_t>(pos.x) == ctx.b->centerx
|
|
|
|
bool at_center = static_cast<int32_t>(pos.x) == ctx.b->centerx
|
|
|
|
&& static_cast<int32_t>(pos.y) == ctx.b->centery;
|
|
|
|
&& static_cast<int32_t>(pos.y) == ctx.b->centery;
|
|
|
|
bool add_size = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch(ctx.b->getType()) {
|
|
|
|
switch(ctx.b->getType()) {
|
|
|
|
case building_type::Armorstand:
|
|
|
|
case building_type::Armorstand:
|
|
|
|
str = "a"; break;
|
|
|
|
return "a";
|
|
|
|
case building_type::Bed:
|
|
|
|
case building_type::Bed:
|
|
|
|
str = "b"; break;
|
|
|
|
return "b";
|
|
|
|
case building_type::Chair:
|
|
|
|
case building_type::Chair:
|
|
|
|
str = "c"; break;
|
|
|
|
return "c";
|
|
|
|
case building_type::Door:
|
|
|
|
case building_type::Door:
|
|
|
|
str = "d"; break;
|
|
|
|
return "d";
|
|
|
|
case building_type::Floodgate:
|
|
|
|
case building_type::Floodgate:
|
|
|
|
str = "x"; break;
|
|
|
|
return "x";
|
|
|
|
case building_type::Cabinet:
|
|
|
|
case building_type::Cabinet:
|
|
|
|
str = "f"; break;
|
|
|
|
return "f";
|
|
|
|
case building_type::Box:
|
|
|
|
case building_type::Box:
|
|
|
|
str = "h"; break;
|
|
|
|
return "h";
|
|
|
|
//case building_type::Kennel is missing
|
|
|
|
//case building_type::Kennel is missing
|
|
|
|
case building_type::FarmPlot:
|
|
|
|
case building_type::FarmPlot:
|
|
|
|
do_block_building(ctx, str, "p", at_nw_corner, &add_size); break;
|
|
|
|
return do_block_building(ctx, "p", at_nw_corner, &add_size);
|
|
|
|
case building_type::Weaponrack:
|
|
|
|
case building_type::Weaponrack:
|
|
|
|
str = "r"; break;
|
|
|
|
return "r";
|
|
|
|
case building_type::Statue:
|
|
|
|
case building_type::Statue:
|
|
|
|
str = "s"; break;
|
|
|
|
return "s";
|
|
|
|
case building_type::Table:
|
|
|
|
case building_type::Table:
|
|
|
|
str = "t"; break;
|
|
|
|
return "t";
|
|
|
|
case building_type::RoadPaved:
|
|
|
|
case building_type::RoadPaved:
|
|
|
|
do_block_building(ctx, str, "o", at_nw_corner, &add_size); break;
|
|
|
|
return do_block_building(ctx, "o", at_nw_corner, &add_size);
|
|
|
|
case building_type::RoadDirt:
|
|
|
|
case building_type::RoadDirt:
|
|
|
|
do_block_building(ctx, str, "O", at_nw_corner, &add_size); break;
|
|
|
|
return do_block_building(ctx, "O", at_nw_corner, &add_size);
|
|
|
|
case building_type::Bridge:
|
|
|
|
case building_type::Bridge:
|
|
|
|
do_block_building(ctx, str, get_bridge_str(ctx.b), at_nw_corner,
|
|
|
|
return do_block_building(ctx, get_bridge_str(ctx.b), at_nw_corner,
|
|
|
|
&add_size);
|
|
|
|
&add_size);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case building_type::Well:
|
|
|
|
case building_type::Well:
|
|
|
|
str = "l"; break;
|
|
|
|
return "l";
|
|
|
|
case building_type::SiegeEngine:
|
|
|
|
case building_type::SiegeEngine:
|
|
|
|
do_block_building(ctx, str, get_siege_str(ctx.b), at_center);
|
|
|
|
return do_block_building(ctx, get_siege_str(ctx.b), at_center);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case building_type::Workshop:
|
|
|
|
case building_type::Workshop:
|
|
|
|
do_block_building(ctx, str, get_workshop_str(ctx.b), at_center);
|
|
|
|
return do_block_building(ctx, get_workshop_str(ctx.b), at_center);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case building_type::Furnace:
|
|
|
|
case building_type::Furnace:
|
|
|
|
do_block_building(ctx, str, get_furnace_str(ctx.b), at_center);
|
|
|
|
return do_block_building(ctx, get_furnace_str(ctx.b), at_center);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case building_type::WindowGlass:
|
|
|
|
case building_type::WindowGlass:
|
|
|
|
str = "y"; break;
|
|
|
|
return "y";
|
|
|
|
case building_type::WindowGem:
|
|
|
|
case building_type::WindowGem:
|
|
|
|
str = "Y"; break;
|
|
|
|
return "Y";
|
|
|
|
case building_type::Construction:
|
|
|
|
case building_type::Construction:
|
|
|
|
str = get_construction_str(ctx.b); break;
|
|
|
|
return get_construction_str(ctx.b);
|
|
|
|
case building_type::Shop:
|
|
|
|
case building_type::Shop:
|
|
|
|
do_block_building(ctx, str, "z", at_center);
|
|
|
|
return do_block_building(ctx, "z", at_center);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case building_type::AnimalTrap:
|
|
|
|
case building_type::AnimalTrap:
|
|
|
|
str = "m"; break;
|
|
|
|
return "m";
|
|
|
|
case building_type::Chain:
|
|
|
|
case building_type::Chain:
|
|
|
|
str = "v"; break;
|
|
|
|
return "v";
|
|
|
|
case building_type::Cage:
|
|
|
|
case building_type::Cage:
|
|
|
|
str = "j"; break;
|
|
|
|
return "j";
|
|
|
|
case building_type::TradeDepot:
|
|
|
|
case building_type::TradeDepot:
|
|
|
|
do_block_building(ctx, str, "D", at_center); break;
|
|
|
|
return do_block_building(ctx, "D", at_center);
|
|
|
|
case building_type::Trap:
|
|
|
|
case building_type::Trap:
|
|
|
|
str = get_trap_str(ctx.b); break;
|
|
|
|
return get_trap_str(ctx.b);
|
|
|
|
case building_type::ScrewPump:
|
|
|
|
case building_type::ScrewPump:
|
|
|
|
do_block_building(ctx, str, get_screw_pump_str(ctx.b), at_se_corner);
|
|
|
|
return do_block_building(ctx, get_screw_pump_str(ctx.b), at_se_corner);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case building_type::WaterWheel:
|
|
|
|
case building_type::WaterWheel:
|
|
|
|
do_block_building(ctx, str, get_water_wheel_str(ctx.b), at_center);
|
|
|
|
return do_block_building(ctx, get_water_wheel_str(ctx.b), at_center);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case building_type::Windmill:
|
|
|
|
case building_type::Windmill:
|
|
|
|
do_block_building(ctx, str, "Mm", at_center); break;
|
|
|
|
return do_block_building(ctx, "Mm", at_center);
|
|
|
|
case building_type::GearAssembly:
|
|
|
|
case building_type::GearAssembly:
|
|
|
|
str = "Mg"; break;
|
|
|
|
return "Mg";
|
|
|
|
case building_type::AxleHorizontal:
|
|
|
|
case building_type::AxleHorizontal:
|
|
|
|
do_block_building(ctx, str, get_axle_str(ctx.b), at_nw_corner,
|
|
|
|
return do_block_building(ctx, get_axle_str(ctx.b), at_nw_corner,
|
|
|
|
&add_size);
|
|
|
|
&add_size);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case building_type::AxleVertical:
|
|
|
|
case building_type::AxleVertical:
|
|
|
|
str = "Mv"; break;
|
|
|
|
return "Mv";
|
|
|
|
case building_type::Rollers:
|
|
|
|
case building_type::Rollers:
|
|
|
|
do_block_building(ctx, str, get_roller_str(ctx.b), at_nw_corner,
|
|
|
|
return do_block_building(ctx, get_roller_str(ctx.b), at_nw_corner,
|
|
|
|
&add_size);
|
|
|
|
&add_size);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case building_type::Support:
|
|
|
|
case building_type::Support:
|
|
|
|
str = "S"; break;
|
|
|
|
return "S";
|
|
|
|
case building_type::ArcheryTarget:
|
|
|
|
case building_type::ArcheryTarget:
|
|
|
|
str = "A"; break;
|
|
|
|
return "A";
|
|
|
|
case building_type::TractionBench:
|
|
|
|
case building_type::TractionBench:
|
|
|
|
str = "R"; break;
|
|
|
|
return "R";
|
|
|
|
case building_type::Hatch:
|
|
|
|
case building_type::Hatch:
|
|
|
|
str = "H"; break;
|
|
|
|
return "H";
|
|
|
|
case building_type::Slab:
|
|
|
|
case building_type::Slab:
|
|
|
|
//how to mine alt key?!?
|
|
|
|
//how to mine alt key?!?
|
|
|
|
//alt+s
|
|
|
|
//alt+s
|
|
|
|
str = "~"; break;
|
|
|
|
return "~";
|
|
|
|
case building_type::NestBox:
|
|
|
|
case building_type::NestBox:
|
|
|
|
str = "N"; break;
|
|
|
|
return "N";
|
|
|
|
case building_type::Hive:
|
|
|
|
case building_type::Hive:
|
|
|
|
//alt+h
|
|
|
|
//alt+h
|
|
|
|
str = "~"; break;
|
|
|
|
return "~";
|
|
|
|
case building_type::GrateWall:
|
|
|
|
case building_type::GrateWall:
|
|
|
|
str = "W"; break;
|
|
|
|
return "W";
|
|
|
|
case building_type::GrateFloor:
|
|
|
|
case building_type::GrateFloor:
|
|
|
|
str = "G"; break;
|
|
|
|
return "G";
|
|
|
|
case building_type::BarsVertical:
|
|
|
|
case building_type::BarsVertical:
|
|
|
|
str = "B"; break;
|
|
|
|
return "B";
|
|
|
|
case building_type::BarsFloor:
|
|
|
|
case building_type::BarsFloor:
|
|
|
|
//alt+b
|
|
|
|
//alt+b
|
|
|
|
str = "~"; break;
|
|
|
|
return "~";
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
str = if_pretty(ctx, "~");
|
|
|
|
return "~";
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (add_size)
|
|
|
|
|
|
|
|
str.append(get_expansion_str(ctx.b));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void get_tile_place(const df::coord &pos, const tile_context &ctx,
|
|
|
|
// returns "~" if keys is NULL; otherwise returns the keys with the building
|
|
|
|
string &str) {
|
|
|
|
// dimensions in the expansion syntax
|
|
|
|
if (!ctx.b || ctx.b->getType() != building_type::Stockpile)
|
|
|
|
static const char * add_expansion_syntax(const tile_context &ctx,
|
|
|
|
return;
|
|
|
|
const char *keys) {
|
|
|
|
|
|
|
|
if (!keys)
|
|
|
|
|
|
|
|
return "~";
|
|
|
|
|
|
|
|
std::ostringstream s;
|
|
|
|
|
|
|
|
pair<uint32_t, uint32_t> size = get_building_size(ctx.b);
|
|
|
|
|
|
|
|
s << keys << "(" << size.first << "x" << size.second << ")";
|
|
|
|
|
|
|
|
return cache(s.str().c_str());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ctx.b->x1 != static_cast<int32_t>(pos.x)
|
|
|
|
static const char * get_tile_build(const df::coord &pos,
|
|
|
|
|| ctx.b->y1 != static_cast<int32_t>(pos.y)) {
|
|
|
|
const tile_context &ctx) {
|
|
|
|
str = if_pretty(ctx, "`");
|
|
|
|
if (!ctx.b || ctx.b->getType() == building_type::Stockpile) {
|
|
|
|
return;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool add_size = false;
|
|
|
|
|
|
|
|
const char *keys = get_build_keys(pos, ctx, add_size);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!add_size)
|
|
|
|
|
|
|
|
return keys;
|
|
|
|
|
|
|
|
return add_expansion_syntax(ctx, keys);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char * get_place_keys(const tile_context &ctx) {
|
|
|
|
df::building_stockpilest* sp =
|
|
|
|
df::building_stockpilest* sp =
|
|
|
|
virtual_cast<df::building_stockpilest>(ctx.b);
|
|
|
|
virtual_cast<df::building_stockpilest>(ctx.b);
|
|
|
|
if (!sp) {
|
|
|
|
if (!sp) {
|
|
|
|
str = "~";
|
|
|
|
return NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (sp->settings.flags.whole) {
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_animals: return "a";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_food: return "f";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_furniture: return "u";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_corpses: return "y";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_refuse: return "r";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_wood: return "w";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_stone: return "s";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_gems: return "e";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_bars_blocks: return "b";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_cloth: return "h";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_leather: return "l";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_ammo: return "z";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_coins: return "n";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_finished_goods: return "g";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_weapons: return "p";
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_armor: return "d";
|
|
|
|
|
|
|
|
default: // TODO: handle stockpiles with multiple types
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char * get_tile_place(const df::coord &pos,
|
|
|
|
|
|
|
|
const tile_context &ctx) {
|
|
|
|
|
|
|
|
if (!ctx.b || ctx.b->getType() != building_type::Stockpile)
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
|
|
switch (sp->settings.flags.whole)
|
|
|
|
if (ctx.b->x1 != static_cast<int32_t>(pos.x)
|
|
|
|
{
|
|
|
|
|| ctx.b->y1 != static_cast<int32_t>(pos.y)) {
|
|
|
|
case df::stockpile_group_set::mask_animals: str = "a"; break;
|
|
|
|
return if_pretty(ctx, "`");
|
|
|
|
case df::stockpile_group_set::mask_food: str = "f"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_furniture: str = "u"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_corpses: str = "y"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_refuse: str = "r"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_wood: str = "w"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_stone: str = "s"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_gems: str = "e"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_bars_blocks: str = "b"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_cloth: str = "h"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_leather: str = "l"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_ammo: str = "z"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_coins: str = "n"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_finished_goods: str = "g"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_weapons: str = "p"; break;
|
|
|
|
|
|
|
|
case df::stockpile_group_set::mask_armor: str = "d"; break;
|
|
|
|
|
|
|
|
default: // multiple stockpile types
|
|
|
|
|
|
|
|
str = "~";
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
str.append(get_expansion_str(ctx.b));
|
|
|
|
return add_expansion_syntax(ctx, get_place_keys(ctx));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void get_tile_query(const df::coord &, const tile_context &ctx,
|
|
|
|
static const char * get_tile_query(const df::coord &, const tile_context &ctx) {
|
|
|
|
string &str) {
|
|
|
|
if (!ctx.b || !ctx.b->is_room)
|
|
|
|
if (ctx.b && ctx.b->is_room)
|
|
|
|
return NULL;
|
|
|
|
str = "r+";
|
|
|
|
return "r+";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool create_output_dir(color_ostream &out,
|
|
|
|
static bool create_output_dir(color_ostream &out,
|
|
|
@ -613,22 +630,22 @@ static bool get_filename(string &fname,
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
typedef map<int16_t /* x */, string> bp_row;
|
|
|
|
typedef map<int16_t /* x */, const char *> bp_row;
|
|
|
|
typedef map<int16_t /* y */, bp_row> bp_area;
|
|
|
|
typedef map<int16_t /* y */, bp_row> bp_area;
|
|
|
|
typedef map<int16_t /* z */, bp_area> bp_volume;
|
|
|
|
typedef map<int16_t /* z */, bp_area> bp_volume;
|
|
|
|
|
|
|
|
|
|
|
|
static const bp_area NEW_AREA;
|
|
|
|
static const bp_area NEW_AREA;
|
|
|
|
static const bp_row NEW_ROW;
|
|
|
|
static const bp_row NEW_ROW;
|
|
|
|
|
|
|
|
|
|
|
|
typedef void (get_tile_fn)(const df::coord &pos, const tile_context &ctx,
|
|
|
|
typedef const char * (get_tile_fn)(const df::coord &pos,
|
|
|
|
string &str);
|
|
|
|
const tile_context &ctx);
|
|
|
|
typedef void (init_ctx_fn)(const df::coord &pos, tile_context &ctx);
|
|
|
|
typedef void (init_ctx_fn)(const df::coord &pos, tile_context &ctx);
|
|
|
|
|
|
|
|
|
|
|
|
struct blueprint_processor {
|
|
|
|
struct blueprint_processor {
|
|
|
|
bp_volume mapdata;
|
|
|
|
bp_volume mapdata;
|
|
|
|
string phase;
|
|
|
|
const string phase;
|
|
|
|
get_tile_fn *get_tile;
|
|
|
|
get_tile_fn * const get_tile;
|
|
|
|
init_ctx_fn *init_ctx;
|
|
|
|
init_ctx_fn * const init_ctx;
|
|
|
|
blueprint_processor(const string &phase, get_tile_fn *get_tile,
|
|
|
|
blueprint_processor(const string &phase, get_tile_fn *get_tile,
|
|
|
|
init_ctx_fn *init_ctx = NULL)
|
|
|
|
init_ctx_fn *init_ctx = NULL)
|
|
|
|
: phase(phase), get_tile(get_tile), init_ctx(init_ctx) { }
|
|
|
|
: phase(phase), get_tile(get_tile), init_ctx(init_ctx) { }
|
|
|
@ -674,10 +691,10 @@ static void write_pretty(ofstream &ofile, const blueprint_options &opts,
|
|
|
|
if (area && area->count(y))
|
|
|
|
if (area && area->count(y))
|
|
|
|
row = &area->at(y);
|
|
|
|
row = &area->at(y);
|
|
|
|
for (int16_t x = 0; x < opts.width; ++x) {
|
|
|
|
for (int16_t x = 0; x < opts.width; ++x) {
|
|
|
|
const string *tile = NULL;
|
|
|
|
const char *tile = NULL;
|
|
|
|
if (row && row->count(x))
|
|
|
|
if (row && row->count(x))
|
|
|
|
tile = &row->at(x);
|
|
|
|
tile = row->at(x);
|
|
|
|
ofile << (tile ? *tile : " ") << ",";
|
|
|
|
ofile << (tile ? tile : " ") << ",";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ofile << "#" << endl;
|
|
|
|
ofile << "#" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -758,9 +775,8 @@ static bool do_transform(color_ostream &out,
|
|
|
|
for (blueprint_processor &processor : processors) {
|
|
|
|
for (blueprint_processor &processor : processors) {
|
|
|
|
if (processor.init_ctx)
|
|
|
|
if (processor.init_ctx)
|
|
|
|
processor.init_ctx(pos, ctx);
|
|
|
|
processor.init_ctx(pos, ctx);
|
|
|
|
string tile_str;
|
|
|
|
const char *tile_str = processor.get_tile(pos, ctx);
|
|
|
|
processor.get_tile(pos, ctx, tile_str);
|
|
|
|
if (tile_str) {
|
|
|
|
if (!tile_str.empty()) {
|
|
|
|
|
|
|
|
// ensure our z-index is in the order we want to write
|
|
|
|
// ensure our z-index is in the order we want to write
|
|
|
|
auto area = processor.mapdata.emplace(abs(z - start.z),
|
|
|
|
auto area = processor.mapdata.emplace(abs(z - start.z),
|
|
|
|
NEW_AREA);
|
|
|
|
NEW_AREA);
|
|
|
@ -890,7 +906,9 @@ static bool do_blueprint(color_ostream &out,
|
|
|
|
if (end.z < -1)
|
|
|
|
if (end.z < -1)
|
|
|
|
end.z = -1;
|
|
|
|
end.z = -1;
|
|
|
|
|
|
|
|
|
|
|
|
return do_transform(out, start, end, options, files);
|
|
|
|
bool ok = do_transform(out, start, end, options, files);
|
|
|
|
|
|
|
|
cache(NULL);
|
|
|
|
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// entrypoint when called from Lua. returns the names of the generated files
|
|
|
|
// entrypoint when called from Lua. returns the names of the generated files
|
|
|
|