From 819327348b3c8f3274de22c52972c4f5d46a8486 Mon Sep 17 00:00:00 2001 From: Chris Dombroski Date: Wed, 7 Jan 2015 16:27:48 -0500 Subject: [PATCH 01/10] Blueprint plugin basic structure It should be able to load and make empty blueprint files. --- plugins/CMakeLists.txt | 1 + plugins/blueprint.cpp | 172 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 plugins/blueprint.cpp diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index b68fe61bc..f58c0182d 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -91,6 +91,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(automaterial automaterial.cpp) DFHACK_PLUGIN(automelt automelt.cpp) DFHACK_PLUGIN(autotrade autotrade.cpp) + DFHACK_PLUGIN(blueprint blueprint.cpp) DFHACK_PLUGIN(burrows burrows.cpp LINK_LIBRARIES lua) DFHACK_PLUGIN(building-hacks building-hacks.cpp LINK_LIBRARIES lua) DFHACK_PLUGIN(buildingplan buildingplan-lib.cpp buildingplan.cpp) diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp new file mode 100644 index 000000000..987d6d0d8 --- /dev/null +++ b/plugins/blueprint.cpp @@ -0,0 +1,172 @@ +//Blueprint +//By cdombroski +//Translates a region of tiles specified by the cursor and arguments/prompts into a series of blueprint files suitable for digfort/buildingplan/quickfort + +#include +#include + +#include "modules/Gui.h" +#include "modules/MapCache.h" + +using std::string; +using std::endl; +using std::vector; +using std::ofstream; +using namespace DFHack; + +DFHACK_PLUGIN("blueprint"); + +#define swap(x, y)\ + x += y;\ + y = x - y;\ + x -= x + +enum phase {DIG, BUILD, PLACE, QUERY}; + +command_result blueprint(color_ostream &out, vector ¶meters); + +DFhackCExport command_result plugin_init(color_ostream &out, vector &commands) +{ + commands.push_back(PluginCommand("blueprint", "Convert map tiles into a blueprint", blueprint, false)); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown(color_ostream &out) +{ + return CR_OK; +} + +command_result help(color_ostream &out) +{ + out << "blueprint width height depth name [dig [build [place [query]]]]" << endl + << " width, height, depth: area to translate in tiles" << endl + << " name: base name for blueprint files" << endl + << " dig: generate blueprints for digging" << endl + << " build: generate blueprints for building" << endl + << " place: generate blueprints for stockpiles" << endl + << " query: generate blueprints for querying (room designations)" << endl + << " defaults to generating all blueprints" << endl + << endl + << "blueprint translates a portion of your fortress into blueprints suitable for" << endl + << " digfort/fortplan/quickfort. Blueprints are created in the DF folder with names" << endl + << " following a \"name-phase.csv\" pattern. Translation starts at the current" << endl + << " cursor location and includes all tiles in the range specified." << endl; + return CR_OK; +} + + +command_result do_transform(DFCoord start, DFCoord range, string name, phase last_phase) +{ + ofstream dig, build, place, query; + switch (last_phase) + { + case QUERY: + query = ofstream(name + "-query.csv", ofstream::trunc); + query << "#query" << endl; + case PLACE: + place = ofstream(name + "-place.csv", ofstream::trunc); + place << "#place" << endl; + case BUILD: + build = ofstream(name + "-build.csv", ofstream::trunc); + build << "#build" << endl; + case DIG: + dig = ofstream(name + "-dig.csv", ofstream::trunc); + dig << "#dig" << endl; + } + DFCoord end = start + range; + if (start.x > end.x) + { + swap(start.x, end.x); + } + if (start.y > end.y) + { + swap(start.y, end.y); + } + if (start.z > end.z) + { + swap(start.z, end.z); + } + + MapExtras::MapCache mc; + for (auto z = start.z; z < end.z; z++) + { + for (auto y = start.y; y < end.y; y++) + { + for (auto x = start.x; x < end.x; x++) + { + switch (last_phase) { + case QUERY: + case PLACE: + case BUILD: + case DIG: + } + } + switch (last_phase) { + case QUERY: + query << "#" << endl; + case PLACE: + place << "#" << endl; + case BUILD: + place << "#" << endl; + case DIG: + dig << "#" << endl; + } + } + if (z < end.z - 1) + switch (last_phase) { + case QUERY: + query << "#>" << endl; + case PLACE: + place << "#>" << endl; + case BUILD: + place << "#>" << endl; + case DIG: + dig << "#>" << endl; + } + } + switch (last_phase) { + case QUERY: + query.close(); + case PLACE: + place.close(); + case BUILD: + place.close(); + case DIG: + dig.close(); + } + return CR_OK; +} + +command_result blueprint(color_ostream &out, vector ¶meters) +{ + if (parameters.size() < 4 || parameters.size() > 8) + return help(out); + CoreSuspender suspend; + if (!Maps::IsValid()) + { + out.printerr("Map is not available!\n"); + return CR_FAILURE; + } + int32_t x, y, z; + if (!Gui::getCursorCoords(x, y, z)) + { + out.printerr("Can't get cursor coords! Make sure you have an active cursor in DF.\n"); + return CR_FAILURE; + } + DFCoord start (x, y, z); + DFCoord range (stoi(parameters[0]), stoi(parameters[1]), stoi(parameters[2])); + switch(parameters.size()) + { + case 4: + case 8: + return do_transform(start, range, parameters[3], QUERY); + case 5: + return do_transform(start, range, parameters[3], DIG); + case 6: + return do_transform(start, range, parameters[3], BUILD); + case 7: + return do_transform(start, range, parameters[3], PLACE); + default: //wtf? + return CR_FAILURE; + } +} \ No newline at end of file From b627240943002087eb3dcd918a4d7ea59cc60187 Mon Sep 17 00:00:00 2001 From: Chris Dombroski Date: Thu, 8 Jan 2015 12:17:18 -0500 Subject: [PATCH 02/10] Dig mode complete --- plugins/blueprint.cpp | 71 ++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 17 deletions(-) diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index 987d6d0d8..eea748697 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -19,7 +19,7 @@ DFHACK_PLUGIN("blueprint"); #define swap(x, y)\ x += y;\ y = x - y;\ - x -= x + x -= y enum phase {DIG, BUILD, PLACE, QUERY}; @@ -54,8 +54,39 @@ command_result help(color_ostream &out) return CR_OK; } +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 et; + df::tiletype_shape ts = et.attr_table[tt].shape; + switch (ts) + { + case df::tiletype_shape::EMPTY: + case df::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: + return 'd'; + case df::tiletype_shape::FORTIFICATION: + return 'a'; //or possibly 'F' with new keybindings? + case df::tiletype_shape::STAIR_UP: + return 'u'; + case df::tiletype_shape::STAIR_DOWN: + return 'j'; + case df::tiletype_shape::STAIR_UPDOWN: + return 'i'; + case df::tiletype_shape::RAMP: + return 'r'; + default: + return ' '; + + } +} -command_result do_transform(DFCoord start, DFCoord range, string name, phase last_phase) + +command_result do_transform(DFCoord start, DFCoord end, string name, phase last_phase) { ofstream dig, build, place, query; switch (last_phase) @@ -73,32 +104,38 @@ command_result do_transform(DFCoord start, DFCoord range, string name, phase las dig = ofstream(name + "-dig.csv", ofstream::trunc); dig << "#dig" << endl; } - DFCoord end = start + range; if (start.x > end.x) { swap(start.x, end.x); + start.x++; + end.x++; } if (start.y > end.y) { swap(start.y, end.y); + start.y++; + end.y++; } if (start.z > end.z) { swap(start.z, end.z); + start.z++; + end.z++; } MapExtras::MapCache mc; - for (auto z = start.z; z < end.z; z++) + for (int32_t z = start.z; z < end.z; z++) { - for (auto y = start.y; y < end.y; y++) + for (int32_t y = start.y; y < end.y; y++) { - for (auto x = start.x; x < end.x; x++) + for (int32_t x = start.x; x < end.x; x++) { switch (last_phase) { case QUERY: case PLACE: case BUILD: case DIG: + dig << get_tile_dig(mc, x, y, z) << ','; } } switch (last_phase) { @@ -107,7 +144,7 @@ command_result do_transform(DFCoord start, DFCoord range, string name, phase las case PLACE: place << "#" << endl; case BUILD: - place << "#" << endl; + build << "#" << endl; case DIG: dig << "#" << endl; } @@ -115,13 +152,13 @@ command_result do_transform(DFCoord start, DFCoord range, string name, phase las if (z < end.z - 1) switch (last_phase) { case QUERY: - query << "#>" << endl; + query << "#<" << endl; case PLACE: - place << "#>" << endl; + place << "#<" << endl; case BUILD: - place << "#>" << endl; + build << "#<" << endl; case DIG: - dig << "#>" << endl; + dig << "#<" << endl; } } switch (last_phase) { @@ -130,7 +167,7 @@ command_result do_transform(DFCoord start, DFCoord range, string name, phase las case PLACE: place.close(); case BUILD: - place.close(); + build.close(); case DIG: dig.close(); } @@ -154,18 +191,18 @@ command_result blueprint(color_ostream &out, vector ¶meters) return CR_FAILURE; } DFCoord start (x, y, z); - DFCoord range (stoi(parameters[0]), stoi(parameters[1]), stoi(parameters[2])); + DFCoord end (x + stoi(parameters[0]), y + stoi(parameters[1]), z + stoi(parameters[2])); switch(parameters.size()) { case 4: case 8: - return do_transform(start, range, parameters[3], QUERY); + return do_transform(start, end, parameters[3], QUERY); case 5: - return do_transform(start, range, parameters[3], DIG); + return do_transform(start, end, parameters[3], DIG); case 6: - return do_transform(start, range, parameters[3], BUILD); + return do_transform(start, end, parameters[3], BUILD); case 7: - return do_transform(start, range, parameters[3], PLACE); + return do_transform(start, end, parameters[3], PLACE); default: //wtf? return CR_FAILURE; } From ea313b6bf5b2e27cd217a02069746e8143b838ee Mon Sep 17 00:00:00 2001 From: Chris Dombroski Date: Fri, 9 Jan 2015 16:00:47 -0500 Subject: [PATCH 03/10] plugins/blueprint.cpp: Buildings hopefully --- plugins/blueprint.cpp | 381 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 359 insertions(+), 22 deletions(-) diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index eea748697..2689f4c69 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -5,22 +5,31 @@ #include #include +#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 ¶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 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: From 3489c2f39a352fca12b1dd01b3af8bc27554cee3 Mon Sep 17 00:00:00 2001 From: Chris Dombroski Date: Mon, 12 Jan 2015 11:52:46 -0500 Subject: [PATCH 04/10] Buildings complete --- plugins/blueprint.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index 2689f4c69..092562f5d 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -5,6 +5,10 @@ #include #include +#include "modules/Buildings.h" +#include "modules/Gui.h" +#include "modules/MapCache.h" + #include "df/building_axle_horizontalst.h" #include "df/building_bridgest.h" #include "df/building_constructionst.h" @@ -16,10 +20,6 @@ #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; @@ -95,6 +95,9 @@ char get_tile_dig(MapExtras::MapCache mc, int32_t x, int32_t y, int32_t z) string get_tile_build(df::building* b) { + if (! b) + return " "; + string ret; switch(b->getType()) { case building_type::Armorstand: @@ -141,7 +144,7 @@ string get_tile_build(df::building* b) case building_type::Well: return "l"; case building_type::SiegeEngine: - return "i" + ((df::building_siegeenginest*) b)->type == df::siegeengine_type::Ballista ? "b" : "c"; + return ((df::building_siegeenginest*) b)->type == df::siegeengine_type::Ballista ? "ib" : "ic"; case building_type::Workshop: switch (((df::building_workshopst*) b)->type) { @@ -321,7 +324,7 @@ string get_tile_build(df::building* b) return "Tc"; case trap_type::TrackStop: df::building_trapst* ts = (df::building_trapst*) b; - string ret = "CS"; + ret = "CS"; if (ts->use_dump) { if (ts->dump_x_shift == 0) @@ -377,7 +380,7 @@ string get_tile_build(df::building* b) case building_type::AxleVertical: return "Mv"; case building_type::Rollers: - string ret = "Mr"; + ret = "Mr"; switch (((df::building_rollersst*) b)->direction) { case screw_pump_direction::FromNorth: From f315ee43a4a6481e06a818e6c3a71f109ab8d991 Mon Sep 17 00:00:00 2001 From: Chris Dombroski Date: Tue, 13 Jan 2015 14:28:28 -0500 Subject: [PATCH 05/10] Added stockpiles --- plugins/blueprint.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index 092562f5d..eb4802525 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -424,6 +424,50 @@ string get_tile_build(df::building* b) } } +char get_tile_place(df::building* b) +{ + if (! b || b->getType() != building_type::Stockpile) + return ' '; + df::building_stockpilest* sp = (df::building_stockpilest*) b; + 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: //multiple stockpile type + return ' '; + } +} + command_result do_transform(DFCoord start, DFCoord end, string name, phase last_phase) { ofstream dig, build, place, query; @@ -472,6 +516,7 @@ command_result do_transform(DFCoord start, DFCoord end, string name, phase last_ switch (last_phase) { case QUERY: case PLACE: + place << get_tile_place(b) << ','; case BUILD: build << get_tile_build(b) << ','; case DIG: From d0273b8eff3cfeeefcd7f01b02906a9a9727e7df Mon Sep 17 00:00:00 2001 From: Chris Dombroski Date: Tue, 13 Jan 2015 16:15:54 -0500 Subject: [PATCH 06/10] Now puts room designations in the query blueprint --- plugins/blueprint.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index eb4802525..4bd534d8a 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -468,6 +468,13 @@ char get_tile_place(df::building* b) } } +string get_tile_query(df::building* b) +{ + if (b && b->is_room) + return "r+"; + return " "; +} + command_result do_transform(DFCoord start, DFCoord end, string name, phase last_phase) { ofstream dig, build, place, query; @@ -515,6 +522,7 @@ command_result do_transform(DFCoord start, DFCoord end, string name, phase last_ df::building* b = DFHack::Buildings::findAtTile(DFCoord(x, y, z)); switch (last_phase) { case QUERY: + query << get_tile_query(b) << ','; case PLACE: place << get_tile_place(b) << ','; case BUILD: From 106612f3868b15e0f3e91faa2150e16063b6d3d7 Mon Sep 17 00:00:00 2001 From: Chris Dombroski Date: Wed, 14 Jan 2015 14:08:54 -0500 Subject: [PATCH 07/10] Use alternate qf syntax for output. --- plugins/blueprint.cpp | 173 ++++++++++++++++++++++++++++++------------ 1 file changed, 123 insertions(+), 50 deletions(-) diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index 4bd534d8a..c6611cef5 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -25,6 +25,7 @@ using std::endl; using std::vector; using std::ofstream; using std::swap; +using std::pair; using namespace DFHack; using namespace df::enums; @@ -63,6 +64,11 @@ command_result help(color_ostream &out) return CR_OK; } +pair get_building_size(df::building* b) +{ + return pair(b->x2 - b->x1 + 1, b->y2 - b->y1 + 1); +} + 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)); @@ -93,11 +99,15 @@ char get_tile_dig(MapExtras::MapCache mc, int32_t x, int32_t y, int32_t z) } } -string get_tile_build(df::building* b) +string get_tile_build(uint32_t x, uint32_t y, df::building* b) { if (! b) return " "; - string ret; + bool at_nw_corner = x == b->x1 && y == b->y1; + bool at_se_corner = x == b->x2 && y == b->y2; + bool at_center = x == b->centerx && y == b->centery; + pair size = get_building_size(b); + stringstream out = stringstream(); switch(b->getType()) { case building_type::Armorstand: @@ -116,7 +126,10 @@ string get_tile_build(df::building* b) return "h"; //case building_type::Kennel is missing case building_type::FarmPlot: - return "p"; + if(!at_nw_corner) + return "`"; + out << "p(" << size.first << "x" << size.second << ")"; + return out.str(); case building_type::Weaponrack: return "r"; case building_type::Statue: @@ -124,28 +137,47 @@ string get_tile_build(df::building* b) case building_type::Table: return "t"; case building_type::RoadPaved: - return "o"; + if(! at_nw_corner) + return "`"; + out << "o(" << size.first << "x" << size.second << ")"; + return out.str(); case building_type::RoadDirt: - return "O"; + if(! at_nw_corner) + return "`"; + out << "O(" << size.first << "x" << size.second << ")"; + return out.str(); case building_type::Bridge: + if(! at_nw_corner) + return "`"; switch(((df::building_bridgest*) b)->direction) { case df::building_bridgest::T_direction::Down: - return "gx"; + out << "gx"; + break; case df::building_bridgest::T_direction::Left: - return "ga"; + out << "ga"; + break; case df::building_bridgest::T_direction::Up: - return "gw"; + out << "gw"; + break; case df::building_bridgest::T_direction::Right: - return "gd"; + out << "gd"; + break; case df::building_bridgest::T_direction::Retracting: - return "gs"; + out << "gs"; + break; } + out << "(" << size.first << "x" << size.second << ")"; + return out.str(); case building_type::Well: return "l"; case building_type::SiegeEngine: + if (! at_center) + return "`"; return ((df::building_siegeenginest*) b)->type == df::siegeengine_type::Ballista ? "ib" : "ic"; case building_type::Workshop: + if (! at_center) + return "`"; switch (((df::building_workshopst*) b)->type) { case workshop_type::Leatherworks: @@ -194,9 +226,11 @@ string get_tile_build(df::building* b) return "wd"; case workshop_type::Custom: //can't do anything with custom workshop - return " "; + return "`"; } case building_type::Furnace: + if (! at_center) + return "`"; switch (((df::building_furnacest*) b)->type) { case furnace_type::WoodFurnace: @@ -215,7 +249,7 @@ string get_tile_build(df::building* b) return "en"; case furnace_type::Custom: //can't do anything with custom furnace - return " "; + return "`"; } case building_type::WindowGlass: return "y"; @@ -300,6 +334,8 @@ string get_tile_build(df::building* b) return "trackrampNSEW"; } case building_type::Shop: + if (! at_center) + return "`"; return "z"; case building_type::AnimalTrap: return "m"; @@ -308,6 +344,8 @@ string get_tile_build(df::building* b) case building_type::Cage: return "j"; case building_type::TradeDepot: + if (! at_center) + return "`"; return "D"; case building_type::Trap: switch (((df::building_trapst*) b)->trap_type) @@ -324,38 +362,40 @@ string get_tile_build(df::building* b) return "Tc"; case trap_type::TrackStop: df::building_trapst* ts = (df::building_trapst*) b; - ret = "CS"; + out << "CS"; if (ts->use_dump) { if (ts->dump_x_shift == 0) { if (ts->dump_y_shift > 0) - ret += "dd"; + out << "dd"; else - ret += "d"; + out << "d"; } else { if (ts->dump_x_shift > 0) - ret += "ddd"; + out << "ddd"; else - ret += "dddd"; + out << "dddd"; } } switch (ts->friction) { case 10: - ret += "a"; + out << "a"; case 50: - ret += "a"; + out << "a"; case 500: - ret += "a"; + out << "a"; case 10000: - ret += "a"; + out << "a"; } - return ret; + return out.str(); } case building_type::ScrewPump: + if (! at_se_corner) //screw pumps anchor at bottom/right + return "`"; switch (((df::building_screw_pumpst*) b)->direction) { case screw_pump_direction::FromNorth: @@ -368,31 +408,42 @@ string get_tile_build(df::building* b) return "Msh"; } case building_type::WaterWheel: + if (! at_center) + return "`"; //s swaps orientation which defaults to vertical - return "Mw" + ((df::building_water_wheelst*) b)->is_vertical ? "" : "s"; + return ((df::building_water_wheelst*) b)->is_vertical ? "Mw" : "Mws"; case building_type::Windmill: + if (! at_center) + return "`"; return "Mm"; case building_type::GearAssembly: return "Mg"; case building_type::AxleHorizontal: + if (! at_nw_corner) //a guess based on how constructions work + return "`"; //same as water wheel but reversed - return "Mh" + ((df::building_axle_horizontalst*) b)->is_vertical ? "s" : ""; + out << "Mh" << (((df::building_axle_horizontalst*) b)->is_vertical ? "s" : "") + << "(" << size.first << "x" << size.second << ")"; + return out.str(); case building_type::AxleVertical: return "Mv"; case building_type::Rollers: - ret = "Mr"; + if (! at_nw_corner) + return "`"; + out << "Mr"; switch (((df::building_rollersst*) b)->direction) { case screw_pump_direction::FromNorth: break; case screw_pump_direction::FromEast: - ret += "s"; + out << "s"; case screw_pump_direction::FromSouth: - ret += "s"; + out << "s"; case screw_pump_direction::FromWest: - ret += "s"; + out << "s"; } - return ret; + out << "(" << size.first << "x" << size.second << ")"; + return out.str(); case building_type::Support: return "S"; case building_type::ArcheryTarget: @@ -424,48 +475,70 @@ string get_tile_build(df::building* b) } } -char get_tile_place(df::building* b) +string get_tile_place(uint32_t x, uint32_t y, df::building* b) { if (! b || b->getType() != building_type::Stockpile) - return ' '; + return " "; + if (b->x1 != x || b->y1 != y) + return "`"; + pair size = get_building_size(b); df::building_stockpilest* sp = (df::building_stockpilest*) b; + stringstream out = stringstream(); switch (sp->settings.flags.whole) { case df::stockpile_group_set::mask_animals: - return 'a'; + out << "a"; + break; case df::stockpile_group_set::mask_food: - return 'f'; + out << "f"; + break; case df::stockpile_group_set::mask_furniture: - return 'u'; + out << "u"; + break; case df::stockpile_group_set::mask_corpses: - return 'y'; + out << "y"; + break; case df::stockpile_group_set::mask_refuse: - return 'r'; + out << "r"; + break; case df::stockpile_group_set::mask_wood: - return 'w'; + out << "w"; + break; case df::stockpile_group_set::mask_stone: - return 's'; + out << "s"; + break; case df::stockpile_group_set::mask_gems: - return 'e'; + out << "e"; + break; case df::stockpile_group_set::mask_bars_blocks: - return 'b'; + out << "b"; + break; case df::stockpile_group_set::mask_cloth: - return 'h'; + out << "h"; + break; case df::stockpile_group_set::mask_leather: - return 'l'; + out << "l"; + break; case df::stockpile_group_set::mask_ammo: - return 'z'; + out << "z"; + break; case df::stockpile_group_set::mask_coins: - return 'n'; + out << "n"; + break; case df::stockpile_group_set::mask_finished_goods: - return 'g'; + out << "g"; + break; case df::stockpile_group_set::mask_weapons: - return 'p'; + out << "p"; + break; case df::stockpile_group_set::mask_armor: - return 'd'; + out << "d"; + break; default: //multiple stockpile type - return ' '; + return "`"; } + out << "("<< size.first << "x" << size.second << ")"; + return out.str(); } string get_tile_query(df::building* b) @@ -524,9 +597,9 @@ command_result do_transform(DFCoord start, DFCoord end, string name, phase last_ case QUERY: query << get_tile_query(b) << ','; case PLACE: - place << get_tile_place(b) << ','; + place << get_tile_place(x, y, b) << ','; case BUILD: - build << get_tile_build(b) << ','; + build << get_tile_build(x, y, b) << ','; case DIG: dig << get_tile_dig(mc, x, y, z) << ','; } From da2224b0badfb6d8a4c95ab701192ba9f3f2f1a7 Mon Sep 17 00:00:00 2001 From: Chris Dombroski Date: Wed, 14 Jan 2015 14:58:15 -0500 Subject: [PATCH 08/10] Changed how parameters are parsed. --- plugins/blueprint.cpp | 95 ++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/plugins/blueprint.cpp b/plugins/blueprint.cpp index c6611cef5..60cf8dec7 100644 --- a/plugins/blueprint.cpp +++ b/plugins/blueprint.cpp @@ -25,13 +25,14 @@ using std::endl; using std::vector; using std::ofstream; using std::swap; +using std::find; using std::pair; using namespace DFHack; using namespace df::enums; DFHACK_PLUGIN("blueprint"); -enum phase {DIG, BUILD, PLACE, QUERY}; +enum phase {DIG=1, BUILD=2, PLACE=4, QUERY=8}; command_result blueprint(color_ostream &out, vector ¶meters); @@ -48,7 +49,7 @@ DFhackCExport command_result plugin_shutdown(color_ostream &out) command_result help(color_ostream &out) { - out << "blueprint width height depth name [dig [build [place [query]]]]" << endl + out << "blueprint width height depth name [dig] [build] [place] [query]" << endl << " width, height, depth: area to translate in tiles" << endl << " name: base name for blueprint files" << endl << " dig: generate blueprints for digging" << endl @@ -548,21 +549,26 @@ string get_tile_query(df::building* b) return " "; } -command_result do_transform(DFCoord start, DFCoord end, string name, phase last_phase) +command_result do_transform(DFCoord start, DFCoord end, string name, uint32_t phases) { ofstream dig, build, place, query; - switch (last_phase) + if (phases & QUERY) { - case QUERY: query = ofstream(name + "-query.csv", ofstream::trunc); query << "#query" << endl; - case PLACE: + } + if (phases & PLACE) + { place = ofstream(name + "-place.csv", ofstream::trunc); place << "#place" << endl; - case BUILD: + } + if (phases & BUILD) + { build = ofstream(name + "-build.csv", ofstream::trunc); build << "#build" << endl; - case DIG: + } + if (phases & DIG) + { dig = ofstream(name + "-dig.csv", ofstream::trunc); dig << "#dig" << endl; } @@ -593,54 +599,53 @@ 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: + if (phases & QUERY) query << get_tile_query(b) << ','; - case PLACE: + if (phases & PLACE) place << get_tile_place(x, y, b) << ','; - case BUILD: + if (phases & BUILD) build << get_tile_build(x, y, b) << ','; - case DIG: + if (phases & DIG) dig << get_tile_dig(mc, x, y, z) << ','; - } } - switch (last_phase) { - case QUERY: + if (phases & QUERY) query << "#" << endl; - case PLACE: + if (phases & PLACE) place << "#" << endl; - case BUILD: + if (phases & BUILD) build << "#" << endl; - case DIG: + if (phases & DIG) dig << "#" << endl; - } } if (z < end.z - 1) - switch (last_phase) { - case QUERY: + { + if (phases & QUERY) query << "#<" << endl; - case PLACE: + if (phases & PLACE) place << "#<" << endl; - case BUILD: + if (phases & BUILD) build << "#<" << endl; - case DIG: + if (phases & DIG) dig << "#<" << endl; } } - switch (last_phase) { - case QUERY: + if (phases & QUERY) query.close(); - case PLACE: + if (phases & PLACE) place.close(); - case BUILD: + if (phases & BUILD) build.close(); - case DIG: + if (phases & DIG) dig.close(); - } return CR_OK; } -command_result blueprint(color_ostream &out, vector ¶meters) +bool cmd_option_exists(vector& parameters, const string& option) +{ + return find(parameters.begin(), parameters.end(), option) != parameters.end(); +} + +command_result blueprint(color_ostream &out, vector ¶meters) { if (parameters.size() < 4 || parameters.size() > 8) return help(out); @@ -658,18 +663,16 @@ command_result blueprint(color_ostream &out, vector ¶meters) } DFCoord start (x, y, z); DFCoord end (x + stoi(parameters[0]), y + stoi(parameters[1]), z + stoi(parameters[2])); - switch(parameters.size()) - { - case 4: - case 8: - return do_transform(start, end, parameters[3], QUERY); - case 5: - return do_transform(start, end, parameters[3], DIG); - case 6: - return do_transform(start, end, parameters[3], BUILD); - case 7: - return do_transform(start, end, parameters[3], PLACE); - default: //wtf? - return CR_FAILURE; - } + if (parameters.size() == 4) + return do_transform(start, end, parameters[3], DIG | BUILD | PLACE | QUERY); + uint32_t option = 0; + if (cmd_option_exists(parameters, "dig")) + option |= DIG; + if (cmd_option_exists(parameters, "build")) + option |= BUILD; + if (cmd_option_exists(parameters, "place")) + option |= PLACE; + if (cmd_option_exists(parameters, "query")) + option |= QUERY; + return do_transform(start, end, parameters[3], option); } \ No newline at end of file From bc30d7cdda48126e3cda7a4b409f87782322be9f Mon Sep 17 00:00:00 2001 From: Chris Dombroski Date: Wed, 14 Jan 2015 15:34:14 -0500 Subject: [PATCH 09/10] Update documentation for new plugin --- Readme.html | 471 +++++++++++++++++++++++++++++++--------------------- Readme.rst | 17 ++ 2 files changed, 302 insertions(+), 186 deletions(-) diff --git a/Readme.html b/Readme.html index 558c2a662..47f25f636 100644 --- a/Readme.html +++ b/Readme.html @@ -481,121 +481,126 @@ access DF memory and allow for easier development of new tools.

  • mapexport
  • dwarfexport
  • exportlegends
  • +
  • blueprint
  • -
  • Job management
      -
    • job
    • -
    • job-material
    • -
    • job-duplicate
    • -
    • stockflow
    • -
    • workflow
        -
      • Function
      • -
      • Constraint format
      • -
      • Constraint examples
      • +
      • Job management
      • -
      • Fortress activity management
          -
        • seedwatch
        • -
        • zone
            -
          • Usage with single units
          • -
          • Usage with filters
          • -
          • Mass-renaming
          • -
          • Cage zones
          • -
          • Examples
          • +
          • Fortress activity management
          • -
          • Other
          • -
          • Scripts
              -
            • fix/*
            • -
            • gui/*
            • -
            • binpatch
            • -
            • create-items
            • -
            • digfort
            • -
            • drain-aquifer
            • -
            • deathcause
            • -
            • dfstatus
            • -
            • embark
            • -
            • exterminate
            • -
            • growcrops
            • -
            • lever
            • -
            • locate-ore
            • -
            • lua
            • -
            • masspit
            • -
            • multicmd
            • -
            • quicksave
            • -
            • remove-stress
            • -
            • setfps
            • -
            • siren
            • -
            • soundsense-season
            • -
            • source
            • -
            • superdwarf
            • -
            • stripcaged
            • -
            • teleport
            • -
            • undump-buildings
            • +
            • Scripts
            • -
            • modtools
            • -
            • In-game interface tools
                -
              • Dwarf Manipulator
              • -
              • Search
              • -
              • AutoMaterial
              • -
              • Stockpile Automation
              • -
              • Track Stop Menu
              • -
              • gui/advfort
              • -
              • gui/assign-rack
              • -
              • gui/choose-weapons
              • -
              • gui/clone-uniform
              • -
              • gui/companion-order
              • -
              • gui/gm-editor
              • -
              • Hotkeys
              • -
              • Hotkeys
              • -
              • Stockpile Automation
              • -
              • Stockpile Automation
              • -
              • gui/liquids
              • -
              • gui/mechanisms
              • -
              • gui/mod-manager
              • -
              • gui/rename
              • -
              • gui/room-list
              • -
              • gui/guide-path
              • -
              • gui/workflow
              • -
              • gui/workshop-job
              • +
              • modtools
              • +
              • In-game interface tools
              • -
              • Behavior Mods
                  -
                • Siege Engine
                  -

                  job-duplicate

                  +

                  job-duplicate

                  Duplicate the selected job in a workshop:

                  • In 'q' mode, when a job is highlighted within a workshop or furnace building, @@ -2244,7 +2278,7 @@ instantly duplicates the job.
                  -

                  stockflow

                  +

                  stockflow

                  Allows the fortress bookkeeper to queue jobs through the manager, based on space or items available in stockpiles.

                  Usage:

                  @@ -2272,7 +2306,7 @@ number of identical orders already in the queue.

                  waiting for the bookkeeper.

                  -

                  workflow

                  +

                  workflow

                  Manage control of repeat jobs.

                  Usage:

                  @@ -2302,7 +2336,7 @@ this list can be copied to a file, and then reloaded using the
                  Delete all constraints.
                  -

                  Function

                  +

                  Function

                  When the plugin is enabled, it protects all repeat jobs from removal. If they do disappear due to any cause, they are immediately re-added to their workshop and suspended.

                  @@ -2315,7 +2349,7 @@ the frequency of jobs being toggled.

                  in the game UI.

                  -

                  Constraint format

                  +

                  Constraint format

                  The contstraint spec consists of 4 parts, separated with '/' characters:

                   ITEM[:SUBTYPE]/[GENERIC_MAT,...]/[SPECIFIC_MAT:...]/[LOCAL,<quality>]
                  @@ -2344,7 +2378,7 @@ be used to ignore imported items or items below a certain quality.

                -

                Constraint examples

                +

                Constraint examples

                Keep metal bolts within 900-1000, and wood/bone within 150-200:

                 workflow amount AMMO:ITEM_AMMO_BOLTS/METAL 1000 100
                @@ -2393,9 +2427,9 @@ workflow count CRAFTS///LOCAL,EXCEPTIONAL 100 90
                 
                -

                Fortress activity management

                +

                Fortress activity management

                -

                seedwatch

                +

                seedwatch

                Watches the numbers of seeds available and enables/disables seed and plant cooking.

                Each plant type can be assigned a limit. If their number falls below that limit, the plants and seeds of that type will be excluded from cookery. @@ -2430,7 +2464,7 @@ You have to reactivate with 'seedwatch start' after you load the game.

                -

                zone

                +

                zone

                Helps a bit with managing activity zones (pens, pastures and pits) and cages.

                Options:

                @@ -2525,7 +2559,7 @@ for war/hunt). Negatable.
                -

                Usage with single units

                +

                Usage with single units

                One convenient way to use the zone tool is to bind the command 'zone assign' to a hotkey, maybe also the command 'zone set'. Place the in-game cursor over a pen/pasture or pit, use 'zone set' to mark it. Then you can select units @@ -2534,7 +2568,7 @@ and use 'zone assign' to assign them to their new home. Allows pitting your own dwarves, by the way.

                -

                Usage with filters

                +

                Usage with filters

                All filters can be used together with the 'assign' command.

                Restrictions: It's not possible to assign units who are inside built cages or chained because in most cases that won't be desirable anyways. @@ -2552,14 +2586,14 @@ are not properly added to your own stocks; slaughtering them should work).

                Most filters can be negated (e.g. 'not grazer' -> race is not a grazer).

                -

                Mass-renaming

                +

                Mass-renaming

                Using the 'nick' command you can set the same nickname for multiple units. If used without 'assign', 'all' or 'count' it will rename all units in the current default target zone. Combined with 'assign', 'all' or 'count' (and further optional filters) it will rename units matching the filter conditions.

                -

                Cage zones

                +

                Cage zones

                Using the 'tocages' command you can assign units to a set of cages, for example a room next to your butcher shop(s). They will be spread evenly among available cages to optimize hauling to and butchering from them. For this to work you need @@ -2570,7 +2604,7 @@ would make no sense, but can be used together with 'nick' or 'remnick' and all the usual filters.

                -

                Examples

                +

                Examples

                zone assign all own ALPACA minage 3 maxage 10
                Assign all own alpacas who are between 3 and 10 years old to the selected @@ -2596,7 +2630,7 @@ on the current default zone.
                -

                autonestbox

                +

                autonestbox

                Assigns unpastured female egg-layers to nestbox zones. Requires that you create pen/pasture zones above nestboxes. If the pen is bigger than 1x1 the nestbox must be in the top left corner. Only 1 unit will be assigned per pen, regardless @@ -2623,7 +2657,7 @@ frames between runs.

                -

                autobutcher

                +

                autobutcher

                Assigns lifestock for slaughter once it reaches a specific count. Requires that you add the target race(s) to a watch list. Only tame units will be processed.

                Named units will be completely ignored (to protect specific animals from @@ -2729,7 +2763,7 @@ autobutcher.bat

                -

                autochop

                +

                autochop

                Automatically manage tree cutting designation to keep available logs withing given quotas.

                Open the dashboard by running:

                @@ -2747,7 +2781,7 @@ enable getplants menu.

                -

                autolabor

                +

                autolabor

                Automatically manage dwarf labors to efficiently complete jobs. Autolabor tries to keep as many dwarves as possible busy but also tries to have dwarves specialize in specific skills.

                @@ -2843,14 +2877,14 @@ and then assign additional dwarfs that meet any of these conditions:

                -

                Other

                +

                Other

                -

                catsplosion

                +

                catsplosion

                Makes cats just multiply. It is not a good idea to run this more than once or twice.

                -

                dfusion

                +

                dfusion

                This is the DFusion lua plugin system by Warmist, running as a DFHack plugin. There are two parts to this plugin: an interactive script that shows a text based menu and lua modules. Some of the functionality of is intentionaly left out of the menu:

                @@ -2872,7 +2906,7 @@ twice.

                -

                embark-tools

                +

                embark-tools

                A collection of embark-related tools.

                Usage:

                @@ -2888,7 +2922,7 @@ embark-tools enable/disable tool [tool]...
                 
                 
                -

                petcapRemover

                +

                petcapRemover

                This plugin allows you to remove or raise the pet population cap. In vanilla DF, pets will not reproduce unless the population is below 50 and the number of children of that species is below a certain percentage. This plugin allows removing the second restriction and removing or raising the first. Pets still require PET or PET_EXOTIC tags in order to reproduce. Type help petcapRemover for exact usage. In order to make population more stable and avoid sudden population booms as you go below the raised population cap, this plugin counts pregnancies toward the new population cap. It can still go over, but only in the case of multiple births.

                petcapRemover
                @@ -2902,7 +2936,7 @@ embark-tools enable/disable tool [tool]...
                -

                misery

                +

                misery

                When enabled, every new negative dwarven thought will be multiplied by a factor (2 by default).

                Usage:

                @@ -2924,7 +2958,7 @@ embark-tools enable/disable tool [tool]...
                -

                strangemood

                +

                strangemood

                Creates a strange mood job the same way the game itself normally does it.

                Options:

                @@ -2946,13 +2980,13 @@ Valid values are "miner", "carpenter", "engraver",

                Known limitations: if the selected unit is currently performing a job, the mood will not be started.

                -

                log-region

                +

                log-region

                When enabled in dfhack.init, each time a fort is loaded identifying information will be written to the gamelog. Assists in parsing the file if you switch between forts, and adds information for story-building.

                -

                Scripts

                +

                Scripts

                Lua or ruby scripts placed in the hack/scripts/ directory are considered for execution as if they were native DFHack commands. They are listed at the end of the 'ls' command output.

                @@ -2961,7 +2995,7 @@ only be listed by ls if called as 'ls -a'. This is intended as a way to hide scripts that are obscure, developer-oriented, or should be used as keybindings.

                Some notable scripts:

                -

                fix/*

                +

                fix/*

                Scripts in this subdirectory fix various bugs and issues, some of them obscure.

                • fix/blood-del

                  @@ -3007,17 +3041,33 @@ state however, use tweak stable-t
                -

                gui/*

                +

                gui/*

                Scripts that implement dialogs inserted into the main game window are put in this directory.

                • gui/hack-wish

                  A graphical interface for creating items.

                • +
                • gui/stockpiles

                  +

                  Load and save stockpile settings from the 'q' menu. +Usage:

                  +
                  +

                  System Message: ERROR/3 (Readme.rst, line 2225)

                  +

                  Unexpected indentation.

                  +
                  +
                  +

                  gui/stockpiles -save to save the current stockpile +gui/stockpiles -load to load settings into the current stockpile +gui/stockpiles -dir <path> set the default directory to save settings into +gui/stockpiles -help to see this message

                  +
                  +
                +

                Don't forget to enable stockpiles and create the stocksettings directory in +the DF folder before trying to use this plugin.

                -

                binpatch

                +

                binpatch

                Checks, applies or removes binary patches directly in memory at runtime:

                 binpatch check/apply/remove <patchname>
                @@ -3027,7 +3077,7 @@ script uses hack/patches/<df-v
                 the version appropriate for the currently loaded executable.

                -

                create-items

                +

                create-items

                Spawn arbitrary items under the cursor.

                The first argument gives the item category, the second gives the material, and the optionnal third gives the number of items to create (defaults to 20).

                @@ -3049,7 +3099,7 @@ create-items bar adamantine
                -

                digfort

                +

                digfort

                A script to designate an area for digging according to a plan in csv format.

                This script, inspired from quickfort, can designate an area for digging. Your plan should be stored in a .csv file like this:

                @@ -3071,25 +3121,25 @@ as an offset for the pattern: instead of starting at the cursor, it will start Dwarf Fortress.exe is found).

                -

                drain-aquifer

                +

                drain-aquifer

                Remove all 'aquifer' tag from the map blocks. Irreversible.

                -

                deathcause

                +

                deathcause

                Focus a body part ingame, and this script will display the cause of death of the creature. Also works when selecting units from the 'u'nitlist viewscreen.

                -

                dfstatus

                +

                dfstatus

                Show a quick overview of critical stock quantities, including food, dirnks, wood, and various bars.

                -

                embark

                +

                embark

                Allows to embark anywhere. Currently windows only.

                -

                exterminate

                +

                exterminate

                Kills any unit of a given race.

                With no argument, lists the available races and count eligible targets.

                With the special argument him, targets only the selected creature.

                @@ -3120,8 +3170,35 @@ exterminate him exterminate elve magma
                +
                +

                fortplan

                +

                Usage: fortplan [filename]

                +

                Designates furniture for building according to a .csv file with +quickfort-style syntax. Companion to digfort.

                +

                The first line of the file must contain the following:

                +
                +#build start(X; Y; <start location description>)
                +

                ...where X and Y are the offset from the top-left corner of the file's area +where the in-game cursor should be located, and <start location description> +is an optional description of where that is. You may also leave a description +of the contents of the file itself following the closing parenthesis on the +same line.

                +

                The syntax of the file itself is similar to digfort or quickfort. At present, +only buildings constructed of an item with the same name as the building +are supported. All other characters are ignored. For example:

                +
                +,,d,`,` +,f,,t,` +,s,b,c,
                +

                This section of a file would designate for construction a door and some +furniture inside a bedroom: specifically, clockwise from top left, a cabinet, +a table, a chair, a bed, and a statue.

                +

                All of the building designation uses Planning Mode, so you do not need to +have the items available to construct all the buildings when you run +fortplan with the .csv file.

                +
                -

                growcrops

                +

                growcrops

                Instantly grow seeds inside farming plots.

                With no argument, this command list the various seed types currently in use in your farming plots. @@ -3132,8 +3209,20 @@ harvested. You can change the number with a 2nd argument.

                growcrops plump 40
                +
                +

                hfs-pit

                +

                Creates a pit to the underworld at the cursor.

                +

                Takes three arguments: diameter of the pit in tiles, whether to wall off +the pit, and whether to insert stairs. If no arguments are given, the default +is "hfs-pit 1 0 0", ie single-tile wide with no walls or stairs.

                +
                +hfs-pit 4 0 1 +hfs-pit 2 1 0
                +

                First example is a four-across pit with stairs but no walls; second is a +two-across pit with stairs but no walls.

                +
                -

                lever

                +

                lever

                Allow manipulation of in-game levers from the dfhack console.

                Can list levers, including state and links, with:

                @@ -3147,7 +3236,7 @@ lever pull 42 --now
                 
                -

                locate-ore

                +

                locate-ore

                Scan the map for metal ores.

                Finds and designate for digging one tile of a specific metal ore. Only works for native metal ores, does not handle reaction stuff (eg STEEL).

                @@ -3160,7 +3249,7 @@ locate-ore iron
                -

                lua

                +

                lua

                There are the following ways to invoke this command:

                1. lua (without any parameters)

                  @@ -3179,14 +3268,14 @@ directory. If the filename is not supplied, it loads "dfhack.lua".

                -

                masspit

                +

                masspit

                Designate all creatures in cages on top of a pit/pond activity zone for pitting. Works best with an animal stockpile on top of the zone.

                Works with a zone number as argument (eg Activity Zone #6 -> masspit 6) or with the game cursor on top of the area.

                -

                multicmd

                +

                multicmd

                Run multiple dfhack commands. The argument is split around the character ; and all parts are run sequencially as independent dfhack commands. Useful for hotkeys.

                @@ -3195,22 +3284,32 @@ dfhack commands. Useful for hotkeys.

                multicmd locate-ore iron ; digv
                +
                +

                position

                +

                Reports the current time: date, clock time, month, and season. Also reports +location: z-level, cursor position, window size, and mouse location.

                +
                +
                +

                putontable

                +

                Makes item appear on the table, like in adventure mode shops. Arguments: '-a' +or '--all' for all items.

                +
                -

                quicksave

                +

                quicksave

                If called in dwarf mode, makes DF immediately auto-save the game by setting a flag normally used in seasonal auto-save.

                -

                remove-stress

                +

                remove-stress

                Sets stress to -1,000,000; the normal range is 0 to 500,000 with very stable or very stressed dwarves taking on negative or greater values respectively. Applies to the selected unit, or use "remove-stress -all" to apply to all units.

                -

                setfps

                +

                setfps

                Run setfps <number> to set the FPS cap at runtime, in case you want to watch combat in slow motion or something :)

                -

                siren

                +

                siren

                Wakes up sleeping units, cancels breaks and stops parties either everywhere, or in the burrows given as arguments. In return, adds bad thoughts about noise, tiredness and lack of protection. Also, the units with interrupted @@ -3218,7 +3317,7 @@ breaks will go on break again a lot sooner. The script is intended for emergencies, e.g. when a siege appears, and all your military is partying.

                -

                soundsense-season

                +

                soundsense-season

                It is a well known issue that Soundsense cannot detect the correct current season when a savegame is loaded and has to play random season music until a season switch occurs.

                @@ -3227,7 +3326,7 @@ to gamelog.txt on every map load to fix this. For best results call the script from dfhack.init.

                -

                source

                +

                source

                Create an infinite magma or water source or drain on a tile.

                This script registers a map tile as a liquid source, and every 12 game ticks that tile receives or remove 1 new unit of flow based on the configuration.

                @@ -3249,7 +3348,7 @@ source add water 0 - water drain
                -

                superdwarf

                +

                superdwarf

                Similar to fastdwarf, per-creature.

                To make any creature superfast, target it ingame using 'v' and:

                @@ -3259,7 +3358,7 @@ superdwarf add
                 

                This plugin also shortens the 'sleeping' and 'on break' periods of targets.

                -

                stripcaged

                +

                stripcaged

                For dumping items inside cages. Will mark selected items for dumping, then a dwarf may come and actually dump it. See also autodump.

                With the items argument, only dumps items laying in the cage, excluding @@ -3277,7 +3376,7 @@ stripcaged weapons 25321 34228

                -

                teleport

                +

                teleport

                Teleports a unit to given coordinates.

                Examples:

                @@ -3287,12 +3386,12 @@ teleport -unit 1234 -x 56 -y 115 -z 26  - teleports unit 1234 to 56,115,26
                 
                -

                undump-buildings

                +

                undump-buildings

                Undesignates building base materials for dumping.

                -

                modtools

                +

                modtools

                These scripts are mostly useful for raw modders and scripters. They all have standard arguments: arguments are of the form tool -argName1 argVal1 -argName2 argVal2. This is equivalent to tool -argName2 argVal2 -argName1 argVal1. It is not necessary to provide a value to an argument name: tool -argName3 is fine. Supplying the same argument name multiple times will result in an error. Argument names are preceded with a dash. The -help argument will print a descriptive usage string describing the nature of the arguments. For multiple word argument values, brackets must be used: tool -argName4 [ sadf1 sadf2 sadf3 ]. In order to allow passing literal braces as part of the argument, backslashes are used: tool -argName4 [ \] asdf \foo ] sets argName4 to \] asdf foo. The *-trigger scripts have a similar policy with backslashes.

                • add-syndrome

                  @@ -3349,7 +3448,7 @@ teleport -unit 1234 -x 56 -y 115 -z 26 - teleports unit 1234 to 56,115,26
                -

                In-game interface tools

                +

                In-game interface tools

                These tools work by displaying dialogs or overlays in the game window, and are mostly implemented by lua scripts.

                @@ -3364,7 +3463,7 @@ guideline because it arguably just fixes small usability bugs in the game UI.

                -

                Dwarf Manipulator

                +

                Dwarf Manipulator

                Implemented by the 'manipulator' plugin.

                To activate, open the unit screen and press 'l'.

                images/manipulator.png @@ -3405,7 +3504,7 @@ cursor onto that cell instead of toggling it. directly to the main dwarf mode screen.

                -

                AutoMaterial

                +

                AutoMaterial

                Implemented by the 'automaterial' plugin.

                This makes building constructions (walls, floors, fortifications, etc) a little bit easier by saving you from having to trawl through long lists of materials each time @@ -3464,7 +3563,7 @@ materials, it returns you back to this screen. If you use this along with severa enabled materials, you should be able to place complex constructions more conveniently.

                -

                Stockpile Automation

                +

                Stockpile Automation

                Enable the automelt or autotrade plugins in your dfhack.init with:

                 enable automelt
                @@ -3475,7 +3574,7 @@ When automelt is enabled for a stockpile, any meltable items placed in it will b
                 When autotrade is enabled for a stockpile, any items placed in it will be designated to be taken to the Trade Depot whenever merchants are on the map.

                -

                Track Stop Menu

                +

                Track Stop Menu

                The q menu of track stops is completely blank by default. To enable one:

                 enable trackstop
                @@ -3489,7 +3588,7 @@ It re-uses the keybindings from the track stop building interface:

                -

                gui/advfort

                +

                gui/advfort

                This script allows to perform jobs in adventure mode. For more complete help press '?' while script is running. It's most confortable to use this as a keybinding. (e.g. keybinding set Ctrl-T gui/advfort). Possible arguments:

                @@ -3508,7 +3607,7 @@ implies -a
                -

                gui/assign-rack

                +

                gui/assign-rack

                Bind to a key (the example config uses P), and activate when viewing a weapon rack in the 'q' mode.

                images/assign-rack.png @@ -3532,7 +3631,7 @@ the intended user. In order to aid in the choice, it shows the number of currently assigned racks for every valid squad.

                -

                gui/choose-weapons

                +

                gui/choose-weapons

                Bind to a key (the example config uses Ctrl-W), and activate in the Equip->View/Customize page of the military screen.

                Depending on the cursor location, it rewrites all 'individual choice weapon' entries @@ -3543,14 +3642,14 @@ only that entry, and does it even if it is not 'individual choice'.

                and may lead to inappropriate weapons being selected.

                -

                gui/clone-uniform

                +

                gui/clone-uniform

                Bind to a key (the example config uses Ctrl-C), and activate in the Uniforms page of the military screen with the cursor in the leftmost list.

                When invoked, the script duplicates the currently selected uniform template, and selects the newly created copy.

                -

                gui/companion-order

                +

                gui/companion-order

                A script to issue orders for companions. Select companions with lower case chars, issue orders with upper case. Must be in look or talk mode to issue command on tile.

                images/companion-order.png @@ -3566,7 +3665,7 @@ case. Must be in look or talk mode to issue command on tile.

                -

                gui/gm-editor

                +

                gui/gm-editor

                There are three ways to open this editor:

                • using gui/gm-editor command/keybinding - opens editor on what is selected @@ -3581,7 +3680,7 @@ the same as version above.
                • in-game help.

                -

                Hotkeys

                +

                Hotkeys

                Opens an in-game screen showing DFHack keybindings that are valid in the current mode.

                images/hotkeys.png

                Type hotkeys into the DFHack console to open the screen, or bind the command to a @@ -3591,7 +3690,7 @@ keybinding add Ctrl-F1 hotkeys

                -

                Hotkeys

                +

                Hotkeys

                Opens an in-game screen showing DFHack keybindings that are valid in the current mode.

                images/hotkeys.png

                Type hotkeys into the DFHack console to open the screen, or bind the command to a @@ -3600,7 +3699,7 @@ globally active hotkey in dfhack.init, e.g.:

                keybinding add Ctrl-F1 hotkeys
                -

                Stockpile Automation

                +

                Stockpile Automation

                Enable the autodump plugin in your dfhack.init with
                enable autodump
                @@ -3609,7 +3708,7 @@ globally active hotkey in dfhack.init, e.g.:

                Any items placed in this stockpile will be designated to be dumped.

                -

                Stockpile Automation

                +

                Stockpile Automation

                Enable the automelt plugin in your dfhack.init with
                enable automelt
                @@ -3618,7 +3717,7 @@ Any items placed in this stockpile will be designated to be dumped.

                Any items placed in this stockpile will be designated to be melted.

                -

                gui/liquids

                +

                gui/liquids

                To use, bind to a key (the example config uses Alt-L) and activate in the 'k' mode.

                images/liquids.png

                This script is a gui front-end to the liquids plugin and works similar to it, @@ -3638,7 +3737,7 @@ rivers power water wheels even when full and technically not flowing.

                After setting up the desired operations using the described keys, use Enter to apply them.

                -

                gui/mechanisms

                +

                gui/mechanisms

                To use, bind to a key (the example config uses Ctrl-M) and activate in the 'q' mode.

                images/mechanisms.png

                Lists mechanisms connected to the building, and their links. Navigating the list centers @@ -3648,13 +3747,13 @@ focus on the current one. Shift-Enter has an effect equivalent to pressing Enter re-entering the mechanisms ui.

                -

                gui/mod-manager

                +

                gui/mod-manager

                A way to simply install and remove small mods. It looks for specially formatted mods in df subfolder 'mods'. Mods are not included, for example mods see: github mini mod repository

                images/mod-manager.png
                -

                gui/rename

                +

                gui/rename

                Backed by the rename plugin, this script allows entering the desired name via a simple dialog in the game ui.

                  @@ -3677,7 +3776,7 @@ their species string.

                  unit profession change to Ctrl-Shift-T.

                -

                gui/room-list

                +

                gui/room-list

                To use, bind to a key (the example config uses Alt-R) and activate in the 'q' mode, either immediately or after opening the assign owner page.

                images/room-list.png @@ -3685,7 +3784,7 @@ either immediately or after opening the assign owner page.

                list, and allows unassigning them.

                -

                gui/guide-path

                +

                gui/guide-path

                Bind to a key (the example config uses Alt-P), and activate in the Hauling menu with the cursor over a Guide order.

                images/guide-path.png @@ -3693,7 +3792,7 @@ the cursor over a Guide order.

                computes it when the order is executed for the first time.

                -

                gui/workflow

                +

                gui/workflow

                Bind to a key (the example config uses Alt-W), and activate with a job selected in a workshop in the 'q' mode.

                images/workflow.png @@ -3740,7 +3839,7 @@ the current stock value. The bright green dashed line is the target limit (maximum) and the dark green line is that minus the gap (minimum).

                -

                gui/workshop-job

                +

                gui/workshop-job

                Bind to a key (the example config uses Alt-A), and activate with a job selected in a workshop in the 'q' mode.

                images/workshop-job.png @@ -3777,7 +3876,7 @@ you have to unset the material first.

                -

                Behavior Mods

                +

                Behavior Mods

                These plugins, when activated via configuration UI or by detecting certain structures in RAWs, modify the game engine behavior concerning the target objects to add features not otherwise present.

                @@ -3788,20 +3887,20 @@ technical challenge, and do not represent any long-term plans to produce more similar modifications of the game.

                -

                Siege Engine

                +

                Siege Engine

                The siege-engine plugin enables siege engines to be linked to stockpiles, and aimed at an arbitrary rectangular area across Z levels, instead of the original four directions. Also, catapults can be ordered to load arbitrary objects, not just stones.

                -

                Rationale

                +

                Rationale

                Siege engines are a very interesting feature, but sadly almost useless in the current state because they haven't been updated since 2D and can only aim in four directions. This is an attempt to bring them more up to date until Toady has time to work on it. Actual improvements, e.g. like making siegers bring their own, are something only Toady can do.

                -

                Configuration UI

                +

                Configuration UI

                The configuration front-end to the plugin is implemented by the gui/siege-engine script. Bind it to a key (the example config uses Alt-A) and activate after selecting a siege engine in 'q' mode.

                @@ -3824,7 +3923,7 @@ menu.

                -

                Power Meter

                +

                Power Meter

                The power-meter plugin implements a modified pressure plate that detects power being supplied to gear boxes built in the four adjacent N/S/W/E tiles.

                The configuration front-end is implemented by the gui/power-meter script. Bind it to a @@ -3835,11 +3934,11 @@ in the build menu.

                configuration page, but configures parameters relevant to the modded power meter building.

                -

                Steam Engine

                +

                Steam Engine

                The steam-engine plugin detects custom workshops with STEAM_ENGINE in their token, and turns them into real steam engines.

                -

                Rationale

                +

                Rationale

                The vanilla game contains only water wheels and windmills as sources of power, but windmills give relatively little power, and water wheels require flowing water, which must either be a real river and thus immovable and @@ -3850,7 +3949,7 @@ it can be done just by combining existing features of the game engine in a new way with some glue code and a bit of custom logic.

                -

                Construction

                +

                Construction

                The workshop needs water as its input, which it takes via a passable floor tile below it, like usual magma workshops do. The magma version also needs magma.

                @@ -3874,7 +3973,7 @@ short axles that can be built later than both of the engines.

                -

                Operation

                +

                Operation

                In order to operate the engine, queue the Stoke Boiler job (optionally on repeat). A furnace operator will come, possibly bringing a bar of fuel, and perform it. As a result, a "boiling water" item will appear @@ -3905,7 +4004,7 @@ decrease it by further 4%, and also decrease the whole steam use rate by 10%.

                -

                Explosions

                +

                Explosions

                The engine must be constructed using barrel, pipe and piston from fire-safe, or in the magma version magma-safe metals.

                During operation weak parts get gradually worn out, and @@ -3914,7 +4013,7 @@ toppled during operation by a building destroyer, or a tantruming dwarf.

                -

                Save files

                +

                Save files

                It should be safe to load and view engine-using fortresses from a DF version without DFHack installed, except that in such case the engines won't work. However actually making modifications @@ -3925,7 +4024,7 @@ being generated.

                -

                Add Spatter

                +

                Add Spatter

                This plugin makes reactions with names starting with SPATTER_ADD_ produce contaminants on the items instead of improvements. The produced contaminants are immune to being washed away by water or destroyed by diff --git a/Readme.rst b/Readme.rst index 609a98dcd..87cd92126 100644 --- a/Readme.rst +++ b/Readme.rst @@ -1477,6 +1477,23 @@ Options: :maps: Exports all seventeen detailed maps :all: Equivalent to calling all of the above, in that order +blueprint +--------- +Exports a portion of your fortress into QuickFort style blueprint files.:: + + blueprint [dig] [build] [place] [query] + +Options: + +:x,y,z: Size of map area to export +:name: Name of export files +:dig: Export dig commands to "-dig.csv" +:build: Export build commands to "-build.csv" +:place: Export stockpile commands to "-place.csv" +:query: Export query commands to "-query.csv" + +If only region and name are given, all exports are performed. + Job management ============== From 6b3e6a6bdb812764332395e463db4ef7c0f49690 Mon Sep 17 00:00:00 2001 From: Chris Dombroski Date: Wed, 14 Jan 2015 19:29:06 -0500 Subject: [PATCH 10/10] Update NEWS for blueprint plugin --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 817ca1392..1a018c0c0 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ +DFHack 0.40.24-r1 + New Plugins + blueprint: export part of your fortress to quickfort .csv files DFHack 0.40.23-r1 Internals plugins will not be loaded if globals they specify as required are not located (should prevent some crashes)