|
|
|
@ -5,22 +5,31 @@
|
|
|
|
|
#include <Console.h>
|
|
|
|
|
#include <PluginManager.h>
|
|
|
|
|
|
|
|
|
|
#include "df/building_axle_horizontalst.h"
|
|
|
|
|
#include "df/building_bridgest.h"
|
|
|
|
|
#include "df/building_constructionst.h"
|
|
|
|
|
#include "df/building_furnacest.h"
|
|
|
|
|
#include "df/building_rollersst.h"
|
|
|
|
|
#include "df/building_screw_pumpst.h"
|
|
|
|
|
#include "df/building_siegeenginest.h"
|
|
|
|
|
#include "df/building_trapst.h"
|
|
|
|
|
#include "df/building_water_wheelst.h"
|
|
|
|
|
#include "df/building_workshopst.h"
|
|
|
|
|
|
|
|
|
|
#include "modules/Gui.h"
|
|
|
|
|
#include "modules/MapCache.h"
|
|
|
|
|
#include "modules/Buildings.h"
|
|
|
|
|
|
|
|
|
|
using std::string;
|
|
|
|
|
using std::endl;
|
|
|
|
|
using std::vector;
|
|
|
|
|
using std::ofstream;
|
|
|
|
|
using std::swap;
|
|
|
|
|
using namespace DFHack;
|
|
|
|
|
using namespace df::enums;
|
|
|
|
|
|
|
|
|
|
DFHACK_PLUGIN("blueprint");
|
|
|
|
|
|
|
|
|
|
#define swap(x, y)\
|
|
|
|
|
x += y;\
|
|
|
|
|
y = x - y;\
|
|
|
|
|
x -= y
|
|
|
|
|
|
|
|
|
|
enum phase {DIG, BUILD, PLACE, QUERY};
|
|
|
|
|
|
|
|
|
|
command_result blueprint(color_ostream &out, vector <string> ¶meters);
|
|
|
|
@ -56,35 +65,361 @@ command_result help(color_ostream &out)
|
|
|
|
|
|
|
|
|
|
char get_tile_dig(MapExtras::MapCache mc, int32_t x, int32_t y, int32_t z)
|
|
|
|
|
{
|
|
|
|
|
df::tiletype tt = mc.tiletypeAt(DFCoord(x, y, z));
|
|
|
|
|
df::enum_traits<df::tiletype> et;
|
|
|
|
|
df::tiletype_shape ts = et.attr_table[tt].shape;
|
|
|
|
|
df::tiletype tt = mc.tiletypeAt(DFCoord(x, y, z));
|
|
|
|
|
df::tiletype_shape ts = tileShape(tt);
|
|
|
|
|
switch (ts)
|
|
|
|
|
{
|
|
|
|
|
case df::tiletype_shape::EMPTY:
|
|
|
|
|
case df::tiletype_shape::RAMP_TOP:
|
|
|
|
|
case tiletype_shape::EMPTY:
|
|
|
|
|
case tiletype_shape::RAMP_TOP:
|
|
|
|
|
return 'h';
|
|
|
|
|
case df::tiletype_shape::FLOOR:
|
|
|
|
|
case df::tiletype_shape::BOULDER:
|
|
|
|
|
case df::tiletype_shape::PEBBLES:
|
|
|
|
|
case df::tiletype_shape::BROOK_TOP:
|
|
|
|
|
case tiletype_shape::FLOOR:
|
|
|
|
|
case tiletype_shape::BOULDER:
|
|
|
|
|
case tiletype_shape::PEBBLES:
|
|
|
|
|
case tiletype_shape::BROOK_TOP:
|
|
|
|
|
return 'd';
|
|
|
|
|
case df::tiletype_shape::FORTIFICATION:
|
|
|
|
|
return 'a'; //or possibly 'F' with new keybindings?
|
|
|
|
|
case df::tiletype_shape::STAIR_UP:
|
|
|
|
|
case tiletype_shape::FORTIFICATION:
|
|
|
|
|
return 'F';
|
|
|
|
|
case tiletype_shape::STAIR_UP:
|
|
|
|
|
return 'u';
|
|
|
|
|
case df::tiletype_shape::STAIR_DOWN:
|
|
|
|
|
case tiletype_shape::STAIR_DOWN:
|
|
|
|
|
return 'j';
|
|
|
|
|
case df::tiletype_shape::STAIR_UPDOWN:
|
|
|
|
|
case tiletype_shape::STAIR_UPDOWN:
|
|
|
|
|
return 'i';
|
|
|
|
|
case df::tiletype_shape::RAMP:
|
|
|
|
|
case tiletype_shape::RAMP:
|
|
|
|
|
return 'r';
|
|
|
|
|
default:
|
|
|
|
|
return ' ';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string get_tile_build(df::building* b)
|
|
|
|
|
{
|
|
|
|
|
switch(b->getType())
|
|
|
|
|
{
|
|
|
|
|
case building_type::Armorstand:
|
|
|
|
|
return "a";
|
|
|
|
|
case building_type::Bed:
|
|
|
|
|
return "b";
|
|
|
|
|
case building_type::Chair:
|
|
|
|
|
return "c";
|
|
|
|
|
case building_type::Door:
|
|
|
|
|
return "d";
|
|
|
|
|
case building_type::Floodgate:
|
|
|
|
|
return "x";
|
|
|
|
|
case building_type::Cabinet:
|
|
|
|
|
return "f";
|
|
|
|
|
case building_type::Box:
|
|
|
|
|
return "h";
|
|
|
|
|
//case building_type::Kennel is missing
|
|
|
|
|
case building_type::FarmPlot:
|
|
|
|
|
return "p";
|
|
|
|
|
case building_type::Weaponrack:
|
|
|
|
|
return "r";
|
|
|
|
|
case building_type::Statue:
|
|
|
|
|
return "s";
|
|
|
|
|
case building_type::Table:
|
|
|
|
|
return "t";
|
|
|
|
|
case building_type::RoadPaved:
|
|
|
|
|
return "o";
|
|
|
|
|
case building_type::RoadDirt:
|
|
|
|
|
return "O";
|
|
|
|
|
case building_type::Bridge:
|
|
|
|
|
switch(((df::building_bridgest*) b)->direction)
|
|
|
|
|
{
|
|
|
|
|
case df::building_bridgest::T_direction::Down:
|
|
|
|
|
return "gx";
|
|
|
|
|
case df::building_bridgest::T_direction::Left:
|
|
|
|
|
return "ga";
|
|
|
|
|
case df::building_bridgest::T_direction::Up:
|
|
|
|
|
return "gw";
|
|
|
|
|
case df::building_bridgest::T_direction::Right:
|
|
|
|
|
return "gd";
|
|
|
|
|
case df::building_bridgest::T_direction::Retracting:
|
|
|
|
|
return "gs";
|
|
|
|
|
}
|
|
|
|
|
case building_type::Well:
|
|
|
|
|
return "l";
|
|
|
|
|
case building_type::SiegeEngine:
|
|
|
|
|
return "i" + ((df::building_siegeenginest*) b)->type == df::siegeengine_type::Ballista ? "b" : "c";
|
|
|
|
|
case building_type::Workshop:
|
|
|
|
|
switch (((df::building_workshopst*) b)->type)
|
|
|
|
|
{
|
|
|
|
|
case workshop_type::Leatherworks:
|
|
|
|
|
return "we";
|
|
|
|
|
case workshop_type::Quern:
|
|
|
|
|
return "wq";
|
|
|
|
|
case workshop_type::Millstone:
|
|
|
|
|
return "wM";
|
|
|
|
|
case workshop_type::Loom:
|
|
|
|
|
return "wo";
|
|
|
|
|
case workshop_type::Clothiers:
|
|
|
|
|
return "wk";
|
|
|
|
|
case workshop_type::Bowyers:
|
|
|
|
|
return "wb";
|
|
|
|
|
case workshop_type::Carpenters:
|
|
|
|
|
return "wc";
|
|
|
|
|
case workshop_type::MetalsmithsForge:
|
|
|
|
|
return "wf";
|
|
|
|
|
case workshop_type::MagmaForge:
|
|
|
|
|
return "wv";
|
|
|
|
|
case workshop_type::Jewelers:
|
|
|
|
|
return "wj";
|
|
|
|
|
case workshop_type::Masons:
|
|
|
|
|
return "wm";
|
|
|
|
|
case workshop_type::Butchers:
|
|
|
|
|
return "wu";
|
|
|
|
|
case workshop_type::Tanners:
|
|
|
|
|
return "wn";
|
|
|
|
|
case workshop_type::Craftsdwarfs:
|
|
|
|
|
return "wr";
|
|
|
|
|
case workshop_type::Siege:
|
|
|
|
|
return "ws";
|
|
|
|
|
case workshop_type::Mechanics:
|
|
|
|
|
return "wt";
|
|
|
|
|
case workshop_type::Still:
|
|
|
|
|
return "wl";
|
|
|
|
|
case workshop_type::Farmers:
|
|
|
|
|
return "ww";
|
|
|
|
|
case workshop_type::Kitchen:
|
|
|
|
|
return "wz";
|
|
|
|
|
case workshop_type::Fishery:
|
|
|
|
|
return "wh";
|
|
|
|
|
case workshop_type::Ashery:
|
|
|
|
|
return "wy";
|
|
|
|
|
case workshop_type::Dyers:
|
|
|
|
|
return "wd";
|
|
|
|
|
case workshop_type::Custom:
|
|
|
|
|
//can't do anything with custom workshop
|
|
|
|
|
return " ";
|
|
|
|
|
}
|
|
|
|
|
case building_type::Furnace:
|
|
|
|
|
switch (((df::building_furnacest*) b)->type)
|
|
|
|
|
{
|
|
|
|
|
case furnace_type::WoodFurnace:
|
|
|
|
|
return "ew";
|
|
|
|
|
case furnace_type::Smelter:
|
|
|
|
|
return "es";
|
|
|
|
|
case furnace_type::GlassFurnace:
|
|
|
|
|
return "eg";
|
|
|
|
|
case furnace_type::Kiln:
|
|
|
|
|
return "ek";
|
|
|
|
|
case furnace_type::MagmaSmelter:
|
|
|
|
|
return "el";
|
|
|
|
|
case furnace_type::MagmaGlassFurnace:
|
|
|
|
|
return "ea";
|
|
|
|
|
case furnace_type::MagmaKiln:
|
|
|
|
|
return "en";
|
|
|
|
|
case furnace_type::Custom:
|
|
|
|
|
//can't do anything with custom furnace
|
|
|
|
|
return " ";
|
|
|
|
|
}
|
|
|
|
|
case building_type::WindowGlass:
|
|
|
|
|
return "y";
|
|
|
|
|
case building_type::WindowGem:
|
|
|
|
|
return "Y";
|
|
|
|
|
case building_type::Construction:
|
|
|
|
|
switch (((df::building_constructionst*) b)->type)
|
|
|
|
|
{
|
|
|
|
|
case construction_type::Fortification:
|
|
|
|
|
return "CF";
|
|
|
|
|
case construction_type::Wall:
|
|
|
|
|
return "CW";
|
|
|
|
|
case construction_type::Floor:
|
|
|
|
|
return "Cf";
|
|
|
|
|
case construction_type::UpStair:
|
|
|
|
|
return "Cu";
|
|
|
|
|
case construction_type::DownStair:
|
|
|
|
|
return "Cj";
|
|
|
|
|
case construction_type::UpDownStair:
|
|
|
|
|
return "Cx";
|
|
|
|
|
case construction_type::Ramp:
|
|
|
|
|
return "Cr";
|
|
|
|
|
case construction_type::TrackN:
|
|
|
|
|
return "trackN";
|
|
|
|
|
case construction_type::TrackS:
|
|
|
|
|
return "trackS";
|
|
|
|
|
case construction_type::TrackE:
|
|
|
|
|
return "trackE";
|
|
|
|
|
case construction_type::TrackW:
|
|
|
|
|
return "trackW";
|
|
|
|
|
case construction_type::TrackNS:
|
|
|
|
|
return "trackNS";
|
|
|
|
|
case construction_type::TrackNE:
|
|
|
|
|
return "trackNE";
|
|
|
|
|
case construction_type::TrackNW:
|
|
|
|
|
return "trackNW";
|
|
|
|
|
case construction_type::TrackSE:
|
|
|
|
|
return "trackSE";
|
|
|
|
|
case construction_type::TrackSW:
|
|
|
|
|
return "trackSW";
|
|
|
|
|
case construction_type::TrackEW:
|
|
|
|
|
return "trackEW";
|
|
|
|
|
case construction_type::TrackNSE:
|
|
|
|
|
return "trackNSE";
|
|
|
|
|
case construction_type::TrackNSW:
|
|
|
|
|
return "trackNSW";
|
|
|
|
|
case construction_type::TrackNEW:
|
|
|
|
|
return "trackNEW";
|
|
|
|
|
case construction_type::TrackSEW:
|
|
|
|
|
return "trackSEW";
|
|
|
|
|
case construction_type::TrackNSEW:
|
|
|
|
|
return "trackNSEW";
|
|
|
|
|
case construction_type::TrackRampN:
|
|
|
|
|
return "trackrampN";
|
|
|
|
|
case construction_type::TrackRampS:
|
|
|
|
|
return "trackrampS";
|
|
|
|
|
case construction_type::TrackRampE:
|
|
|
|
|
return "trackrampE";
|
|
|
|
|
case construction_type::TrackRampW:
|
|
|
|
|
return "trackrampW";
|
|
|
|
|
case construction_type::TrackRampNS:
|
|
|
|
|
return "trackrampNS";
|
|
|
|
|
case construction_type::TrackRampNE:
|
|
|
|
|
return "trackrampNE";
|
|
|
|
|
case construction_type::TrackRampNW:
|
|
|
|
|
return "trackrampNW";
|
|
|
|
|
case construction_type::TrackRampSE:
|
|
|
|
|
return "trackrampSE";
|
|
|
|
|
case construction_type::TrackRampSW:
|
|
|
|
|
return "trackrampSW";
|
|
|
|
|
case construction_type::TrackRampEW:
|
|
|
|
|
return "trackrampEW";
|
|
|
|
|
case construction_type::TrackRampNSE:
|
|
|
|
|
return "trackrampNSE";
|
|
|
|
|
case construction_type::TrackRampNSW:
|
|
|
|
|
return "trackrampNSW";
|
|
|
|
|
case construction_type::TrackRampNEW:
|
|
|
|
|
return "trackrampNEW";
|
|
|
|
|
case construction_type::TrackRampSEW:
|
|
|
|
|
return "trackrampSEW";
|
|
|
|
|
case construction_type::TrackRampNSEW:
|
|
|
|
|
return "trackrampNSEW";
|
|
|
|
|
}
|
|
|
|
|
case building_type::Shop:
|
|
|
|
|
return "z";
|
|
|
|
|
case building_type::AnimalTrap:
|
|
|
|
|
return "m";
|
|
|
|
|
case building_type::Chain:
|
|
|
|
|
return "v";
|
|
|
|
|
case building_type::Cage:
|
|
|
|
|
return "j";
|
|
|
|
|
case building_type::TradeDepot:
|
|
|
|
|
return "D";
|
|
|
|
|
case building_type::Trap:
|
|
|
|
|
switch (((df::building_trapst*) b)->trap_type)
|
|
|
|
|
{
|
|
|
|
|
case trap_type::StoneFallTrap:
|
|
|
|
|
return "Ts";
|
|
|
|
|
case trap_type::WeaponTrap:
|
|
|
|
|
return "Tw";
|
|
|
|
|
case trap_type::Lever:
|
|
|
|
|
return "Tl";
|
|
|
|
|
case trap_type::PressurePlate:
|
|
|
|
|
return "Tp";
|
|
|
|
|
case trap_type::CageTrap:
|
|
|
|
|
return "Tc";
|
|
|
|
|
case trap_type::TrackStop:
|
|
|
|
|
df::building_trapst* ts = (df::building_trapst*) b;
|
|
|
|
|
string ret = "CS";
|
|
|
|
|
if (ts->use_dump)
|
|
|
|
|
{
|
|
|
|
|
if (ts->dump_x_shift == 0)
|
|
|
|
|
{
|
|
|
|
|
if (ts->dump_y_shift > 0)
|
|
|
|
|
ret += "dd";
|
|
|
|
|
else
|
|
|
|
|
ret += "d";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (ts->dump_x_shift > 0)
|
|
|
|
|
ret += "ddd";
|
|
|
|
|
else
|
|
|
|
|
ret += "dddd";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
switch (ts->friction)
|
|
|
|
|
{
|
|
|
|
|
case 10:
|
|
|
|
|
ret += "a";
|
|
|
|
|
case 50:
|
|
|
|
|
ret += "a";
|
|
|
|
|
case 500:
|
|
|
|
|
ret += "a";
|
|
|
|
|
case 10000:
|
|
|
|
|
ret += "a";
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
case building_type::ScrewPump:
|
|
|
|
|
switch (((df::building_screw_pumpst*) b)->direction)
|
|
|
|
|
{
|
|
|
|
|
case screw_pump_direction::FromNorth:
|
|
|
|
|
return "Msu";
|
|
|
|
|
case screw_pump_direction::FromEast:
|
|
|
|
|
return "Msk";
|
|
|
|
|
case screw_pump_direction::FromSouth:
|
|
|
|
|
return "Msm";
|
|
|
|
|
case screw_pump_direction::FromWest:
|
|
|
|
|
return "Msh";
|
|
|
|
|
}
|
|
|
|
|
case building_type::WaterWheel:
|
|
|
|
|
//s swaps orientation which defaults to vertical
|
|
|
|
|
return "Mw" + ((df::building_water_wheelst*) b)->is_vertical ? "" : "s";
|
|
|
|
|
case building_type::Windmill:
|
|
|
|
|
return "Mm";
|
|
|
|
|
case building_type::GearAssembly:
|
|
|
|
|
return "Mg";
|
|
|
|
|
case building_type::AxleHorizontal:
|
|
|
|
|
//same as water wheel but reversed
|
|
|
|
|
return "Mh" + ((df::building_axle_horizontalst*) b)->is_vertical ? "s" : "";
|
|
|
|
|
case building_type::AxleVertical:
|
|
|
|
|
return "Mv";
|
|
|
|
|
case building_type::Rollers:
|
|
|
|
|
string ret = "Mr";
|
|
|
|
|
switch (((df::building_rollersst*) b)->direction)
|
|
|
|
|
{
|
|
|
|
|
case screw_pump_direction::FromNorth:
|
|
|
|
|
break;
|
|
|
|
|
case screw_pump_direction::FromEast:
|
|
|
|
|
ret += "s";
|
|
|
|
|
case screw_pump_direction::FromSouth:
|
|
|
|
|
ret += "s";
|
|
|
|
|
case screw_pump_direction::FromWest:
|
|
|
|
|
ret += "s";
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
case building_type::Support:
|
|
|
|
|
return "S";
|
|
|
|
|
case building_type::ArcheryTarget:
|
|
|
|
|
return "A";
|
|
|
|
|
case building_type::TractionBench:
|
|
|
|
|
return "R";
|
|
|
|
|
case building_type::Hatch:
|
|
|
|
|
return "H";
|
|
|
|
|
case building_type::Slab:
|
|
|
|
|
//how to mine alt key?!?
|
|
|
|
|
//alt+s
|
|
|
|
|
return " ";
|
|
|
|
|
case building_type::NestBox:
|
|
|
|
|
return "N";
|
|
|
|
|
case building_type::Hive:
|
|
|
|
|
//alt+h
|
|
|
|
|
return " ";
|
|
|
|
|
case building_type::GrateWall:
|
|
|
|
|
return "W";
|
|
|
|
|
case building_type::GrateFloor:
|
|
|
|
|
return "G";
|
|
|
|
|
case building_type::BarsVertical:
|
|
|
|
|
return "B";
|
|
|
|
|
case building_type::BarsFloor:
|
|
|
|
|
//alt+b
|
|
|
|
|
return " ";
|
|
|
|
|
default:
|
|
|
|
|
return " ";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
command_result do_transform(DFCoord start, DFCoord end, string name, phase last_phase)
|
|
|
|
|
{
|
|
|
|
@ -130,10 +465,12 @@ command_result do_transform(DFCoord start, DFCoord end, string name, phase last_
|
|
|
|
|
{
|
|
|
|
|
for (int32_t x = start.x; x < end.x; x++)
|
|
|
|
|
{
|
|
|
|
|
df::building* b = DFHack::Buildings::findAtTile(DFCoord(x, y, z));
|
|
|
|
|
switch (last_phase) {
|
|
|
|
|
case QUERY:
|
|
|
|
|
case PLACE:
|
|
|
|
|
case BUILD:
|
|
|
|
|
build << get_tile_build(b) << ',';
|
|
|
|
|
case DIG:
|
|
|
|
|
dig << get_tile_dig(mc, x, y, z) << ',';
|
|
|
|
|
}
|
|
|
|
@ -159,7 +496,7 @@ command_result do_transform(DFCoord start, DFCoord end, string name, phase last_
|
|
|
|
|
build << "#<" << endl;
|
|
|
|
|
case DIG:
|
|
|
|
|
dig << "#<" << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
switch (last_phase) {
|
|
|
|
|
case QUERY:
|
|
|
|
|