Show a quick overview of critical stock quantities, including food, dirnks, wood, and various bars.
-
-
+
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 15933e0f6..d5c1e026b 100644
--- a/Readme.rst
+++ b/Readme.rst
@@ -2273,10 +2273,6 @@ dfstatus
========
Show a quick overview of critical stock quantities, including food, dirnks, wood, and various bars.
-embark
-======
-Allows to embark anywhere. Currently windows only.
-
exterminate
===========
Kills any unit of a given race.
From c39cf1fb49aee87bd7d2e812a26062b7fe4ee334 Mon Sep 17 00:00:00 2001
From: lethosor
Date: Mon, 5 Jan 2015 19:36:06 -0500
Subject: [PATCH 02/28] Add room assignment search
---
plugins/search.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 67 insertions(+), 1 deletion(-)
diff --git a/plugins/search.cpp b/plugins/search.cpp
index e25343cf7..929cd653c 100644
--- a/plugins/search.cpp
+++ b/plugins/search.cpp
@@ -43,6 +43,9 @@ DFHACK_PLUGIN_IS_ENABLED(is_enabled);
REQUIRE_GLOBAL(gps);
REQUIRE_GLOBAL(gview);
REQUIRE_GLOBAL(ui);
+REQUIRE_GLOBAL(ui_building_assign_units);
+REQUIRE_GLOBAL(ui_building_in_assign);
+REQUIRE_GLOBAL(ui_building_item_cursor);
/*
Search Plugin
@@ -1671,6 +1674,68 @@ IMPLEMENT_HOOKS(df::viewscreen_dwarfmodest, burrow_search);
//
+//
+// START: Room assignment search
+//
+
+typedef search_generic room_assign_search_base;
+class room_assign_search : public room_assign_search_base
+{
+public:
+ bool can_init(df::viewscreen_dwarfmodest *screen)
+ {
+ if (ui->main.mode == df::ui_sidebar_mode::QueryBuilding && *ui_building_in_assign)
+ {
+ return room_assign_search_base::can_init(screen);
+ }
+
+ return false;
+ }
+
+ string get_element_description(df::unit *element) const
+ {
+ return element ? get_unit_description(element) : "Nobody";
+ }
+
+ void render() const
+ {
+ auto dims = Gui::getDwarfmodeViewDims();
+ int left_margin = dims.menu_x1 + 1;
+ int x = left_margin;
+ int y = 19;
+
+ print_search_option(x, y);
+ }
+
+ vector *get_primary_list()
+ {
+ return ui_building_assign_units;
+ }
+
+ virtual int32_t * get_viewscreen_cursor()
+ {
+ return ui_building_item_cursor;
+ }
+
+ bool should_check_input(set *input)
+ {
+ if (input->count(interface_key::SECONDSCROLL_UP) || input->count(interface_key::SECONDSCROLL_DOWN)
+ || input->count(interface_key::SECONDSCROLL_PAGEUP) || input->count(interface_key::SECONDSCROLL_PAGEDOWN))
+ {
+ end_entry_mode();
+ return false;
+ }
+
+ return true;
+ }
+};
+
+IMPLEMENT_HOOKS(df::viewscreen_dwarfmodest, room_assign_search);
+
+//
+// END: Room assignment search
+//
+
#define SEARCH_HOOKS \
HOOK_ACTION(unitlist_search_hook) \
HOOK_ACTION(roomlist_search_hook) \
@@ -1684,7 +1749,8 @@ IMPLEMENT_HOOKS(df::viewscreen_dwarfmodest, burrow_search);
HOOK_ACTION(annoucnement_search_hook) \
HOOK_ACTION(joblist_search_hook) \
HOOK_ACTION(burrow_search_hook) \
- HOOK_ACTION(stockpile_search_hook)
+ HOOK_ACTION(stockpile_search_hook) \
+ HOOK_ACTION(room_assign_search_hook)
DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable)
{
From d833005832470727fb56271cac83442f4366d44d Mon Sep 17 00:00:00 2001
From: Peridexis Errant
Date: Tue, 6 Jan 2015 22:43:09 +1100
Subject: [PATCH 03/28] delete un-portable plugins
copypaste needs to be redone, not ported (see issue #479).
creaturemanager is obsolete due to the manipulator plugin, vjeck's
scripts for the cheaty bits, and changes to DF itself.
---
needs_porting/copypaste.cpp | 479 ----------
needs_porting/creaturemanager.cpp | 1428 -----------------------------
2 files changed, 1907 deletions(-)
delete mode 100644 needs_porting/copypaste.cpp
delete mode 100644 needs_porting/creaturemanager.cpp
diff --git a/needs_porting/copypaste.cpp b/needs_porting/copypaste.cpp
deleted file mode 100644
index 4f584241e..000000000
--- a/needs_porting/copypaste.cpp
+++ /dev/null
@@ -1,479 +0,0 @@
-// Console version of DF copy paste, proof of concept
-// By belal
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define DFHACK_WANT_MISCUTILS
-#define DFHACK_WANT_TILETYPES
-#include
-#include "modules/WindowIO.h"
-
-using namespace DFHack;
-//bool waitTillCursorState(DFHack::Context *DF, bool On);
-//bool waitTillCursorPositionState(DFHack::Context *DF, int32_t x,int32_t y, int32_t z);
-
-//change this if you are having problems getting correct results, lower if you would like to go faster
-//const int WAIT_AMT = 25;
-
-void sort(uint32_t &a,uint32_t &b)
-{
- if(a > b){
- uint32_t c = b;
- b = a;
- a = c;
- }
-}
-void sort(int32_t &a,int32_t &b)
-{
- if(a > b){
- int16_t c = b;
- b = a;
- a = c;
- }
-}
-void printVecOfVec(ostream &out, vector > >vec,char sep)
-{
- for(size_t k=0;k buildCommands;
- buildCommands["building_stockpilest"]="";
- buildCommands["building_zonest"]="";
- buildCommands["building_construction_blueprintst"]="";
- buildCommands["building_wagonst"]="";
- buildCommands["building_armor_standst"]="a";
- buildCommands["building_bedst"]="b";
- buildCommands["building_seatst"]="c";
- buildCommands["building_burial_receptaclest"]="n";
- buildCommands["building_doorst"]="d";
- buildCommands["building_floodgatest"]="x";
- buildCommands["building_floor_hatchst"]="H";
- buildCommands["building_wall_gratest"]="W";
- buildCommands["building_floor_gratest"]="G";
- buildCommands["building_vertical_barsst"]="B";
- buildCommands["building_floor_barsst"]="alt-b";
- buildCommands["building_cabinetst"]="f";
- buildCommands["building_containerst"]="h";
- buildCommands["building_shopst"]="";
- buildCommands["building_workshopst"]="";
- buildCommands["building_alchemists_laboratoryst"]="wa";
- buildCommands["building_carpenters_workshopst"]="wc";
- buildCommands["building_farmers_workshopst"]="ww";
- buildCommands["building_masons_workshopst"]="wm";
- buildCommands["building_craftdwarfs_workshopst"]="wr";
- buildCommands["building_jewelers_workshopst"]="wj";
- buildCommands["building_metalsmiths_workshopst"]="wf";
- buildCommands["building_magma_forgest"]="";
- buildCommands["building_bowyers_workshopst"]="wb";
- buildCommands["building_mechanics_workshopst"]="wt";
- buildCommands["building_siege_workshopst"]="ws";
- buildCommands["building_butchers_shopst"]="wU";
- buildCommands["building_leather_worksst"]="we";
- buildCommands["building_tanners_shopst"]="wn";
- buildCommands["building_clothiers_shopst"]="wk";
- buildCommands["building_fisheryst"]="wh";
- buildCommands["building_stillst"]="wl";
- buildCommands["building_loomst"]="wo";
- buildCommands["building_quernst"]="wq";
- buildCommands["building_kennelsst"]="k";
- buildCommands["building_kitchenst"]="wz";
- buildCommands["building_asheryst"]="wy";
- buildCommands["building_dyers_shopst"]="wd";
- buildCommands["building_millstonest"]="wM";
- buildCommands["building_farm_plotst"]="p";
- buildCommands["building_weapon_rackst"]="r";
- buildCommands["building_statuest"]="s";
- buildCommands["building_tablest"]="t";
- buildCommands["building_paved_roadst"]="o";
- buildCommands["building_bridgest"]="g";
- buildCommands["building_wellst"]="l";
- buildCommands["building_siege enginest"]="i";
- buildCommands["building_catapultst"]="ic";
- buildCommands["building_ballistast"]="ib";
- buildCommands["building_furnacest"]="";
- buildCommands["building_wood_furnacest"]="ew";
- buildCommands["building_smelterst"]="es";
- buildCommands["building_glass_furnacest"]="ek";
- buildCommands["building_kilnst"]="ek";
- buildCommands["building_magma_smelterst"]="es";
- buildCommands["building_magma_glass_furnacest"]="ek";
- buildCommands["building_magma_kilnst"]="ek";
- buildCommands["building_glass_windowst"]="y";
- buildCommands["building_gem_windowst"]="Y";
- buildCommands["building_tradedepotst"]="D";
- buildCommands["building_mechanismst"]="";
- buildCommands["building_leverst"]="Tl";
- buildCommands["building_pressure_platest"]="Tp";
- buildCommands["building_cage_trapst"]="Tc";
- buildCommands["building_stonefall_trapst"]="Ts";
- buildCommands["building_weapon_trapst"]="Tw";
- buildCommands["building_spikest"]="";
- buildCommands["building_animal_trapst"]="m";
- buildCommands["building_screw_pumpst"]="Ms";
- buildCommands["building_water_wheelst"]="Mw";
- buildCommands["building_windmillst"]="Mm";
- buildCommands["building_gear_assemblyst"]="Mg";
- buildCommands["building_horizontal_axlest"]="Mh";
- buildCommands["building_vertical_axlest"]="Mv";
- buildCommands["building_supportst"]="S";
- buildCommands["building_cagest"]="j";
- buildCommands["building_archery_targetst"]="A";
- buildCommands["building_restraintst"]="v";
-
- DFHack::ContextManager DFMgr("Memory.xml");
- DFHack::Context *DF = DFMgr.getSingleContext();
-
- try
- {
- DF->Attach();
- }
- catch (std::exception& e)
- {
- std::cerr << e.what() << std::endl;
- #ifndef LINUX_BUILD
- cin.ignore();
- #endif
- return 1;
- }
-
- DFHack::Gui *Gui = DF->getGui();
- DFHack::VersionInfo* mem = DF->getMemoryInfo();
- DFHack::Process * p = DF->getProcess();
- OffsetGroup * OG_Maps = mem->getGroup("Maps");
- OffsetGroup * OG_MapBlock = OG_Maps->getGroup("block");
- OffsetGroup * OG_LocalFt = OG_Maps->getGroup("features")->getGroup("local");
- uint32_t designations = OG_MapBlock->getOffset("designation");
- uint32_t block_feature1 = OG_MapBlock->getOffset("feature_local");
- uint32_t block_feature2 = OG_MapBlock->getOffset("feature_global");
- uint32_t region_x_offset = OG_Maps->getAddress("region_x");
- uint32_t region_y_offset = OG_Maps->getAddress("region_y");
- uint32_t region_z_offset = OG_Maps->getAddress("region_z");
- uint32_t feature1_start_ptr = OG_LocalFt->getAddress("start_ptr");
- int32_t regionX, regionY, regionZ;
-
- // read position of the region inside DF world
- p->readDWord (region_x_offset, (uint32_t &)regionX);
- p->readDWord (region_y_offset, (uint32_t &)regionY);
- p->readDWord (region_z_offset, (uint32_t &)regionZ);
- while(1){
- int32_t cx1,cy1,cz1;
- cx1 = -30000;
- while(cx1 == -30000)
- {
- DF->ForceResume();
- cout << "Set cursor at first position, then press any key";
- cin.ignore();
- DF->Suspend();
- Gui->getCursorCoords(cx1,cy1,cz1);
- }
-
- uint32_t tx1,ty1,tz1;
- tx1 = cx1/16;
- ty1 = cy1/16;
- tz1 = cz1;
-
- int32_t cx2,cy2,cz2;
- cx2 = -30000;
- while(cx2 == -30000)
- {
- DF->Resume();
- cout << "Set cursor at second position, then press any key";
- cin.ignore();
- DF->Suspend();
- Gui->getCursorCoords(cx2,cy2,cz2);
- }
- uint32_t tx2,ty2,tz2;
- tx2 = cx2/16;
- ty2 = cy2/16;
- tz2 = cz2;
- sort(tx1,tx2);
- sort(ty1,ty2);
- sort(tz1,tz2);
- sort(cx1,cx2);
- sort(cy1,cy2);
- sort(cz1,cz2);
-
- vector > >dig(cz2-cz1+1,vector >(cy2-cy1+1,vector(cx2-cx1+1)));
- vector > >build(cz2-cz1+1,vector >(cy2-cy1+1,vector(cx2-cx1+1)));
- mapblock40d block;
- DFHack::Maps *Maps = DF->getMaps();
- Maps->Start();
- for(uint32_t y = ty1;y<=ty2;y++)
- {
- for(uint32_t x = tx1;x<=tx2;x++)
- {
- for(uint32_t z = tz1;z<=tz2;z++)
- {
- if(Maps->isValidBlock(x,y,z))
- {
- if(Maps->ReadBlock40d(x,y,z,&block))
- {
- int ystart,yend,xstart,xend;
- ystart=xstart=0;
- yend=xend=15;
- if(y == ty2)
- {
- yend = cy2 % 16;
- }
- if(y == ty1)
- {
- ystart = cy1 % 16;
- }
- if(x == tx2)
- {
- xend = cx2 % 16;
- }
- if(x == tx1)
- {
- xstart = cx1 % 16;
- }
- int zidx = z-tz1;
- for(int yy = ystart; yy <= yend;yy++)
- {
- int yidx = yy+(16*(y-ty1)-(cy1%16));
- for(int xx = xstart; xx <= xend;xx++)
- {
- int xidx = xx+(16*(x-tx1)-(cx1%16));
- int16_t tt = block.tiletypes[xx][yy];
- DFHack::TileShape ts = DFHack::tileShape(tt);
- if(DFHack::isOpenTerrain(tt) || DFHack::isFloorTerrain(tt))
- {
- dig[zidx][yidx][xidx] = "d";
- }
- else if(DFHack::STAIR_DOWN == ts)
- {
- dig [zidx][yidx][xidx] = "j";
- build [zidx][yidx][xidx] = "Cd";
- }
- else if(DFHack::STAIR_UP == ts)
- {
- dig [zidx][yidx][xidx] = "u";
- build [zidx][yidx][xidx] = "Cu";
- }
- else if(DFHack::STAIR_UPDOWN == ts)
- {
- dig [zidx][yidx][xidx] = "i";
- build [zidx][yidx][xidx] = "Cx";
- }
- else if(DFHack::isRampTerrain(tt))
- {
- dig [zidx][yidx][xidx] = "r";
- build [zidx][yidx][xidx] = "Cr";
- }
- else if(DFHack::isWallTerrain(tt))
- {
- build [zidx][yidx][xidx] = "Cw";
- }
- }
- yidx++;
- }
- }
- }
- }
- }
- }
- DFHack::Buildings * Bld = DF->getBuildings();
- std::map custom_workshop_types;
- uint32_t numBuildings;
- if(Bld->Start(numBuildings))
- {
- Bld->ReadCustomWorkshopTypes(custom_workshop_types);
- for(uint32_t i = 0; i < numBuildings; i++)
- {
- DFHack::t_building temp;
- Bld->Read(i, temp);
- if(temp.type != 0xFFFFFFFF) // check if type isn't invalid
- {
- std::string typestr;
- mem->resolveClassIDToClassname(temp.type, typestr);
- if(temp.z == cz1 && cx1 <= temp.x1 && cx2 >= temp.x2 && cy1 <= temp.y1 && cy2 >= temp.y2)
- {
- string currStr = build[temp.z-cz1][temp.y1-cy1][temp.x1-cx1];
- stringstream stream;
- string newStr = buildCommands[typestr];
- if(temp.x1 != temp.x2)
- {
- stream << "(" << temp.x2-temp.x1+1 << "x" << temp.y2-temp.y1+1 << ")";
- newStr += stream.str();
- }
- build[temp.z-cz1][temp.y1-cy1][temp.x1-cx1] = newStr + currStr;
- }
- }
- }
- }
-// for testing purposes
- //ofstream outfile("test.txt");
-// printVecOfVec(outfile, dig,'\t');
-// outfile << endl;
-// printVecOfVec(outfile, build,'\t');
-// outfile << endl;
-// outfile.close();
-
- int32_t cx3,cy3,cz3,cx4,cy4,cz4;
- uint32_t tx3,ty3,tz3,tx4,ty4,tz4;
- char result;
- while(1){
- cx3 = -30000;
- while(cx3 == -30000){
- DF->Resume();
- cout << "Set cursor at new position, then press any key:";
- result = cin.get();
- DF->Suspend();
- Gui->getCursorCoords(cx3,cy3,cz3);
- }
- if(result == 'q'){
- break;
- }
- cx4 = cx3+cx2-cx1;
- cy4 = cy3+cy2-cy1;
- cz4 = cz3+cz2-cz1;
- tx3=cx3/16;
- ty3=cy3/16;
- tz3=cz3;
- tx4=cx4/16;
- ty4=cy4/16;
- tz4=cz4;
- DFHack::WindowIO * Win = DF->getWindowIO();
- designations40d designationBlock;
- for(uint32_t y = ty3;y<=ty4;y++)
- {
- for(uint32_t x = tx3;x<=tx4;x++)
- {
- for(uint32_t z = tz3;z<=tz4;z++)
- {
- Maps->Start();
- Maps->ReadBlock40d(x,y,z,&block);
- Maps->ReadDesignations(x,y,z,&designationBlock);
- int ystart,yend,xstart,xend;
- ystart=xstart=0;
- yend=xend=15;
- if(y == ty4){
- yend = cy4 % 16;
- }
- if(y == ty3){
- ystart = cy3 % 16;
- }
- if(x == tx4){
- xend = cx4 % 16;
- }
- if(x == tx3){
- xstart = cx3 % 16;
- }
- int zidx = z-tz3;
- for(int yy = ystart; yy <= yend;yy++){
- int yidx = yy+(16*(y-ty3)-(cy3%16));
- for(int xx = xstart; xx <= xend;xx++){
- int xidx = xx+(16*(x-tx3)-(cx3%16));
- if(dig[zidx][yidx][xidx] != ""){
- char test = dig[zidx][yidx][xidx].c_str()[0];
- switch (test){
- case 'd':
- designationBlock[xx][yy].bits.dig = DFHack::designation_default;
- break;
- case 'i':
- designationBlock[xx][yy].bits.dig = DFHack::designation_ud_stair;
- break;
- case 'u':
- designationBlock[xx][yy].bits.dig = DFHack::designation_u_stair;
- break;
- case 'j':
- designationBlock[xx][yy].bits.dig = DFHack::designation_d_stair;
- break;
- case 'r':
- designationBlock[xx][yy].bits.dig = DFHack::designation_ramp;
- break;
- }
-
- }
- }
- yidx++;
- }
- Maps->Start();
- Maps->WriteDesignations(x,y,z,&designationBlock);
- }
- }
- }
- }
- }
- DF->Detach();
- #ifndef LINUX_BUILD
- std::cout << "Done. Press any key to continue" << std::endl;
- cin.ignore();
- #endif
- return 0;
-}
-/*
-bool waitTillCursorState(DFHack::Context *DF, bool On)
-{
- DFHack::WindowIO * w = DF->getWindowIO();
- DFHack::Position * p = DF->getPosition();
- int32_t x,y,z;
- int tryCount = 0;
- DF->Suspend();
- bool cursorResult = p->getCursorCoords(x,y,z);
- while(tryCount < 50 && On && !cursorResult || !On && cursorResult)
- {
- DF->Resume();
- w->TypeSpecial(DFHack::WAIT,1,WAIT_AMT);
- tryCount++;
- DF->Suspend();
- cursorResult = p->getCursorCoords(x,y,z);
- }
- if(tryCount >= 50)
- {
- cerr << "Something went wrong, cursor at x: " << x << " y: " << y << " z: " << z << endl;
- return false;
- }
- DF->Resume();
- return true;
-}
-bool waitTillCursorPositionState(DFHack::Context *DF, int32_t x,int32_t y, int32_t z)
-{
- DFHack::WindowIO * w = DF->getWindowIO();
- DFHack::Position * p = DF->getPosition();
- int32_t x2,y2,z2;
- int tryCount = 0;
- DF->Suspend();
- bool cursorResult = p->getCursorCoords(x2,y2,z2);
- while(tryCount < 50 && (x != x2 || y != y2 || z != z2))
- {
- DF->Resume();
- w->TypeSpecial(DFHack::WAIT,1,WAIT_AMT);
- tryCount++;
- DF->Suspend();
- cursorResult = p->getCursorCoords(x2,y2,z2);
- }
- if(tryCount >= 50)
- {
- cerr << "Something went wrong, cursor at x: " << x2 << " y: " << y2 << " z: " << z2 << endl;
- return false;
- }
- DF->Resume();
- return true;
-}*/
\ No newline at end of file
diff --git a/needs_porting/creaturemanager.cpp b/needs_porting/creaturemanager.cpp
deleted file mode 100644
index 0d65e9f6e..000000000
--- a/needs_porting/creaturemanager.cpp
+++ /dev/null
@@ -1,1428 +0,0 @@
-/*********************************************
- * Purpose:
- *
- * - Display creatures
- * - Modify skills and labors of creatures
- * - Kill creatures
- * - Etc.
- *
- * Version: 0.1.1
- * Date: 2011-04-07
- * Author: raoulxq (based on creaturedump.cpp from peterix)
-
- * Todo:
- * - Option to add/remove single skills
- * - Ghosts/Merchants/etc. should be tagged as not own creatures
- * - Filter by nickname with -n
- * - Filter by first name with -fn
- * - Filter by last name with -ln
- * - Add pattern matching (or at least matching) to -n/-fn/-ln
- * - Set nickname with --setnick (only if -i is given)
- * - Show skills/labors only when -ss/-sl/-v is given or a skill/labor is changed
- * - Make -1 the default for everything but -i
- * - Imply -i if first argument is a number
- * - Search for nick/profession if first argument is a string without - (i.e. no switch)
- * - Switch --showhappy (show dwarf's experiences which make her un-/happy)
- * - Switch --makefriendly
- * - Switch --listskills, showing first 3 important skills
-
- * Done:
- * - More space for "Current Job"
- * - Attempted to revive creature(s) with --revive, but it doesn't work (flag is there but invisible)
- * - Switch -rcs, remove civil skills
- * - Switch -rms, remove military skills (who would want that?)
- * - Allow comma separated list of IDs for -i
- * - '-c all' shows all creatures
- * - Rename from skillmodify.cpp to creature.cpp
- * - Kill creature(s) with --kill
- * - Hide skills with level 0 and 0 experience points
- * - Add --showallflags flag to display all flags (default: display a few important ones)
- * - Add --showdead flag to also display dead creatures
- * - Display more creature flags
- * - Show creature type (again)
- * - Add switch -1/--summary to only display one line for every creature. Good for an overview.
- * - Display current job (has been there all the time, but not shown in Windows due to missing memory offsets)
- * - Remove magic numbers
- * - Show social skills only when -ss is given
- * - Hide hauler labors when +sh is given
- * - Add -v for verbose
- * - Override forbidden mass-designation with -f
- * - Option to add/remove single labors
- * - Switches -ras and rl should only be possible with -nn or -i
- * - Switch -rh removes hauler jobs
- * - Dead creatures should not be displayed
- * - Childs should not get labors assigned to
- * - Babies should not get labors assigned to
- * - Switch -al adds labor number n
- * - Switch -rl removes labor number n
- * - Switch -ral removes all labors
- * - Switch -ll lists all available labors
- *********************************************
-*/
-
-#include
-#include
-#include
-#include
-#include
-#include
-using namespace std;
-
-#define DFHACK_WANT_MISCUTILS
-#include
-#include
-
-/* Note about magic numbers:
- * If you have an idea how to better solve this, tell me. Currently I'd be
- * either dependent on Toady One's implementation (#defining numbers) or
- * Memory.xml (#defining text). I voted for Toady One's numbers to be more
- * stable, but could be wrong.
- *
- * Ideally there would be a flag "is_military" or "is_social" in Memory.xml.
- */
-
-/* Social skills */
-#define SKILL_PERSUASION 72
-#define SKILL_NEGOTIATION 73
-#define SKILL_JUDGING_INTENT 74
-#define SKILL_INTIMIDATION 79
-#define SKILL_CONVERSATION 80
-#define SKILL_COMEDY 81
-#define SKILL_FLATTERY 82
-#define SKILL_CONSOLING 83
-#define SKILL_PACIFICATION 84
-
-/* Misc skills */
-#define SKILL_WEAPONSMITHING 27
-#define SKILL_ARMORSMITHING 28
-#define SKILL_RECORD_KEEPING 77
-#define SKILL_WAX_WORKING 115
-
-/* Some military skills */
-#define SKILL_COORDINATION 95
-#define SKILL_BALANCE 96
-#define SKILL_LEADERSHIP 97
-#define SKILL_TEACHING 98
-#define SKILL_FIGHTING 99
-#define SKILL_ARCHERY 100
-#define SKILL_WRESTLING 101
-#define SKILL_BITING 102
-#define SKILL_STRIKING 103
-#define SKILL_KICKING 104
-#define SKILL_DODGING 105
-
-#define LABOR_STONE_HAULING 1
-#define LABOR_WOOD_HAULING 2
-#define LABOR_BURIAL 3
-#define LABOR_FOOD_HAULING 4
-#define LABOR_REFUSE_HAULING 5
-#define LABOR_ITEM_HAULING 6
-#define LABOR_FURNITURE_HAULING 7
-#define LABOR_ANIMAL_HAULING 8
-#define LABOR_CLEANING 9
-#define LABOR_FEED_PATIENTS_PRISONERS 22
-#define LABOR_RECOVERING_WOUNDED 23
-
-#define PROFESSION_CHILD 96
-#define PROFESSION_BABY 97
-
-#define NOT_SET INT_MIN
-#define MAX_MOOD 4
-#define NO_MOOD -1
-
-bool quiet=true;
-bool verbose = false;
-bool showhauler = true;
-bool showsocial = false;
-bool showfirstlineonly = false;
-bool showdead = false;
-bool showallflags = false;
-
-int hauler_labors[] = {
- LABOR_STONE_HAULING
- ,LABOR_WOOD_HAULING
- ,LABOR_BURIAL
- ,LABOR_FOOD_HAULING
- ,LABOR_REFUSE_HAULING
- ,LABOR_ITEM_HAULING
- ,LABOR_FURNITURE_HAULING
- ,LABOR_ANIMAL_HAULING
- ,LABOR_CLEANING
- ,LABOR_FEED_PATIENTS_PRISONERS
- ,LABOR_RECOVERING_WOUNDED
-};
-
-int social_skills[] =
-{
- SKILL_PERSUASION
- ,SKILL_NEGOTIATION
- ,SKILL_JUDGING_INTENT
- ,SKILL_INTIMIDATION
- ,SKILL_CONVERSATION
- ,SKILL_COMEDY
- ,SKILL_FLATTERY
- ,SKILL_CONSOLING
- ,SKILL_PACIFICATION
-};
-
-int military_skills[] =
-{
- SKILL_COORDINATION
- ,SKILL_BALANCE
- ,SKILL_LEADERSHIP
- ,SKILL_TEACHING
- ,SKILL_FIGHTING
- ,SKILL_ARCHERY
- ,SKILL_WRESTLING
- ,SKILL_BITING
- ,SKILL_STRIKING
- ,SKILL_KICKING
- ,SKILL_DODGING
-};
-
-void usage(int argc, const char * argv[])
-{
- cout
- << "Usage:" << endl
- << argv[0] << " [option 1] [option 2] [...]" << endl
- << endl
- << "Display options:" << endl
- << "-q : Suppress \"Press any key to continue\" at program termination" << endl
- << "-v : Increase verbosity" << endl
- << endl
-
- << "Choosing which creatures to display and/or modify "
- << "(note that all criteria" << endl << "must match, so adding "
- << " more narrows things down):" << endl
- << "-i id1[,id2,...]: Only show/modify creature with this id" << endl
- << "-c creature : Show/modify this creature type instead of dwarves" << endl
- << " ('all' to show all creatures)" << endl
- << "-nn/--nonicks : Only show/modify creatures with no custom nickname (migrants)" << endl
- << "--nicks : Only show/modify creatures with custom nickname" << endl
- << "--showdead : Also show/modify dead creatures" << endl
- << "--type : Show/modify all creatures of given type" << endl
- << " : Can be used multiple times" << endl
- << " types:" << endl
- << " * dead: all dead creatures" << endl
- << " * demon: all demons" << endl
- << " * diplomat: all diplomats" << endl
- << " * FB: all forgotten beasts" << endl
- << " * female: all female creatures" << endl
- << " * ghost: all ghosts" << endl
- << " * male: all male creatures" << endl
- << " * merchants: all merchants (including pack animals)" << endl
- << " * neuter: all neuter creatuers" << endl
- << " * pregnant: all pregnant creatures" << endl
- << " * tame: all tame creatues" << endl
- << " * wild: all wild creatures" << endl
-
- << endl
-
- << "What information to display:" << endl
- << "-saf : Show all flags of a creature" << endl
- << "--showallflags : Show all flags of a creature" << endl
- << "-ll/--listlabors: List available labors" << endl
- << "-ss : Show social skills" << endl
- << "+sh : Hide hauler labors" << endl
- << "-1/--summary : Only display one line per creature" << endl
-
- << endl
-
- << "Options to modify selected creatures:" << endl
- << "-al : Add labor to creature" << endl
- << "-rl : Remove labor from creature" << endl
- << "-ras : Remove all skills from creature (i.e. set them to zero)" << endl
- << "-rcs : Remove civil skills from creature (i.e. set them to zero)" << endl
- << "-rms : Remove military skills from creature (i.e. set them to zero)" << endl
- << "-ral : Remove all labors from creature" << endl
- << "-ah : Add hauler labors (stone hauling, etc.) to creature" << endl
- << "-rh : Remove hauler labors (stone hauling, etc.) from creature" << endl
- // Disabling mood doesn't work as intented
- << "--setmood : Set mood to n (-1 = no mood, max=4, buggy!)" << endl
- << "--kill : Kill creature(s) (leaves behind corpses)" << endl
- << "--erase : Remove creature(s) from game without killing" << endl
- << "--tame : Tames animals, recruits intelligent creatures." << endl
- << "--slaugher : Mark a creature for slaughter, even sentients" << endl
- << "--butcher : Same as --slaugher" << endl
- // Doesn't seem to work
- //<< "--revive : Attempt to revive creature(s) (remove dead and killed flag)" << endl
- // Setting happiness doesn't work really, because hapiness is recalculated
- //<< "--sethappiness : Set happiness to n" << endl
- << "-f : Force an action" << endl
- << endl
- << "Examples:" << endl
- << endl
- << "Show all dwarfs:" << endl
- << argv[0] << " -c Dwarf" << endl
- << endl
- << "Show summary of all creatures (spoiler: includes unknown creatures):" << endl
- << argv[0] << " -1 -c all" << endl
- << endl
- << "Kill that nasty ogre" << endl
- << argv[0] << " -i 52 --kill" << endl
- << endl
- << "Check that the ogre is really dead" << endl
- << argv[0] << " -c ogre --showdead" << endl
- << endl
- << "Remove all skills from dwarfs 15 and 32:" << endl
- << argv[0] << " -i 15,32 -ras" << endl
- << endl
- << "Remove all skills and labors from dwarfs with no custom nickname:" << endl
- << argv[0] << " -c DWARF -nn -ras -ral" << endl
- << endl
- << "Add hauling labors to all dwarfs without nickname (e.g. migrants):" << endl
- << argv[0] << " -c DWARF -nn -ah" << endl
- << endl
- << "Show list of labor ids:" << endl
- << argv[0] << " -c DWARF -ll" << endl
- << endl
- << "Add engraving labor to all dwarfs without nickname (get the labor id from the list above):" << endl
- << argv[0] << " -c DWARF -nn -al 13" << endl
- << endl
- << "Make Urist, Stodir and Ingish miners:" << endl
- << argv[0] << " -i 31,42,77 -al 0" << endl
- << endl
- << "Make all demons friendly:" << endl
- << argv[0] << " --type demon --tame" << endl
- ;
- if (quiet == false) {
- cout << "Press any key to continue" << endl;
- cin.ignore();
- }
-}
-
-DFHack::Materials * Materials;
-DFHack::VersionInfo *mem;
-DFHack::Creatures * Creatures = NULL;
-
-// Note that toCaps() changes the string itself and I'm using it a few times in
-// an unsafe way below. Didn't crash yet however.
-std::string toCaps(std::string s)
-{
- const int length = s.length();
- std::locale loc("");
- bool caps=true;
- if (length == 0) {
- return s;
- }
- for(int i=0; i!=length ; ++i)
- {
- if (caps)
- {
- s[i] = std::toupper(s[i],loc);
- caps = false;
- }
- else if (s[i] == '_' || s[i] == ' ')
- {
- s[i] = ' ';
- caps = true;
- }
- else
- {
- s[i] = std::tolower(s[i],loc);
- }
- }
- return s;
-}
-
-int strtoint(const string &str)
-{
- stringstream ss(str);
- int result;
- return ss >> result ? result : -1;
-}
-
-
-// A C++ standard library function should be used instead
-bool is_in(int m, int set[], int set_size)
-{
- for (int i=0; i v, int comp)
-{
- for (size_t i=0; igetTranslation();
- DFHack::VersionInfo *mem = DF->getMemoryInfo();
-
- string type="(no type)";
- if (Materials->raceEx[creature.race].rawname[0])
- {
- type = toCaps(Materials->raceEx[creature.race].rawname);
- }
-
- string name="(no name)";
- if(creature.name.nickname[0])
- {
- name = creature.name.nickname;
- }
- else
- {
- if(creature.name.first_name[0])
- {
- name = toCaps(creature.name.first_name);
-
- string transName = Tran->TranslateName(creature.name,false);
- if(!transName.empty())
- {
- name += " " + toCaps(transName);
- }
- }
- }
-
- string profession="";
- try {
- profession = mem->getProfession(creature.profession);
- }
- catch (exception& e)
- {
- cout << "Error retrieving creature profession: " << e.what() << endl;
- }
- if(creature.custom_profession[0])
- {
- profession = creature.custom_profession;
- }
-
-
- string jobid;
- stringstream ss;
- ss << "(" << creature.current_job.jobId << ")";
- jobid = ss.str();
-
- string job="No Job/On Break" + (creature.current_job.jobId == 0 ? "" : jobid);
- if(creature.current_job.active)
- {
- job=mem->getJob(creature.current_job.jobId);
-
- int p=job.size();
- while (p>0 && (job[p]==' ' || job[p]=='\t'))
- p--;
- if (p <= 1) // Display numeric jobID if unknown job
- {
- job = jobid;
- }
- }
-
- if (showfirstlineonly)
- {
- printf("%3d", index);
- printf(" %-17s", type.c_str());
- printf(" %-24s", name.c_str());
- printf(" %-16s", toCaps(profession).c_str());
- printf(" %-38s", job.c_str());
- printf(" %5d", creature.happiness);
- if (showdead)
- {
- printf(" %-5s", creature.flags1.bits.dead ? "Dead" : "Alive");
- }
-
- printf("\n");
-
- return;
- }
- else
- {
- printf("ID: %d", index);
- printf(", %s", type.c_str());
- printf(", %s", name.c_str());
- printf(", %s", toCaps(profession).c_str());
- printf(", Job: %s", job.c_str());
- printf(", Happiness: %d", creature.happiness);
- printf("\n");
- printf("Origin: %p\n", creature.origin);
- printf("Civ #: %d\n", creature.civ);
- }
-
- if((creature.mood != NO_MOOD) && (creature.mood<=MAX_MOOD))
- {
- cout << "Creature is in a strange mood (mood=" << creature.mood << "), skill: " << mem->getSkill(creature.mood_skill) << endl;
- vector mymat;
- if(Creatures->ReadJob(&creature, mymat))
- {
- for(unsigned int i = 0; i < mymat.size(); i++)
- {
- printf("\t%s(%d)\t%d %d %d - %.8x\n", Materials->getDescription(mymat[i]).c_str(), mymat[i].itemType, mymat[i].subType, mymat[i].subIndex, mymat[i].index, mymat[i].flags);
- }
- }
- }
-
- if(creature.has_default_soul)
- {
- // Print out skills
- int skillid;
- int skillrating;
- int skillexperience;
- string skillname;
-
- cout << setiosflags(ios::left);
-
- for(unsigned int i = 0; i < creature.defaultSoul.numSkills;i++)
- {
- skillid = creature.defaultSoul.skills[i].id;
- bool is_social = is_in(skillid, social_skills, sizeof(social_skills)/sizeof(social_skills[0]));
- if (!is_social || (is_social && showsocial))
- {
- skillrating = creature.defaultSoul.skills[i].rating;
- skillexperience = creature.defaultSoul.skills[i].experience;
- try
- {
- skillname = mem->getSkill(skillid);
- }
- catch(DFHack::Error::AllMemdef &e)
- {
- skillname = "Unknown skill";
- cout << e.what() << endl;
- }
- if (skillrating > 0 || skillexperience > 0)
- {
- cout << "(Skill " << int(skillid) << ") " << setw(16) << skillname << ": "
- << skillrating << "/" << skillexperience << endl;
- }
- }
- }
-
- for(unsigned int i = 0; i < NUM_CREATURE_LABORS;i++)
- {
- if(!creature.labors[i])
- continue;
- string laborname;
- try
- {
- laborname = mem->getLabor(i);
- }
- catch(exception &)
- {
- laborname = "(Undefined)";
- }
- bool is_labor = is_in(i, hauler_labors, sizeof(hauler_labors)/sizeof(hauler_labors[0]));
- if (!is_labor || (is_labor && showhauler))
- cout << "(Labor " << i << ") " << setw(16) << laborname << endl;
- }
- }
-
- if (creature.pregnancy_timer > 0)
- cout << "Pregnant: " << creature.pregnancy_timer << " ticks to "
- << "birth." << endl;
-
- if (showallflags)
- {
- DFHack::t_creaturflags1 f1 = creature.flags1;
- DFHack::t_creaturflags2 f2 = creature.flags2;
- DFHack::t_creaturflags3 f3 = creature.flags3;
-
- if(f1.bits.dead){cout << "Flag: dead" << endl; }
- if(f1.bits.had_mood){cout<TranslateName(creature.artifact_name,false);
- cout << "Artifact: " << artifact_name << endl;
- }
- }
- cout << endl;
-}
-
-class creature_filter
-{
-public:
-
- enum sex_filter
- {
- SEX_FEMALE = 0,
- SEX_MALE = 1,
- SEX_ANY = 254, // Our magin number for ignoring sex.
- SEX_NEUTER = 255
- };
-
- bool dead;
- bool demon;
- bool diplomat;
- bool find_nonicks;
- bool find_nicks;
- bool forgotten_beast;
- bool ghost;
- bool merchant;
- bool pregnant;
- bool tame;
- bool wild;
-
- sex_filter sex;
-
- string creature_type;
- std::vector creature_id;
-
- #define DEFAULT_CREATURE_STR "Default"
-
- creature_filter()
- {
- // By default we only select dwarves, except that if we use the
- // --type option we want to default to everyone. So we start out
- // with a special string, and if remains unchanged after all
- // the options have been processed we turn it to DWARF.
- creature_type = DEFAULT_CREATURE_STR;
-
- dead = false;
- demon = false;
- diplomat = false;
- find_nonicks = false;
- find_nicks = false;
- forgotten_beast = false;
- ghost = false;
- merchant = false;
- pregnant = false;
- sex = SEX_ANY;
- tame = false;
- wild = false;
- }
-
- // If the creature type is still the default, then change it to allow
- // for all creatures. If the creature type has been explicitly set,
- // then don't alter it.
- void defaultTypeToAll()
- {
- if (creature_type == DEFAULT_CREATURE_STR)
- creature_type = "";
- }
-
- // If the creature type is still the default, change it to DWARF
- void defaultTypeToDwarf()
- {
- if (creature_type == DEFAULT_CREATURE_STR)
- creature_type = "Dwarf";
- }
-
- void process_type(string type)
- {
- type = toCaps(type);
-
- // If we're going by type, then by default all species are
- // permitted.
- defaultTypeToAll();
-
- if (type == "Dead")
- {
- dead = true;
- showdead = true;
- }
- else if (type == "Demon")
- demon = true;
- else if (type == "Diplomat")
- diplomat = true;
- else if (type == "Fb" || type == "Beast")
- forgotten_beast = true;
- else if (type == "Ghost")
- ghost = true;
- else if (type == "Merchant")
- merchant = true;
- else if (type == "Pregnant")
- pregnant = true;
- else if (type == "Tame")
- tame = true;
- else if (type == "Wild")
- wild = true;
- else if (type == "Male")
- sex = SEX_MALE;
- else if (type == "Female")
- sex = SEX_FEMALE;
- else if (type == "Neuter")
- sex = SEX_NEUTER;
- else
- {
- cerr << "ERROR: Unknown type '" << type << "'" << endl;
- }
- }
-
- void doneProcessingOptions()
- {
- string temp = toCaps(creature_type);
- creature_type = temp;
-
- defaultTypeToDwarf();
- }
-
- bool creatureMatches(const DFHack::t_creature & creature,
- uint32_t creature_idx)
- {
- // A list of ids overrides everything else.
- if (creature_id.size() > 0)
- return (find_int(creature_id, creature_idx));
-
- // If it's not a list of ids, it has not match all given criteria.
-
- const DFHack::t_creaturflags1 &f1 = creature.flags1;
- const DFHack::t_creaturflags2 &f2 = creature.flags2;
- const DFHack::t_creaturflags3 &f3 = creature.flags3;
-
- if(f1.bits.dead && !showdead)
- return false;
-
- bool hasnick = (creature.name.nickname[0] != '\0');
- if(hasnick && find_nonicks)
- return false;
- if(!hasnick && find_nicks)
- return false;
-
- string race_name = string(Materials->raceEx[creature.race].rawname);
-
- if(!creature_type.empty() && creature_type != toCaps(race_name))
- return false;
-
- if(dead && !f1.bits.dead)
- return false;
- if(demon && !f2.bits.underworld)
- return false;
- if(diplomat && !f1.bits.diplomat)
- return false;
- if(forgotten_beast && !f2.bits.visitor_uninvited)
- return false;
- if(ghost && !f3.bits.ghostly)
- return false;
- if(merchant && !f1.bits.merchant)
- return false;
- if(pregnant && creature.pregnancy_timer == 0)
- return false;
- if (sex != SEX_ANY && creature.sex != (uint8_t) sex)
- return false;
- if(tame && !f1.bits.tame)
- return false;
-
- if(wild && !f2.bits.roaming_wilderness_population_source &&
- !f2.bits.roaming_wilderness_population_source_not_a_map_feature)
- {
- return false;
- }
-
- return true;
- }
-};
-
-int main (int argc, const char* argv[])
-{
- // let's be more useful when double-clicked on windows
-#ifndef LINUX_BUILD
- quiet = false;
-#endif
- creature_filter filter;
-
- bool remove_skills = false;
- bool remove_civil_skills = false;
- bool remove_military_skills = false;
- bool remove_labors = false;
- bool kill_creature = false;
- bool erase_creature = false;
- bool revive_creature = false;
- bool make_hauler = false;
- bool remove_hauler = false;
- bool add_labor = false;
- int add_labor_n = NOT_SET;
- bool remove_labor = false;
- int remove_labor_n = NOT_SET;
- bool set_happiness = false;
- int set_happiness_n = NOT_SET;
- bool set_mood = false;
- int set_mood_n = NOT_SET;
- bool list_labors = false;
- bool force_massdesignation = false;
- bool tame_creature = false;
- bool slaughter_creature = false;
-
- if (argc == 1) {
- usage(argc, argv);
- return 1;
- }
-
- for(int i = 1; i < argc; i++)
- {
- string arg_cur = argv[i];
- string arg_next = "";
- int arg_next_int = NOT_SET;
- /* Check if argv[i+1] is a number >= 0 */
- if (i < argc-1) {
- arg_next = argv[i+1];
- arg_next_int = strtoint(arg_next);
- if (arg_next != "0" && arg_next_int == 0) {
- arg_next_int = NOT_SET;
- }
- }
-
- if(arg_cur == "-q")
- {
- quiet = true;
- }
- else if(arg_cur == "+q")
- {
- quiet = false;
- }
- else if(arg_cur == "-v")
- {
- verbose = true;
- }
- else if(arg_cur == "-1" || arg_cur == "--summary")
- {
- showfirstlineonly = true;
- }
- else if(arg_cur == "-ss" || arg_cur == "--showsocial")
- {
- showsocial = true;
- }
- else if(arg_cur == "+sh" || arg_cur == "-nosh" || arg_cur == "--noshowhauler")
- {
- showhauler = false;
- }
- else if(arg_cur == "--showdead")
- {
- showdead = true;
- }
- else if(arg_cur == "--showallflags" || arg_cur == "-saf")
- {
- showallflags = true;
- }
- else if(arg_cur == "-ras")
- {
- remove_skills = true;
- }
- else if(arg_cur == "-rcs")
- {
- remove_civil_skills = true;
- }
- else if(arg_cur == "-rms")
- {
- remove_military_skills = true;
- }
- else if(arg_cur == "-f")
- {
- force_massdesignation = true;
- }
- // list labors
- else if(arg_cur == "-ll" || arg_cur == "--listlabors")
- {
- list_labors = true;
- }
- // add single labor
- else if(arg_cur == "-al" && i < argc-1)
- {
- if (arg_next_int == NOT_SET || arg_next_int >= NUM_CREATURE_LABORS) {
- usage(argc, argv);
- return 1;
- }
- add_labor = true;
- add_labor_n = arg_next_int;
- i++;
- }
- // remove single labor
- else if(arg_cur == "-rl" && i < argc-1)
- {
- if (arg_next_int == NOT_SET || arg_next_int >= NUM_CREATURE_LABORS) {
- usage(argc, argv);
- return 1;
- }
- remove_labor = true;
- remove_labor_n = arg_next_int;
- i++;
- }
- else if(arg_cur == "--setmood" && i < argc-1)
- {
- if (arg_next_int < NO_MOOD || arg_next_int > MAX_MOOD) {
- usage(argc, argv);
- return 1;
- }
- set_mood = true;
- set_mood_n = arg_next_int;
- i++;
- }
- else if(arg_cur == "--sethappiness" && i < argc-1)
- {
- if (arg_next_int < 1 || arg_next_int >= 2000) {
- usage(argc, argv);
- return 1;
- }
- set_happiness = true;
- set_happiness_n = arg_next_int;
- i++;
- }
- else if(arg_cur == "--kill")
- {
- kill_creature = true;
- showallflags = true;
- showdead = true;
- }
- else if(arg_cur == "--erase")
- {
- erase_creature = true;
- showallflags = true;
- showdead = true;
- }
- else if(arg_cur == "--revive")
- {
- revive_creature = true;
- showdead = true;
- showallflags = true;
- }
- else if(arg_cur == "-ral")
- {
- remove_labors = true;
- }
- else if(arg_cur == "-ah")
- {
- make_hauler = true;
- }
- else if(arg_cur == "-rh")
- {
- remove_hauler = true;
- }
- else if(arg_cur == "-nn" || arg_cur == "--nonicks")
- {
- filter.find_nonicks = true;
- }
- else if(arg_cur == "--nicks")
- {
- filter.find_nicks = true;
- }
- else if(arg_cur == "-c" && i < argc-1)
- {
- filter.creature_type = argv[i+1];
- i++;
- }
- else if(arg_cur == "-i" && i < argc-1)
- {
- std::stringstream ss(argv[i+1]);
- int num;
- while (ss >> num) {
- filter.creature_id.push_back(num);
- ss.ignore(1);
- }
-
- filter.creature_type = ""; // if -i is given, match all creatures
- showdead = true;
- i++;
- }
- else if(arg_cur == "--type" && i < argc-1)
- {
- filter.process_type(arg_next);
- i++;
- }
- else if (arg_cur == "--tame")
- tame_creature = true;
- else if (arg_cur == "--slaugher" || arg_cur == "--butcher")
- slaughter_creature = true;
- else
- {
- if (arg_cur != "-h") {
- cout << "Unknown option '" << arg_cur << "'" << endl;
- cout << endl;
- }
- usage(argc, argv);
- return 1;
- }
- }
-
- filter.doneProcessingOptions();
-
- DFHack::ContextManager DFMgr("Memory.xml");
- DFHack::Context* DF;
- try
- {
- DF = DFMgr.getSingleContext();
- DF->Attach();
- }
- catch (exception& e)
- {
- cerr << e.what() << endl;
- if (quiet == false)
- {
- cin.ignore();
- }
- return 1;
- }
-
- Creatures = DF->getCreatures();
- Materials = DF->getMaterials();
- DFHack::Translation * Tran = DF->getTranslation();
-
- uint32_t numCreatures;
- if(!Creatures->Start(numCreatures))
- {
- cerr << "Can't get creatures" << endl;
- if (quiet == false)
- {
- cin.ignore();
- }
- return 1;
- }
- if(!numCreatures)
- {
- cerr << "No creatures to print" << endl;
- if (quiet == false)
- {
- cin.ignore();
- }
- return 1;
- }
-
- mem = DF->getMemoryInfo();
- Materials->ReadInorganicMaterials();
- Materials->ReadOrganicMaterials();
- Materials->ReadWoodMaterials();
- Materials->ReadPlantMaterials();
- Materials->ReadCreatureTypes();
- Materials->ReadCreatureTypesEx();
- Materials->ReadDescriptorColors();
-
- if(!Tran->Start())
- {
- cerr << "Can't get name tables" << endl;
- return 1;
- }
-
- // List all available labors (reproduces contents of Memory.xml)
- if (list_labors == true) {
- string laborname;
- for (int i=0; i < NUM_CREATURE_LABORS; i++) {
- try {
- laborname = mem->getLabor(i);
- cout << "Labor " << int(i) << ": " << laborname << endl;
- }
- catch (exception&) {
- if (verbose)
- {
- laborname = "Unknown";
- cout << "Labor " << int(i) << ": " << laborname << endl;
- }
- }
- }
- }
- else
- {
- if (showfirstlineonly)
- {
- printf("ID Type Name/nickname Job title Current job Happy%s\n", showdead?" Dead ":"");
- printf("--- ----------------- ------------------------ ---------------- -------------------------------------- -----%s\n", showdead?" -----":"");
- }
-
- vector addrs;
- for(uint32_t creature_idx = 0; creature_idx < numCreatures; creature_idx++)
- {
- DFHack::t_creature creature;
- Creatures->ReadCreature(creature_idx,creature);
- /* Check if we want to display/change this creature or skip it */
- if(filter.creatureMatches(creature, creature_idx))
- {
- printCreature(DF,creature,creature_idx);
- addrs.push_back(creature.origin);
-
- bool dochange = (
- remove_skills || remove_civil_skills || remove_military_skills
- || remove_labors || add_labor || remove_labor
- || make_hauler || remove_hauler
- || kill_creature || erase_creature
- || revive_creature
- || set_happiness
- || set_mood
- || tame_creature || slaughter_creature
- );
-
- if (toCaps(filter.creature_type) == "Dwarf"
- && (creature.profession == PROFESSION_CHILD || creature.profession == PROFESSION_BABY))
- {
- dochange = false;
- }
-
- bool allow_massdesignation =
- filter.creature_id.size()==0 ||
- toCaps(filter.creature_type) != "Dwarf" ||
- filter.find_nonicks == true ||
- force_massdesignation;
- if (dochange == true && allow_massdesignation == false)
- {
- cout
- << "Not changing creature because none of -c (other than dwarf), -i or -nn was" << endl
- << "selected. Add -f (force) to override this safety measure." << endl;
- dochange = false;
- }
-
- if (dochange)
- {
- if(creature.has_default_soul)
- {
- if (kill_creature && !creature.flags1.bits.dead)
- {
- DFHack::t_creaturflags1 f1 = creature.flags1;
- DFHack::t_creaturflags2 f2 = creature.flags2;
- DFHack::t_creaturflags3 f3 = creature.flags3;
-
- f3.bits.scuttle = true;
-
- cout << "Writing flags..." << endl;
- if (!Creatures->WriteFlags(creature_idx, f1.whole,
- f2.whole, f3.whole))
- {
- cout << "Error writing creature flags!" << endl;
- }
- // We want the flags to be shown after our
- // modification, but they are not read back
- creature.flags1 = f1;
- creature.flags2 = f2;
- creature.flags3 = f3;
- }
-
- if (erase_creature && !creature.flags1.bits.dead)
- {
- /*
- [quote author=Eldrick Tobin link=topic=58809.msg2178545#msg2178545 date=1302638055]
-
- After extensive testing that just ate itself -.-;
-
- Runesmith does not unset the following:
- - Active Invader (sets if they are just about the invade, as Currently
- Invading removes this one)
- - Hidden Ambusher (Just in Case, however it is still set when an Active Invader)
- - Hidden in Ambush (Just in Case, however it is still set when an Active Invader,
- until discovery)
- - Incoming (Sets if something is here yet... wave X of a siege here)
- - Invader -Fleeing/Leaving
- - Currently Invading
-
- When it nukes something it basically just sets them to 'dead'. It does not also
- set them to 'killed'. Show dead will show everything (short of 'vanished'/'deleted'
- I'd suspect) so one CAN go through the intensive process to revive a broken siege. These
- particular flags are not visible at the same exact time so multiple passes -even through
- a narrow segment- are advised.
-
- Problem I ran into (last thing before I mention something more DFHack related):
- I set the Killed Flag (but not dead), and I got mortally wounded siegers that refused to
- just pift in Magma. [color=purple]Likely missing upper torsoes on examination[/color].
-
- */
- /* This is from an invading creature's flags:
-
- ID: 560, Crocodile Cave, Nako, Standard, Job: No Job, Happiness: 100
- Flag: Marauder
- Flag: Can Swap
- Flag: Active Invader
- Flag: Invader Origin
- Flag: Coward
- Flag: Hidden Ambusher
- Flag: Invades
- Flag: Ridden
- Flag: Calculated Nerves
- Flag: Calculated Bodyparts
- Flag: Calculated Insulation
- Flag: Vision Good
- Flag: Breathing Good
-
- */
-
- DFHack::t_creaturflags1 f1 = creature.flags1;
- DFHack::t_creaturflags2 f2 = creature.flags2;
-
- f1.bits.dead = 1;
- f2.bits.killed = 1;
- f1.bits.active_invader = 0; /*!< 17: Active invader (for organized ones) */
- f1.bits.hidden_ambusher = 0; /*!< 21: Active marauder/invader moving inward? */
- f1.bits.hidden_in_ambush = 0;
- f1.bits.invades = 0; /*!< 22: Marauder resident/invader moving in all the way */
-
- cout << "Writing flags..." << endl;
- if (!Creatures->WriteFlags(creature_idx, f1.whole, f2.whole))
- {
- cout << "Error writing creature flags!" << endl;
- }
- // We want the flags to be shown after our modification, but they are not read back
- creature.flags1 = f1;
- creature.flags2 = f2;
- }
-
-
- if (revive_creature && creature.flags1.bits.dead)
- {
- DFHack::t_creaturflags1 f1 = creature.flags1;
- DFHack::t_creaturflags2 f2 = creature.flags2;
-
- f1.bits.dead = 0;
- f2.bits.killed = 0;
- f1.bits.active_invader = 1; /*!< 17: Active invader (for organized ones) */
- f1.bits.hidden_ambusher = 1; /*!< 21: Active marauder/invader moving inward? */
- f1.bits.hidden_in_ambush = 1;
- f1.bits.invades = 1; /*!< 22: Marauder resident/invader moving in all the way */
-
- cout << "Writing flags..." << endl;
- if (!Creatures->WriteFlags(creature_idx, f1.whole, f2.whole))
- {
- cout << "Error writing creature flags!" << endl;
- }
- // We want the flags to be shown after our modification, but they are not read back
- creature.flags1 = f1;
- creature.flags2 = f2;
- }
-
- if (set_mood)
- {
- /* Doesn't really work to disable a mood */
- cout << "Setting mood to " << set_mood_n << "..." << endl;
- Creatures->WriteMood(creature_idx, set_mood_n);
- DFHack::t_creaturflags1 f1 = creature.flags1;
- DFHack::t_creaturflags2 f2 = creature.flags2;
- f1.bits.has_mood = (set_mood_n == NO_MOOD ? 0 : 1);
- if (!Creatures->WriteFlags(creature_idx, f1.whole, f2.whole))
- {
- cout << "Error writing creature flags!" << endl;
- }
- creature.flags1 = f1;
- creature.flags2 = f2;
- }
-
- if (set_happiness)
- {
- cout << "Setting happiness to " << set_happiness_n << "..." << endl;
- Creatures->WriteHappiness(creature_idx, set_happiness_n);
- }
-
- if (remove_skills || remove_civil_skills || remove_military_skills)
- {
- DFHack::t_soul & soul = creature.defaultSoul;
-
- cout << "Removing skills..." << endl;
-
- for(unsigned int sk = 0; sk < soul.numSkills;sk++)
- {
- bool is_military = is_in(soul.skills[sk].id, military_skills, sizeof(military_skills)/sizeof(military_skills[0]));
- if (remove_skills
- || (remove_civil_skills && !is_military)
- || (remove_military_skills && is_military))
- {
- soul.skills[sk].rating=0;
- soul.skills[sk].experience=0;
- }
- }
-
- // Doesn't work anyways, so better leave it alone
- //soul.numSkills=0;
- if (Creatures->WriteSkills(creature_idx, soul) == true) {
- cout << "Success writing skills." << endl;
- } else {
- cout << "Error writing skills." << endl;
- }
- }
-
- if (add_labor || remove_labor || remove_labors || make_hauler || remove_hauler)
- {
- if (add_labor) {
- cout << "Adding labor " << add_labor_n << "..." << endl;
- creature.labors[add_labor_n] = 1;
- }
-
- if (remove_labor) {
- cout << "Removing labor " << remove_labor_n << "..." << endl;
- creature.labors[remove_labor_n] = 0;
- }
-
- if (remove_labors) {
- cout << "Removing labors..." << endl;
- for(unsigned int lab = 0; lab < NUM_CREATURE_LABORS; lab++) {
- creature.labors[lab] = 0;
- }
- }
-
- if (remove_hauler) {
- for (int labs=0;
- labs < sizeof(hauler_labors)/sizeof(hauler_labors[0]);
- labs++)
- {
- creature.labors[hauler_labors[labs]] = 0;
- }
- }
-
- if (make_hauler) {
- cout << "Setting hauler labors..." << endl;
- for (int labs=0;
- labs < sizeof(hauler_labors)/sizeof(hauler_labors[0]);
- labs++)
- {
- creature.labors[hauler_labors[labs]] = 1;
- }
- }
- if (Creatures->WriteLabors(creature_idx, creature.labors) == true) {
- cout << "Success writing labors." << endl;
- } else {
- cout << "Error writing labors." << endl;
- }
- }
-
- if (tame_creature)
- {
- bool tame = true;
-
- DFHack::t_creaturflags1 f1 = creature.flags1;
- DFHack::t_creaturflags2 f2 = creature.flags2;
-
- // Site residents are intelligent, so don't
- // tame them.
- if (f2.bits.resident)
- tame = false;
-
- f1.bits.diplomat = false;
- f1.bits.merchant = false;
- f2.bits.resident = false;
- f2.bits.underworld = false;
- f2.bits.visitor_uninvited = false;
- f2.bits.roaming_wilderness_population_source = false;
- f2.bits.roaming_wilderness_population_source_not_a_map_feature = false;
-
- // Creatures which already belong to a civ might
- // be intelligent, so don't tame them.
- if (creature.civ == -1)
- f1.bits.tame = tame;
-
- if (!Creatures->WriteFlags(creature_idx,
- f1.whole, f2.whole))
- {
- cout << "Error writing creature flags!" << endl;
- }
-
- int32_t civ = Creatures->GetDwarfCivId();
- if (!Creatures->WriteCiv(creature_idx, civ))
- {
- cout << "Error writing creature civ!" << endl;
- }
- creature.flags1 = f1;
- creature.flags2 = f2;
- }
-
- if (slaughter_creature)
- {
- DFHack::t_creaturflags1 f1 = creature.flags1;
- DFHack::t_creaturflags2 f2 = creature.flags2;
-
- f2.bits.slaughter = true;
-
- if (!Creatures->WriteFlags(creature_idx,
- f1.whole, f2.whole))
- {
- cout << "Error writing creature flags!" << endl;
- }
- creature.flags1 = f1;
- creature.flags2 = f2;
- }
- }
- else
- {
- cout << "Error removing skills: Creature has no default soul." << endl;
- }
- printCreature(DF,creature,creature_idx);
- } /* End remove skills/labors */
- } /* if (print creature) */
- } /* End for(all creatures) */
- } /* End if (we need to walk creatures) */
-
- Creatures->Finish();
- DF->Detach();
- if (quiet == false)
- {
- cout << "Done. Press any key to continue" << endl;
- cin.ignore();
- }
- return 0;
-}
From 5b54909886bdd58087506d4d35c43edc073b3a14 Mon Sep 17 00:00:00 2001
From: Peridexis Errant
Date: Tue, 6 Jan 2015 22:48:24 +1100
Subject: [PATCH 04/28] Move hotkey-notes to scripts, delete needs_porting!
The notes script is unfinished, but that's the last thing to do - since
everything else is obsolete, ported, or the subject of a github issue to
make a replacement.
---
needs_porting/_notes.txt | 9 -------
{needs_porting => scripts}/hotkey-notes.lua | 30 ++++-----------------
2 files changed, 5 insertions(+), 34 deletions(-)
delete mode 100644 needs_porting/_notes.txt
rename {needs_porting => scripts}/hotkey-notes.lua (54%)
diff --git a/needs_porting/_notes.txt b/needs_porting/_notes.txt
deleted file mode 100644
index cdd364d12..000000000
--- a/needs_porting/_notes.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-TODO:
- copypaste.cpp
- high value target - a proof of concept plugin to allow copy-pasting in DF; does both terrain and buildings/constructions
- creaturemanager.cpp
- modify skills and labors of creatures, kill creatures, etc; impressive but I suspect most functions implemented elsewhere
-
-In progress:
- hotkey-notes.lua
- prints list of hotkeys with name and jump position
diff --git a/needs_porting/hotkey-notes.lua b/scripts/hotkey-notes.lua
similarity index 54%
rename from needs_porting/hotkey-notes.lua
rename to scripts/hotkey-notes.lua
index a84506512..30654911e 100644
--- a/needs_porting/hotkey-notes.lua
+++ b/scripts/hotkey-notes.lua
@@ -1,5 +1,9 @@
-- prints info on assigned hotkeys to the console
+-- A work in progress, hoping for some help!
+-- A different approach might be needed depending on internal structures,
+-- but this gets the idea across.
+
local hotkeys = {'F1 ', 'F2 ', 'F3 ', 'F4 ', 'F5 ', 'F6 ',
'F7 ', 'F8 ', 'F9 ', 'F10', 'F11', 'F12'}
@@ -13,28 +17,4 @@ for i=1, #hotkeys do
hk.z = df.global.window_z
print(hk.id..' '..hk.name..' X= '..hk.x..', Y= '..hk.y..', Z= '..hk.z)
-end
-
---[[
-# the (very) old Python version...
-from context import Context, ContextManager
-
-cm = ContextManager("Memory.xml")
-df = cm.get_single_context()
-
-df.attach()
-
-gui = df.gui
-
-print "Hotkeys"
-
-hotkeys = gui.read_hotkeys()
-
-for key in hotkeys:
- print "x: %d\ny: %d\tz: %d\ttext: %s" % (key.x, key.y, key.z, key.name)
-
-df.detach()
-
-print "Done. Press any key to continue"
-raw_input()
-]]--
+end
\ No newline at end of file
From 49990868462bdcdae0ca4080c7d772390a597af6 Mon Sep 17 00:00:00 2001
From: lethosor
Date: Wed, 7 Jan 2015 16:03:24 -0500
Subject: [PATCH 05/28] Use "OSX" in package names on OS X instead of "Darwin"
---
CMakeLists.txt | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 984bb09e7..a01129418 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -188,5 +188,10 @@ ELSEIF(WIN32)
SET(CPACK_GENERATOR "ZIP")
ENDIF()
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)
-set(CPACK_PACKAGE_FILE_NAME "dfhack-${DFHACK_VERSION}-${CMAKE_SYSTEM_NAME}")
+IF(APPLE)
+ set(DFHACK_PACKAGE_PLATFORM_NAME OSX)
+ELSE()
+ set(DFHACK_PACKAGE_PLATFORM_NAME ${CMAKE_SYSTEM_NAME})
+ENDIF()
+set(CPACK_PACKAGE_FILE_NAME "dfhack-${DFHACK_VERSION}-${DFHACK_PACKAGE_PLATFORM_NAME}")
INCLUDE(CPack)
From b030bb08fec87da89717a20cf999c0284654064f Mon Sep 17 00:00:00 2001
From: Peridexis Errant
Date: Thu, 8 Jan 2015 11:11:09 +1100
Subject: [PATCH 06/28] Finish and document hotkey-notes
All working correctly - thus ends the long story of the needs_porting
folder.
---
NEWS | 4 ++++
Readme.rst | 4 ++++
scripts/hotkey-notes.lua | 28 ++++++++++------------------
3 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/NEWS b/NEWS
index 04819a438..065c08aa8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,8 @@
DFHack Future
+ New Scripts
+ hotkey-notes: print key, name, and jump position of hotkeys
+ Removed
+ needs_porting/*
diff --git a/Readme.rst b/Readme.rst
index 609a98dcd..5d2d86dee 100644
--- a/Readme.rst
+++ b/Readme.rst
@@ -2394,6 +2394,10 @@ is "hfs-pit 1 0 0", ie single-tile wide with no walls or stairs.
First example is a four-across pit with stairs but no walls; second is a
two-across pit with stairs but no walls.
+hotkey-notes
+============
+Lists the key, name, and jump position of your hotkeys.
+
lever
=====
Allow manipulation of in-game levers from the dfhack console.
diff --git a/scripts/hotkey-notes.lua b/scripts/hotkey-notes.lua
index 30654911e..c8b9b9606 100644
--- a/scripts/hotkey-notes.lua
+++ b/scripts/hotkey-notes.lua
@@ -1,20 +1,12 @@
-- prints info on assigned hotkeys to the console
--- A work in progress, hoping for some help!
--- A different approach might be needed depending on internal structures,
--- but this gets the idea across.
-
-local hotkeys = {'F1 ', 'F2 ', 'F3 ', 'F4 ', 'F5 ', 'F6 ',
- 'F7 ', 'F8 ', 'F9 ', 'F10', 'F11', 'F12'}
-
-for i=1, #hotkeys do
- local hk = hotkeys[i]
- hk = {id=hk}
- -- PLACEHOLDER PROPERTIES ONLY!
- hk.name = '_name'
- hk.x = df.global.window_x
- hk.y = df.global.window_y
- hk.z = df.global.window_z
-
- print(hk.id..' '..hk.name..' X= '..hk.x..', Y= '..hk.y..', Z= '..hk.z)
-end
\ No newline at end of file
+local h_list = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8',
+ 'Shift+F1', 'Shift+F2', 'Shift+F3', 'Shift+F4',
+ 'Shift+F5', 'Shift+F6', 'Shift+F7', 'Shift+F8'}
+
+for i=1, #df.global.ui.main.hotkeys do
+ local hk = df.global.ui.main.hotkeys[i-1]
+ if hk.cmd ~= -1 then
+ print(h_list[i]..': '..hk.name..': x='..hk.x..' y='..hk.y..' z='..hk.z)
+ end
+end
From 4ab233694f734241c15030ad57a947da4e0ae386 Mon Sep 17 00:00:00 2001
From: Peridexis Errant
Date: Thu, 8 Jan 2015 13:02:07 +1100
Subject: [PATCH 07/28] tabs -> space in NEWS
---
NEWS | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/NEWS b/NEWS
index 065c08aa8..238a321a3 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,8 @@
DFHack Future
New Scripts
- hotkey-notes: print key, name, and jump position of hotkeys
+ hotkey-notes: print key, name, and jump position of hotkeys
Removed
- needs_porting/*
+ needs_porting/*
@@ -28,7 +28,7 @@ DFHack 0.40.23-r1
Fixed a display issue with PRINT_MODE:TEXT
Fixed a symbol error (MapExtras::BiomeInfo::MAX_LAYERS) when compiling DFHack in Debug mode
New Plugins
- fortplan: designate construction of (limited) buildings from .csv file, quickfort-style
+ fortplan: designate construction of (limited) buildings from .csv file, quickfort-style
New Scripts
gui/stockpiles: an in-game interface for saving and loading stockpile
settings files.
From 9f0558b5471dd364bb3ab3f8ea38baf118ee1444 Mon Sep 17 00:00:00 2001
From: Peridexis Errant
Date: Thu, 8 Jan 2015 13:10:11 +1100
Subject: [PATCH 08/28] Allow for other hotkeys keybinds
Using this method is more compact and more flexible. Also tabs to
spaces...
---
scripts/hotkey-notes.lua | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/scripts/hotkey-notes.lua b/scripts/hotkey-notes.lua
index c8b9b9606..2b713e6bb 100644
--- a/scripts/hotkey-notes.lua
+++ b/scripts/hotkey-notes.lua
@@ -1,12 +1,9 @@
-- prints info on assigned hotkeys to the console
-local h_list = {'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8',
- 'Shift+F1', 'Shift+F2', 'Shift+F3', 'Shift+F4',
- 'Shift+F5', 'Shift+F6', 'Shift+F7', 'Shift+F8'}
-
for i=1, #df.global.ui.main.hotkeys do
local hk = df.global.ui.main.hotkeys[i-1]
- if hk.cmd ~= -1 then
- print(h_list[i]..': '..hk.name..': x='..hk.x..' y='..hk.y..' z='..hk.z)
- end
+ local key = dfhack.screen.getKeyDisplay(df.interface_key.D_HOTKEY1 + i - 1)
+ if hk.cmd ~= -1 then
+ print(key..': '..hk.name..': x='..hk.x..' y='..hk.y..' z='..hk.z)
+ end
end
From 819327348b3c8f3274de22c52972c4f5d46a8486 Mon Sep 17 00:00:00 2001
From: Chris Dombroski
Date: Wed, 7 Jan 2015 16:27:48 -0500
Subject: [PATCH 09/28] 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 10/28] 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 859fdd60d6c058ae77420c97118543109b5004ba Mon Sep 17 00:00:00 2001
From: lethosor
Date: Thu, 8 Jan 2015 16:59:25 -0500
Subject: [PATCH 11/28] annoucnement -> announcement
---
plugins/search.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/plugins/search.cpp b/plugins/search.cpp
index 929cd653c..a1ad442bd 100644
--- a/plugins/search.cpp
+++ b/plugins/search.cpp
@@ -1382,7 +1382,7 @@ IMPLEMENT_HOOKS(df::viewscreen_buildinglistst, roomlist_search);
//
// START: Announcement list search
//
-class annoucnement_search : public search_generic
+class announcement_search : public search_generic
{
public:
void render() const
@@ -1410,7 +1410,7 @@ private:
};
-IMPLEMENT_HOOKS(df::viewscreen_announcelistst, annoucnement_search);
+IMPLEMENT_HOOKS(df::viewscreen_announcelistst, announcement_search);
//
// END: Announcement list search
@@ -1746,7 +1746,7 @@ IMPLEMENT_HOOKS(df::viewscreen_dwarfmodest, room_assign_search);
HOOK_ACTION(military_search_hook) \
HOOK_ACTION(nobles_search_hook) \
HOOK_ACTION(profiles_search_hook) \
- HOOK_ACTION(annoucnement_search_hook) \
+ HOOK_ACTION(announcement_search_hook) \
HOOK_ACTION(joblist_search_hook) \
HOOK_ACTION(burrow_search_hook) \
HOOK_ACTION(stockpile_search_hook) \
From aa332e18e28a803098d74dffc078dfb32593461d Mon Sep 17 00:00:00 2001
From: lethosor
Date: Thu, 8 Jan 2015 16:59:37 -0500
Subject: [PATCH 12/28] Remove stray whitespace
---
plugins/search.cpp | 52 +++++++++++++++++++++++-----------------------
1 file changed, 26 insertions(+), 26 deletions(-)
diff --git a/plugins/search.cpp b/plugins/search.cpp
index a1ad442bd..b4428f049 100644
--- a/plugins/search.cpp
+++ b/plugins/search.cpp
@@ -984,9 +984,9 @@ private:
return desc;
}
- bool should_check_input(set *input)
+ bool should_check_input(set *input)
{
- if (input->count(interface_key::CURSOR_LEFT) || input->count(interface_key::CURSOR_RIGHT) ||
+ if (input->count(interface_key::CURSOR_LEFT) || input->count(interface_key::CURSOR_RIGHT) ||
(!in_entry_mode() && input->count(interface_key::UNITVIEW_PRF_PROF)))
{
if (!in_entry_mode())
@@ -1009,17 +1009,17 @@ private:
return 'q';
}
- vector *get_secondary_list()
+ vector *get_secondary_list()
{
return &viewscreen->jobs[viewscreen->page];
}
- int32_t *get_viewscreen_cursor()
+ int32_t *get_viewscreen_cursor()
{
return &viewscreen->cursor_pos[viewscreen->page];
}
- vector *get_primary_list()
+ vector *get_primary_list()
{
return &viewscreen->units[viewscreen->page];
}
@@ -1092,7 +1092,7 @@ public:
// but the native hotkeys are where we normally write.
return;
}
-
+
print_search_option(2, -1);
if (!search_string.empty())
@@ -1121,7 +1121,7 @@ private:
return &viewscreen->trader_items;
}
- char get_search_select_key()
+ char get_search_select_key()
{
return 'q';
}
@@ -1142,7 +1142,7 @@ public:
// but the native hotkeys are where we normally write.
return;
}
-
+
int32_t x = gps->dimx / 2 + 2;
print_search_option(x, -1);
@@ -1171,7 +1171,7 @@ private:
return &viewscreen->broker_items;
}
- char get_search_select_key()
+ char get_search_select_key()
{
return 'w';
}
@@ -1206,12 +1206,12 @@ public:
print_search_option(51, 23);
}
- vector *get_primary_list()
+ vector *get_primary_list()
{
return &viewscreen->item_names;
}
- vector *get_secondary_list()
+ vector *get_secondary_list()
{
return &viewscreen->item_status;
}
@@ -1260,7 +1260,7 @@ public:
return true;
}
- vector *get_primary_list()
+ vector *get_primary_list()
{
return &viewscreen->positions.candidates;
}
@@ -1273,7 +1273,7 @@ public:
int32_t *cursor = get_viewscreen_cursor();
df::unit *selected_unit = get_primary_list()->at(*cursor);
clear_search();
-
+
for (*cursor = 0; *cursor < get_primary_list()->size(); (*cursor)++)
{
if (get_primary_list()->at(*cursor) == selected_unit)
@@ -1351,21 +1351,21 @@ private:
desc += name;
}
}
-
+
return desc;
}
- vector *get_secondary_list()
+ vector *get_secondary_list()
{
return &viewscreen->room_value;
}
- int32_t *get_viewscreen_cursor()
+ int32_t *get_viewscreen_cursor()
{
return &viewscreen->cursor;
}
- vector *get_primary_list()
+ vector *get_primary_list()
{
return &viewscreen->buildings;
}
@@ -1452,7 +1452,7 @@ public:
return nobles_search_base::can_init(screen);
}
- vector *get_primary_list()
+ vector *get_primary_list()
{
return &viewscreen->candidates;
}
@@ -1482,7 +1482,7 @@ public:
print_search_option(2, 23);
}
- vector *get_primary_list()
+ vector *get_primary_list()
{
return &viewscreen->workers;
}
@@ -1509,7 +1509,7 @@ void get_job_details(string &desc, df::job *job)
desc += c;
}
desc += ".";
-
+
df::item_type itype = ENUM_ATTR(job_type, item, job->job_type);
MaterialInfo mat(job);
@@ -1582,17 +1582,17 @@ private:
return 'q';
}
- vector *get_secondary_list()
+ vector *get_secondary_list()
{
return &viewscreen->units;
}
- int32_t *get_viewscreen_cursor()
+ int32_t *get_viewscreen_cursor()
{
return &viewscreen->cursor_pos;
}
- vector *get_primary_list()
+ vector *get_primary_list()
{
return &viewscreen->jobs;
}
@@ -1638,17 +1638,17 @@ public:
print_search_option(x, y);
}
- vector *get_primary_list()
+ vector *get_primary_list()
{
return &ui->burrows.list_units;
}
- vector *get_secondary_list()
+ vector *get_secondary_list()
{
return &ui->burrows.sel_units;
}
- virtual int32_t * get_viewscreen_cursor()
+ virtual int32_t * get_viewscreen_cursor()
{
return &ui->burrows.unit_cursor_pos;
}
From ea313b6bf5b2e27cd217a02069746e8143b838ee Mon Sep 17 00:00:00 2001
From: Chris Dombroski
Date: Fri, 9 Jan 2015 16:00:47 -0500
Subject: [PATCH 13/28] 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 077d149d645c249f0317fe2b2e42de7f3783e9ee Mon Sep 17 00:00:00 2001
From: lethosor
Date: Sun, 11 Jan 2015 12:48:52 -0500
Subject: [PATCH 14/28] Expose key modifier state to C++/Lua
---
library/Core.cpp | 31 ++++++++++++++-----------------
library/LuaApi.cpp | 19 +++++++++++++++++++
library/include/Core.h | 6 ++++++
3 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/library/Core.cpp b/library/Core.cpp
index 19e2c4345..452c294e3 100644
--- a/library/Core.cpp
+++ b/library/Core.cpp
@@ -714,7 +714,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first, ve
std::string keystr = parts[1];
if (parts[0] == "set")
ClearKeyBindings(keystr);
- for (int i = parts.size()-1; i >= 2; i--)
+ for (int i = parts.size()-1; i >= 2; i--)
{
if (!AddKeyBinding(keystr, parts[i])) {
con.printerr("Invalid key spec: %s\n", keystr.c_str());
@@ -910,7 +910,7 @@ void fIOthread(void * iodata)
main_history.add(command);
main_history.save("dfhack.history");
}
-
+
auto rv = core->runCommand(con, command);
if (rv == CR_NOT_IMPLEMENTED)
@@ -1091,6 +1091,7 @@ bool Core::Init()
screen_window = new Windows::top_level_window();
screen_window->addChild(new Windows::dfhack_dummy(5,10));
started = true;
+ modstate = 0;
cerr << "Starting the TCP listener.\n";
server = new ServerMain();
@@ -1579,7 +1580,7 @@ int UnicodeAwareSym(const SDL::KeyboardEvent& ke)
//MEMO: return false if event is consumed
int Core::DFH_SDL_Event(SDL::Event* ev)
{
- static bool alt = 0;
+ //static bool alt = 0;
// do NOT process events before we are ready.
if(!started) return true;
@@ -1589,31 +1590,27 @@ int Core::DFH_SDL_Event(SDL::Event* ev)
{
auto ke = (SDL::KeyboardEvent *)ev;
- if (ke->ksym.sym == SDL::K_LALT || ke->ksym.sym == SDL::K_RALT)
- {
- alt = (ev->type == SDL::ET_KEYDOWN);
- }
- else
- if(ke->state == SDL::BTN_PRESSED && !hotkey_states[ke->ksym.sym])
+ if (ke->ksym.sym == SDL::K_LSHIFT || ke->ksym.sym == SDL::K_RSHIFT)
+ modstate = (ev->type == SDL::ET_KEYDOWN) ? modstate | MOD_SHIFT : modstate & ~MOD_SHIFT;
+ else if (ke->ksym.sym == SDL::K_LCTRL || ke->ksym.sym == SDL::K_RCTRL)
+ modstate = (ev->type == SDL::ET_KEYDOWN) ? modstate | MOD_CTRL : modstate & ~MOD_CTRL;
+ else if (ke->ksym.sym == SDL::K_LALT || ke->ksym.sym == SDL::K_RALT)
+ modstate = (ev->type == SDL::ET_KEYDOWN) ? modstate | MOD_ALT : modstate & ~MOD_ALT;
+ else if(ke->state == SDL::BTN_PRESSED && !hotkey_states[ke->ksym.sym])
{
hotkey_states[ke->ksym.sym] = true;
- int mod = 0;
- if (ke->ksym.mod & SDL::KMOD_SHIFT) mod |= 1;
- if (ke->ksym.mod & SDL::KMOD_CTRL) mod |= 2;
- if (alt) mod |= 4;
-
// Use unicode so Windows gives the correct value for the
// user's Input Language
if((ke->ksym.unicode & 0xff80) == 0)
{
int key = UnicodeAwareSym(*ke);
- SelectHotkey(key, mod);
+ SelectHotkey(key, modstate);
}
else
{
// Pretend non-ascii characters don't happen:
- SelectHotkey(ke->ksym.sym, mod);
+ SelectHotkey(ke->ksym.sym, modstate);
}
}
else if(ke->state == SDL::BTN_RELEASED)
@@ -1710,7 +1707,7 @@ static bool parseKeySpec(std::string keyspec, int *psym, int *pmod, std::string
} else if (keyspec.size() > 4 && keyspec.substr(0, 4) == "Alt-") {
*pmod |= 4;
keyspec = keyspec.substr(4);
- } else
+ } else
break;
}
diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp
index f2693363a..f9b19b102 100644
--- a/library/LuaApi.cpp
+++ b/library/LuaApi.cpp
@@ -2008,10 +2008,12 @@ static void *checkaddr(lua_State *L, int idx, bool allow_null = false)
static uint32_t getImageBase() { return Core::getInstance().p->getBase(); }
static int getRebaseDelta() { return Core::getInstance().vinfo->getRebaseDelta(); }
+static int8_t getModstate() { return Core::getInstance().getModstate(); }
static const LuaWrapper::FunctionReg dfhack_internal_module[] = {
WRAP(getImageBase),
WRAP(getRebaseDelta),
+ WRAP(getModstate),
{ NULL, NULL }
};
@@ -2351,6 +2353,22 @@ static int internal_runCommand(lua_State *L)
return 1;
}
+static int internal_getModifiers(lua_State *L)
+{
+ int8_t modstate = Core::getInstance().getModstate();
+ lua_newtable(L);
+ lua_pushstring(L, "shift");
+ lua_pushboolean(L, modstate & MOD_SHIFT);
+ lua_settable(L, -3);
+ lua_pushstring(L, "ctrl");
+ lua_pushboolean(L, modstate & MOD_CTRL);
+ lua_settable(L, -3);
+ lua_pushstring(L, "alt");
+ lua_pushboolean(L, modstate & MOD_ALT);
+ lua_settable(L, -3);
+ return 1;
+}
+
static const luaL_Reg dfhack_internal_funcs[] = {
{ "getAddress", internal_getAddress },
{ "setAddress", internal_setAddress },
@@ -2365,6 +2383,7 @@ static const luaL_Reg dfhack_internal_funcs[] = {
{ "diffscan", internal_diffscan },
{ "getDir", internal_getDir },
{ "runCommand", internal_runCommand },
+ { "getModifiers", internal_getModifiers },
{ NULL, NULL }
};
diff --git a/library/include/Core.h b/library/include/Core.h
index b3db50c74..f3166496a 100644
--- a/library/include/Core.h
+++ b/library/include/Core.h
@@ -36,6 +36,10 @@ distribution.
#include "RemoteClient.h"
+#define MOD_SHIFT 1
+#define MOD_CTRL 2
+#define MOD_ALT 4
+
struct WINDOW;
namespace tthread
@@ -142,6 +146,7 @@ namespace DFHack
bool ClearKeyBindings(std::string keyspec);
bool AddKeyBinding(std::string keyspec, std::string cmdline);
std::vector ListKeyBindings(std::string keyspec);
+ int8_t getModstate() { return modstate; }
std::string getHackPath();
@@ -216,6 +221,7 @@ namespace DFHack
std::string cmdline;
std::string focus;
};
+ int8_t modstate;
std::map > key_bindings;
std::map hotkey_states;
From e20808b6f6b4bc4bd2f6e80e2a84dc2039961643 Mon Sep 17 00:00:00 2001
From: Lethosor
Date: Sun, 11 Jan 2015 13:53:51 -0500
Subject: [PATCH 15/28] Allow `dfhack` script to be run from other directories
on OS X
---
package/darwin/dfhack | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package/darwin/dfhack b/package/darwin/dfhack
index 55aa81a98..8040a837a 100755
--- a/package/darwin/dfhack
+++ b/package/darwin/dfhack
@@ -1,5 +1,6 @@
#!/bin/sh
PWD=`dirname "${0}"`
+cd "${PWD}"
#thanks to Iriel for figuring this out
OSREV=`uname -r | cut -d. -f1`
if [ "$OSREV" -ge 11 ] ; then
@@ -11,7 +12,6 @@ else
fi
old_tty_settings=$(stty -g)
-cd "${PWD}"
DYLD_INSERT_LIBRARIES=./hack/libdfhack.dylib ./dwarfort.exe "$@"
stty "$old_tty_settings"
echo ""
From f510cd7c11c34d1a8ded74d207d2e9d369a9a008 Mon Sep 17 00:00:00 2001
From: warmist
Date: Tue, 13 Jan 2015 10:30:53 +0200
Subject: [PATCH 16/28] Update advfort.lua
Fix bug with building jobs
---
scripts/gui/advfort.lua | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/scripts/gui/advfort.lua b/scripts/gui/advfort.lua
index 921dd87cf..17aef6a42 100644
--- a/scripts/gui/advfort.lua
+++ b/scripts/gui/advfort.lua
@@ -1,8 +1,10 @@
-- allows to do jobs in adv. mode.
--[==[
- version: 0.011
+ version: 0.012
changelog:
+ *0.012
+ - fix for some jobs not finding correct building.
*0.011
- fixed crash with building jobs (other jobs might have been crashing too!)
- fixed bug with building asking twice to input items
@@ -1123,7 +1125,7 @@ function usetool:openShopWindow(building)
local filter_pile=workshopJobs.getJobs(building:getType(),building:getSubtype(),building:getCustomType())
if filter_pile then
- local state={unit=adv,from_pos={x=adv.pos.x,y=adv.pos.y, z=adv.pos.z,building=building}
+ local state={unit=adv,from_pos={x=adv.pos.x,y=adv.pos.y, z=adv.pos.z},building=building
,screen=self,bld=building,common=filter_pile.common}
choices={}
for k,v in pairs(filter_pile) do
@@ -1455,4 +1457,4 @@ end
if not (dfhack.gui.getCurFocus()=="dungeonmode/Look" or dfhack.gui.getCurFocus()=="dungeonmode/Default") then
qerror("This script requires an adventurer mode with (l)ook or default mode.")
end
-usetool():show()
\ No newline at end of file
+usetool():show()
From 3489c2f39a352fca12b1dd01b3af8bc27554cee3 Mon Sep 17 00:00:00 2001
From: Chris Dombroski
Date: Mon, 12 Jan 2015 11:52:46 -0500
Subject: [PATCH 17/28] 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 18/28] 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 19/28] 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 20/28] 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 21/28] 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 22/28] 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