From 9cb1a45855751bfbab546ccb3249593c02019f82 Mon Sep 17 00:00:00 2001 From: Anuradha Dissanayake Date: Tue, 20 Nov 2012 23:12:11 +1300 Subject: [PATCH 01/35] Automaterial branch commit --- plugins/CMakeLists.txt | 1 + plugins/automaterial.cpp | 430 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 431 insertions(+) create mode 100644 plugins/automaterial.cpp diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 91d578215..5bda932ce 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -117,6 +117,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(regrass regrass.cpp) DFHACK_PLUGIN(forceequip forceequip.cpp) DFHACK_PLUGIN(manipulator manipulator.cpp) + DFHACK_PLUGIN(automaterial automaterial.cpp) # this one exports functions to lua DFHACK_PLUGIN(burrows burrows.cpp LINK_LIBRARIES lua) DFHACK_PLUGIN(sort sort.cpp LINK_LIBRARIES lua) diff --git a/plugins/automaterial.cpp b/plugins/automaterial.cpp new file mode 100644 index 000000000..2e39f3411 --- /dev/null +++ b/plugins/automaterial.cpp @@ -0,0 +1,430 @@ +// Auto Material Select + +#include +#include +#include + +#include "Core.h" +#include +#include +#include +#include + + +// DF data structure definition headers +#include "DataDefs.h" +#include "MiscUtils.h" +#include "df/viewscreen_dwarfmodest.h" +#include "df/ui_build_selector.h" +#include "df/build_req_choice_genst.h" +#include "df/build_req_choice_specst.h" +#include "df/item.h" + +#include "df/ui.h" +#include "modules/Gui.h" +#include "modules/Screen.h" + +using std::map; +using std::string; +using std::vector; + +using namespace DFHack; +using namespace df::enums; +using df::global::gps; +using df::global::ui; +using df::global::ui_build_selector; + + +DFHACK_PLUGIN("automaterial"); + +struct MaterialDescriptor +{ + df::item_type item_type; + int16_t item_subtype; + int16_t type; + int32_t index; + bool valid; + + bool matches(const MaterialDescriptor &a) const + { + return a.valid && valid && + a.type == type && + a.index == index && + a.item_type == item_type && + a.item_subtype == item_subtype; + } +}; + +typedef int16_t construction_type; + +static map last_used_material; +static map last_moved_material; +static map< construction_type, vector > preferred_materials; +static map< construction_type, df::interface_key > hotkeys; +static bool last_used_moved = false; +static bool auto_choose_materials = true; +static bool auto_choose_attempted = true; +static bool revert_to_last_used_type = false; + +static command_result automaterial_cmd(color_ostream &out, vector & parameters) +{ + return CR_OK; +} + + +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) +{ + return CR_OK; +} + + +void OutputString(int8_t color, int &x, int &y, const std::string &text, bool newline = false, int left_margin = 0) +{ + Screen::paintString(Screen::Pen(' ', color, 0), x, y, text); + if (newline) + { + ++y; + x = left_margin; + } + else + x += text.length(); +} + +void OutputHotkeyString(int &x, int &y, const char *text, const char *hotkey, bool newline = false, int left_margin = 0, int8_t color = COLOR_WHITE) +{ + OutputString(10, x, y, hotkey); + string display(": "); + display.append(text); + OutputString(color, x, y, display, newline, left_margin); +} + + +static inline bool in_material_choice_stage() +{ + return Gui::build_selector_hotkey(Core::getTopViewscreen()) && + ui->main.mode == ui_sidebar_mode::Build && + ui_build_selector->stage == 2; +} + +static inline bool in_type_choice_stage() +{ + return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) && + ui->main.mode == ui_sidebar_mode::Build && + ui_build_selector && + ui_build_selector->building_type >= 0 && + ui_build_selector->stage == 1; +} + +static inline vector &get_curr_constr_prefs() +{ + if (preferred_materials.find(ui_build_selector->building_subtype) == preferred_materials.end()) + preferred_materials[ui_build_selector->building_subtype] = vector(); + + return preferred_materials[ui_build_selector->building_subtype]; +} + +static inline MaterialDescriptor &get_last_used_material() +{ + if (last_used_material.find(ui_build_selector->building_subtype) == last_used_material.end()) + last_used_material[ui_build_selector->building_subtype] = MaterialDescriptor(); + + return last_used_material[ui_build_selector->building_subtype]; +} + +static void set_last_used_material(MaterialDescriptor &matetial) +{ + last_used_material[ui_build_selector->building_subtype] = matetial; +} + +static MaterialDescriptor &get_last_moved_material() +{ + if (last_moved_material.find(ui_build_selector->building_subtype) == last_moved_material.end()) + last_moved_material[ui_build_selector->building_subtype] = MaterialDescriptor(); + + return last_moved_material[ui_build_selector->building_subtype]; +} + +static void set_last_moved_material(MaterialDescriptor &matetial) +{ + last_moved_material[ui_build_selector->building_subtype] = matetial; +} + +static MaterialDescriptor get_material_in_list(size_t i) +{ + MaterialDescriptor result; + result.valid = false; + + if (VIRTUAL_CAST_VAR(gen, df::build_req_choice_genst, ui_build_selector->choices[i])) + { + result.item_type = gen->item_type; + result.item_subtype = gen->item_subtype; + result.type = gen->mat_type; + result.index = gen->mat_index; + result.valid = true; + } + else if (VIRTUAL_CAST_VAR(spec, df::build_req_choice_specst, ui_build_selector->choices[i])) + { + result.item_type = gen->item_type; + result.item_subtype = gen->item_subtype; + result.type = spec->candidate->getActualMaterial(); + result.index = spec->candidate->getActualMaterialIndex(); + result.valid = true; + } + + return result; +} + + +static bool is_material_in_autoselect(size_t &i, MaterialDescriptor &material) +{ + for (i = 0; i < get_curr_constr_prefs().size(); i++) + { + if (get_curr_constr_prefs()[i].matches(material)) + return true; + } + + return false; +} + +static bool is_material_in_list(size_t &i, MaterialDescriptor &material) +{ + const size_t size = ui_build_selector->choices.size(); //Just because material list could be very big + for (i = 0; i < size; i++) + { + if (get_material_in_list(i).matches(material)) + return true; + } + + return false; +} + +static bool move_material_to_top(MaterialDescriptor &material) +{ + size_t i; + if (is_material_in_list(i, material)) + { + auto sel_item = ui_build_selector->choices[i]; + ui_build_selector->choices.erase(ui_build_selector->choices.begin() + i); + ui_build_selector->choices.insert(ui_build_selector->choices.begin(), sel_item); + + ui_build_selector->sel_index = 0; + set_last_moved_material(material); + return true; + } + + set_last_moved_material(MaterialDescriptor()); + return false; +} + +static bool choose_materials() +{ + size_t size = ui_build_selector->choices.size(); + for (size_t i = 0; i < size; i++) + { + MaterialDescriptor material = get_material_in_list(i); + size_t j; + if (is_material_in_autoselect(j, material)) + { + ui_build_selector->sel_index = i; + std::set< df::interface_key > keys; + keys.insert(df::interface_key::SELECT_ALL); + Core::getTopViewscreen()->feed(&keys); + if (!in_material_choice_stage()) + return true; + } + } + + return false; +} + +static bool check_autoselect(MaterialDescriptor &material, bool toggle) +{ + size_t idx; + if (is_material_in_autoselect(idx, material)) + { + if (toggle) + vector_erase_at(get_curr_constr_prefs(), idx); + + return true; + } + else + { + if (toggle) + get_curr_constr_prefs().push_back(material); + + return false; + } +} + +struct jobutils_hook : public df::viewscreen_dwarfmodest +{ + typedef df::viewscreen_dwarfmodest interpose_base; + + DEFINE_VMETHOD_INTERPOSE(void, feed, (set *input)) + { + if (in_material_choice_stage()) + { + MaterialDescriptor material = get_material_in_list(ui_build_selector->sel_index); + if (material.valid) + { + if (input->count(interface_key::SELECT) || input->count(interface_key::SEC_SELECT)) + { + if (get_last_moved_material().matches(material)) + last_used_moved = false; + + set_last_used_material(material); + } + else if (input->count(interface_key::CUSTOM_A)) + { + check_autoselect(material, true); + input->clear(); + } + } + } + else if (in_type_choice_stage()) + { + if (input->count(interface_key::CUSTOM_A)) + { + auto_choose_materials = !auto_choose_materials; + } + else if (input->count(interface_key::CUSTOM_T)) + { + revert_to_last_used_type = !revert_to_last_used_type; + } + } + + construction_type last_used_constr_subtype = (in_material_choice_stage()) ? ui_build_selector->building_subtype : -1; + INTERPOSE_NEXT(feed)(input); + + if (revert_to_last_used_type && last_used_constr_subtype >= 0 && !in_material_choice_stage()) + { + input->clear(); + std::set< df::interface_key > keys; + keys.insert(hotkeys[last_used_constr_subtype]); + Core::getTopViewscreen()->feed(&keys); + } + } + + DEFINE_VMETHOD_INTERPOSE(void, render, ()) + { + if (in_material_choice_stage()) + { + if (!last_used_moved) + { + if (auto_choose_materials && get_curr_constr_prefs().size() > 0) + { + last_used_moved = true; + if (choose_materials()) + { + return; + } + } + else if (ui_build_selector->is_grouped) + { + last_used_moved = true; + move_material_to_top(get_last_used_material()); + } + } + else if (!ui_build_selector->is_grouped) + { + last_used_moved = false; + } + } + else + { + last_used_moved = false; + } + + INTERPOSE_NEXT(render)(); + + if (in_material_choice_stage()) + { + MaterialDescriptor material = get_material_in_list(ui_build_selector->sel_index); + if (material.valid) + { + int left_margin = gps->dimx - 30; + int x = left_margin; + int y = 25; + + string toggle_string = "Enable"; + string title = "Disabled"; + if (check_autoselect(material, false)) + { + toggle_string = "Disable"; + title = "Enabled"; + } + + OutputString(COLOR_BROWN, x, y, "DFHack Autoselect: " + title, true, left_margin); + OutputHotkeyString(x, y, toggle_string.c_str(), "a", true, left_margin); + } + } + else if (in_type_choice_stage() && ui_build_selector->building_subtype != 7) + { + int left_margin = gps->dimx - 30; + int x = left_margin; + int y = 25; + + string autoselect_toggle_string = (auto_choose_materials) ? "Disable Auto Mat-select" : "Enable Auto Mat-select"; + string revert_toggle_string = (revert_to_last_used_type) ? "Disable Auto Type-select" : "Enable Auto Type-select"; + + OutputString(COLOR_BROWN, x, y, "DFHack Options", true, left_margin); + OutputHotkeyString(x, y, autoselect_toggle_string.c_str(), "a", true, left_margin); + OutputHotkeyString(x, y, revert_toggle_string.c_str(), "t", true, left_margin); + } + } +}; + +color_ostream_proxy console_out(Core::getInstance().getConsole()); + + +IMPLEMENT_VMETHOD_INTERPOSE(jobutils_hook, feed); +IMPLEMENT_VMETHOD_INTERPOSE(jobutils_hook, render); + +DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) +{ + if (!gps || !INTERPOSE_HOOK(jobutils_hook, feed).apply() || !INTERPOSE_HOOK(jobutils_hook, render).apply()) + out.printerr("Could not insert jobutils hooks!\n"); + + hotkeys[1] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_WALL; + hotkeys[2] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_FLOOR; + hotkeys[6] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_RAMP; + hotkeys[3] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_STAIR_UP; + hotkeys[4] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_STAIR_DOWN; + hotkeys[5] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_STAIR_UPDOWN; + hotkeys[0] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_FORTIFICATION; + hotkeys[7] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_TRACK; + hotkeys[5] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_TRACK_STOP; + + commands.push_back(PluginCommand( + "automaterial", "Makes construction easier by auto selecting materials", + automaterial_cmd, false, /* true means that the command can't be used from non-interactive user interface */ + // Extended help string. Used by CR_WRONG_USAGE and the help command: + " Makes construction easier by auto selecting materials.\n" + )); + return CR_OK; +} + + +/* +DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) +{ + switch (event) { + case SC_GAME_LOADED: + // initialize from the world just loaded + break; + case SC_GAME_UNLOADED: + // cleanup + break; + default: + break; + } + return CR_OK; +} +*/ + +/* +DFhackCExport command_result plugin_onupdate ( color_ostream &out ) +{ + return CR_OK; +} +*/ From ff40ef6d59e25b50985ebe3dddb169062cfe21e9 Mon Sep 17 00:00:00 2001 From: Quietust Date: Tue, 20 Nov 2012 08:46:24 -0600 Subject: [PATCH 02/35] Run screenshots through pngout, shrinking them by about 50% --- images/assign-rack.png | Bin 8044 -> 3892 bytes images/guide-path.png | Bin 8224 -> 4871 bytes images/liquids.png | Bin 6473 -> 3676 bytes images/manipulator.png | Bin 12399 -> 7373 bytes images/mechanisms.png | Bin 6943 -> 3741 bytes images/power-meter.png | Bin 7523 -> 4435 bytes images/rename-bld.png | Bin 11008 -> 6667 bytes images/rename-prof.png | Bin 10174 -> 6190 bytes images/room-list.png | Bin 8562 -> 4839 bytes images/search.png | Bin 7283 -> 4509 bytes images/siege-engine.png | Bin 8227 -> 4023 bytes images/workflow-new1.png | Bin 9378 -> 5662 bytes images/workflow-new2.png | Bin 11397 -> 6862 bytes images/workflow.png | Bin 8206 -> 4931 bytes images/workshop-job-item.png | Bin 8297 -> 4806 bytes images/workshop-job-material.png | Bin 9278 -> 5553 bytes images/workshop-job.png | Bin 11076 -> 6461 bytes 17 files changed, 0 insertions(+), 0 deletions(-) diff --git a/images/assign-rack.png b/images/assign-rack.png index c0acb580230f15bdb265ace73f1f01d031dc8472..4ebcbf590e2e14ef74fa5c9896fa51205949686a 100644 GIT binary patch literal 3892 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 D*8)9i diff --git a/images/guide-path.png b/images/guide-path.png index 0a3e967a37d5acece7ba2d5da9cf09fba52f8fff..afb6511faa448172ff4bb9214c82fbdf00a68066 100644 GIT binary patch literal 4871 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 Q{YMLMuyvtSSRYLIKh*ANA^-pY literal 8224 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�OtcCf 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 diff --git a/images/liquids.png b/images/liquids.png index f2058695d328b2c4a878bf08b3366e29031d52bd..da70a058b0b4c5b31c71d71f4f9c505681a858ab 100644 GIT binary patch literal 3676 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 Mn`72hmcDWS0)ACjEdT%j literal 6473 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 literal 12399 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 diff --git a/images/power-meter.png b/images/power-meter.png index 4d84f3761bf1f003130b8dde92534b12bfc2cfe6..b1a4b6229d6dfa72535d52566b81342007edc615 100644 GIT binary patch literal 4435 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 GPy8Q(h@s{H literal 7523 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 UYU)AonN;9_jl*x{`{3CB2Ty0(9smFU diff --git a/images/rename-bld.png b/images/rename-bld.png index e1fa8ef31592ca83469e7a675f93b306ef5507f0..0028a87a5b9e68ac28e1b4d4bfdf2fe666ea6583 100644 GIT binary patch literal 6667 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 V15>IpGj=}?urRkat1|V7`ailS$Atg@ literal 11008 zcmY*kv?T@neZT}RQf@(z>@#D-qgGe@rc!N_ zf97mGR@!M7^_Z$XA38Su+Kh+&C~wT@#^2MnaO6??WdW(e$2pUMyO_D99O=K)I~H!Y z-9A6&UL+dhV69+#o_?*WO3(b;!;PvxyCnNpL-ndG<>Q3VfqiRJ`y|KL!(%=U$=HYH zHnGRQP%EkH*ucT2E21;0T=bxCKTffmVc;Ag^oIQH(i!2x)G25A;vJ~CbRon;Z8Ek# z5vNG|(LI`8+exTv*J(-T+1Q1pSS{BGyl#JRvLpRgK&I~jO?#;Em}dIMn6XXS>Ogiu zPZ$Os6X2mns8eQ$Y;d}f4>5?$p5Fw^(v{;MaAw$H#B9IgpZ-|+3fes(*`9b?T&ds-gfJ}C3y7?WcA@|m^J>PfYB9JM)J zrXQ2f4PzH|A3hL4^YEDqYgm*6OHEk_-?Kz(I$=?}+den1$EM)nsi$RD5D$}+xbGgG z@_e~wSAv*ufZ8%5kA+PMwEa8&$RcXXpIY6jU)qMoL6h}~d$U(C`6n&9w6X9m$i!n# zDKWZ69zIEbnQ-z|*~FC>hKI`VpT)^8>P{}c+KX5GmN3*{#TiI~b|l(tf{^j{^7!w{ zE6OfjAz1h;Wa2B=un49`c{4pr2iZsXkqjYuIQX7}D}E?AdfkU;MM_dxbdadY86Gedu0?#=kLbvMTTOB9a~avA912 zutVMLs*RS$U?TF>Cm3Srn71^M)zC^yrXo39fXt3`?VQA2Ti>`3jPt?#4wGIe|Edr3 zzfVq!$@gpqmc;1oI-0&8VbD2nJZ##-NV@-S|Yg%VZPco0djrUWSelY(e5rI&M3(d^xNzsTQbWys)dcI0yv zM9_yA5oDqBX2UNfzm+FyX(C(%;%F%QmG91&$-5qu(Y$K~5@_;CcGh|%A+LROQNJzJ zTZIct>}cgZ4*|UKjluzsAfiDoLDbx&gL+4rq2zlR}GRh{UMq4kQm(zK*$P4)qQhh@9#0m&0`AKA8_sZ!^RCR>Nh zSckbT7xaY8{JdRCK)Bv*EN|3=KXz6roG*KvbugJj>5=VN_zPFD_PB!ta;YA|WnSf@ zvnmgdq+n=_m1KE1{WSAJHTNN39nHN{Q_kfINH57fcxuO)gw}-MJ*`dLe%c4(DOsn> zo@X?qO}}Xm68`*^lZRdt7S7H?_cNtIj2i^nkv-J*iUE#o>&N>pIp`uuzdqb04=a%~ z7)gWS@vBh;nouYT(cWRA|2o{2K|BlH}-2pLlCDR$t*+*a1-o8MtzMhTKNeESELJs3F%LeYO+F zu#V<}PrXYgGo#BzLwZRLPNrr&@U@RqCSOKWbktWGpPZdB5H_*&Hjh=UvI=J$EVuSD z(YLWsdCwz3yGRyFQz4grjE`5!(x?xWq;K_WDMm7u*~h%K=T*oUBII@MJA^{S63n@3 zIHcuow&|l?)Yx$S=pp%5BE7%!G0P71Pb7*<93T7EJ2)@={ynBq#KH`I;2Pchm=FFS zwQ#&>K_{@6Y_y?XE4AHjD_!5+p1v}a*LqU|4@(LzL>1Du)r~ZU;2y%1+Le1)+LeHj zg%^?pNpg7GWir#H6pOk>8@j?x1Db-zyJO` zK2OMqD;y|Q**zk{iWD5^P|iJ;YXa?eg+1Ew@d5kQw3Yp~=$J#w7eOr86cL8O|4pCb zW2e0jMa_zl;bo)Syo1;1iFrGG#Wtm?J$H+Jv{ElC=`8B{Q^i9$S>(g^q~#FKFwipGdldJ9B9 zU{74ZvYvtnxIZB;_kc~S4b_Wing3nVd|sKc76LY`XZ3fZ^xAT+mhQ}!mk_LtBNX8= zGz;^Vkkb>2brafW7RSD+U?#WW(}cY=U(annU->*)62#wKY(V&@*l8~~y_t8Kzg5k7 zSO@3cpi2=3+sQ7)z1PoSk^0AwIapP#@${OR-^RI^ZVvKru-{PRt>D~^(Y(hl(E<`Q zb|{~4N0|+!C~mKk@veJ!(?kJ9wUey&m?niw6|{@u>3w`?1dQgn7W`V7{{4J;^-2u; z(aX*^khP5#M*z+9?k0wy2!_dI9A(rg_UkQ$BNIt2sHO` zdDyz~qz0ndtj@8sD}~H%!@5&pHm$Ae3|6TogLH|9Z8;3rJf0`Q;)TjXI?~83TZnP3 zac>cx$qe=5Jlw%)a+S4y+gxtCELDWA3{l(SY{{8DQmQ*cn!IjCTGt_KC-YjmZ;GC2 zCMR@*)nm~bNNz@qh(Rm+;-!z@6HZK6Sviuw)fofx0N(;2;6(5i>fiAFf6r{a%PEpS zJ)|rtawdH3#GH>DS;9P4oo{q=o^A-RUb@5IQhXzDjP8XZtL6r2I z6Ef7OY{W3#bY7T9x9qx-VI9BDjtb}t$<k}kW)kk_ z7NjGS%Jn*Hy&t!$CLDFQdN|@8%Y-K5^DBiXkI+v>p~rryPlU)&GpvOt>FaCPe1GD3 z7`yV)&ioXfoZcAl2~6+J%=HgG=BPjp>53OUanXl0J+x)t#6C)z43RkQ^-=12{{7Q$w&%WsOm3!J ztFwUTJn%L@leTxI+`$pvP|nj=7OJu6B|kTeS>B8*f!487K6Xj{4SW9U=p}a8FK0G? zpPG|Lm6){uN^jxaz#$(~Nwsm+#iiRdAsBidj&%8^00^(OSYD7*8*$X$$jlOi8R++7 ztHDI?!r(FDJ{(^W66`Jn5+Dx`f#)Cy1)h^{1_+MKq-btGk#|Np%f-@&=6l)IdXMc0 zUxhX~P!*})_9ZIAh*!<-b)_?=@tECUsNsevFd*qA5obYl4C$vm#QuY0}#vq5A6E{S= z;-24&^}DKoysO>wa(ZL&+ofrk;-5BqFMB(=lmp?rYXraZz5M;lMll{9S=F+CVkeTZdu4ovAucLbPz%Nsv_C68wiCh%;xS8JvCT z%0c_V$wOf6drIBGfromte==Ey;K+f5mk0^sx;be6Vgu5gw8@o?)!Psl*CPcWbZ985 zdJ_v9@}3oE1zq#$!3-nyGNis`MlS1VygaODUnlkG+3+W}#imQzwNfb}=+MiIUd&`l zY>fvd{}Vj-!Vv_2EUN4p5$Ys3QE*liI|*_xUzE|+jhZ7WTSpQ3Dv*l*#=nsdda_=L zJy*m+?2;NEXO#9=jdr20}Ur78q&@D=UDD8H|s<<(%Us8J{aES$PELTOO&u z+%`mY{Nd&K;O$7C;;6-a>T+e-gnQk0ZIb*h?eDH zwT+XnF3Qf`=EHw)o3cX-uPHNHX+`+_hllvtXzPNw1clkJ+-(v{HW~Srb{zDVrqA@8 z#7bgH+x(^Ko@RRxx#4vwq3H5`ugXaiZYwawd?rbO8}>5dWkVTQ+FC5YSski*OBhFZRVo7H{9MMIr@7q0)bHNdt1^KP*|2xcV zh-n(*r0ogf!qE28qt0#DJ%_q1c}O|;$v$~J?-BZ_8qDrSpHqBl^D**P*Q%^}eVnO7 zLD%K;3ch9BxhtY-YHEU8F(3yw+M^)r%ddjSrA%hFV2Qzj{P%@(*oYYqMC0u>5Sb}^ z<4-*z0WDDv@Q4dUI1HzXbP04}Fw~AmT@xv_ zYXP~v(ZnXLtoe<)B2zWiGuA>kr@q4Dxi>Go$6)xZfB1zhcZJ6=v^0ClGpMn*C759f z?BQCCd@I{La)fokd{VOErA!r&Ue89k<(CO~Q0b#_~w6b%dT#EbuIe!s_fb%sZbBsT=94ec_3CJpJLA#vIP zLQjJKSUhdB4yygQg7j{=pD2nBNTlB*58s`9{L#3XVoM>3Cxt$ z!0@{0g%TlhsW3A2?tsF2z7u>C{t>en1bJ39?s1F)p4Z$FuY zUXUY~sv}2jc$7$9vZ6-77D&VzISs3pOznNwW$ANl)XNGz+m7x0g;Xo!sCUxdwE99M zRU|gbD913WrMnQ$>uAu)yLs0Lj}+kH$1>NM7UWE&KQ1N3(#m_tr4Ygw18%XL8whE% zPwMT~D_r(VojSS6XRMRHUmHN;lHQM#yOQ&UgmKmsN~L-~)@SNhOcR*Su{!y5O3fv| z&{3U?fNZ4`IbsxSLCntPWrzVXtbnrsT|Z~1%~2bOL5yF$Z}4pTiL`6Z@+!Vrv2F|4 zx|2z&+?Kw{MT;S^tv8#+3<_?_zE>7N7x$Ds5Y;`GQ%_p2(TQ#9v2B_7StKNKe*Xz& zweXamirwY&r4T7Qvqgw=iaBfXL3#e8LviitopBA`I~xtsmw$bL(?mT48iF**;W{Zp z8A&nobqlp)5Zv+wqPakgTRBZR;ab>r{f}3fu&2S9q)QlDk=h(Yu%{eIc`&EIUww~J z+y_8xesFFFmNYKW+mRz3(bqG)&E;q0td3PWVXbs-2iD8VMX@cfr(#eAY38LCA>sFl!&+JsCt9NLjBx4R7{-u@dol1NK$2OkkkT-@$I-*$ zwW}BUpXW2r*S>OxR5fF~f{gNW3p6KhZKaE{!~VzCI(!vH7bTdvOWp|yb8i)PTOHqD zHPP}ccwSI?shXVWne;6{2n&~qV^A{`$p~BmN=hRTDLPbrDE|(-Nv1o!&*QhNEZEEi zT93G!1si&L_c;+^9=a$SEU#&!dKrQXLn*A1MpAW(rmu4p z?2y|aN+c8=C~tj{t$f(JOZ46<7RG0!k%jzHw0^T4ik8MBQ~a=gE1!34o-IIe`tDrx zx%A`1Y{Va2=Pm2Du>tx8I6pq)A=yahXr`c7!PPK`Aw#zQRXkW=0iqSaPXyW^dAN0c zmUZVWd0)A?k`Tz^0{ReXD_EZZ_^#o;9S|ja5Y6jBy!LN4>HFZd^7prIW@Awv*xi?@ z_X7jQ0hlE~4qwd9Z;4??n8&ycI+{T-9gdfD6$1DRtsZCjf2Mi(i+0XbwIWl-Oz<#Q z{jv;aGd`~BVDH#GMAZ{+Ny&boxZ^uNy)USqA21+&*ZeDuG?>24FFf9rCO|Lw#ymew zte??~7h#$a;jX2Y2ddcOk>i9zyr0f z0ebW(?s;Aifh>v3!56>QnXO!jTsT~>tF6Y1p69ppzZ`a>^!m}n1&95`y^W!R`AVbR z&7DgVR~_uN?~u)|^2>S!WOkKbUG6@DezobSQanE6Fttl*JE-O^81h<)M}F5-Vu|4% z2aTl+(rnzb!LkV{&&gf=?dt&rhr2jn^`Fgd2KBXY=INnn%5=KgbpQwqN`dkY?(?Fb{Qc}Am5J7B3;bbBfrQeRx`SRY)mtGv0<|JA1Sp^~vQw~=v?k8LuPkH%%GQ_sLz#%I2i>Ieoi{hQ7fmi81t~Lvef=aWV zTqJh|Az(tyFNYe*37?fAf}6sgfTpLarTn0{XB?!9wi$ym-(9cnTCK#3T3Q%HOT|n! zWjO;kRLcMF*}@GI2`K-dMt%`~xbFA!Yb$@&eY5mgwh7q1+V7noq-g5*X4#?WTmi`s ztf&1kCXq&C9%BFZ$~I270eeb<*RJfR8xx&vDZ`zQf8{4%iPP2xjt;7HE_DCQc-pn) zfil-k-)EJ+bDR^N1e%r=%i&mquqdGviJhyywrp19_Iq^S8Ua;ICjQ`n4!OJW^VEY4CB) zbv-xWuq?z++d|%FsQK4P1~Q3OUb@+O+ZJFafT$soIbAmCC5xbuWJACuI(M^esZk=q z{F0TY6vAa6n7*NS_Rk07WK(*!mAU|+bXe#+kb{^pn#e7Owl`=w;H@vvobuYe_kUZc z`2b`I7;nHtGA90qxI16QqINe)@Kj8GkK3tmAF_3+P_O!*1xN;8dN?1p2>#@qlj8tg3q?o1K%w#Zg?p8`n@~8DM>91s!^Ysi>AwdCJ3+u z0z?CCimaHM^$qf(JAVXH`?qEmN%()aX$PTEp=Ars(w&h&-T$`!zeAM(IROWkQ8lOb zUMa&1{*M4T=nbEOt6)m9sFKkC)=~vIoSkJY{~kYyp*f|?uk~=LIsK1XwRq5>)0(A( z$NIzD{W&((_D>r``VTP>62n{Xwx@iF)_n1Y;CMc1I3;1pg}p&srgq6^W>4nOcOr8)coMv5 zSBW=8OjUM>7YWBPyki1?Rp~`F@qs@ma^PMhBH4E|dmAzw=7}UTi<3-5;;xmfn#0I$H~4 zGFGi351W^|-T+}3i@pUW=jF>oN^l+_c3FCw^8my68w1P;hs1uBA};n0@sqA5l`mBH z)ddOR;ac&%QDU3baWQ-2w&=D8DrBK8uu4al&Q~o4rwJFFZHrF(imB-B0TP_c|1829 zGK!4*pI;E8z3Bcuf+1#D>C4(vKw!nwm9dPDmyTW{TSTY0VE2fJSddbHC-QzLyWqgu zgk}C!;_Qe#4i3)jo4s{RC3d@8j@Sp*3R!&_e+)tH^qq%sJECW0Mmx@=&d;x|t$l91 zWc;7<^t4Cp;RGM~_LQ!q(dE0IZjhWfs#Aow_a{}_1Xj&npv#sCk-L1J4*`bT@34Fq zKb#&N>$4{QN^8Foqo=R7Ea<#F->;)?Mr^O+o`6OHB!~10?~G<46%KVK==hFm>JTy> z%zNZY&KC!d2Nw2<=bzd-L$`MafgAifg5;d<4ycT0+j}Z6rom zxMe9m*3uzJHgFJwI}Fdq=j~Jw0j#;`?+XJ~&ssNjD7+PWVmV08eDTXNuOKx+*Zn}k zhQ*6@VfS~6WS1fpQ=#b7yNiJqt)Jmfs=1td=Op;_B7wMk=p71Wize0h7MwLyE69-E z>T>H2#0adtQpAa-+>eiYitU%6+u=aIH>x{Ag)7!C+c^0gmqoGQtvN31HmWf zjUNe`^pYTwIx@Z_fT8J@g zx#-+Vkw0#il38YfCPu|;lS@_40bVO|KZf{TIau?2XZIf!d2TqEKqKil;AoBI6~AsO zwlDVdO!FXW{YfcB_;jdIEc$^zDk|>2y|2?ei&%!Y!4PA2zIj`;??s!jZ=pxSuK>Dd zADfl>vr!kUL1vzfwU<@tb}gBTQY$mn?t`RXULp`x5cNJV-+56?l^any0};*q?mHLwqw}%8--VH#k zP-PCpikHmZ)vg0~AZk{x?*0J_(x69kyRlL7Hx374&jaNjfq zg(YnVb`4H6iphL?n}ff(6<%RI?7Fyd*1|5tqccwNZKam9kKwSUq%&85^>Bh_ze5X# z-f*su`B62%z67L}$tI;9(P06=)5NDlC-n}1PD(S$p||JRUUV5Ka^iJKBWG+-R=!Dv z(W}q4Q@!?-lrHgvt9iM zec)>xua)F;S+5HNAoNlr-ob4(3_N z_x(jp>RA2wb}FGn=TKMor8h@9l6(EA7%+wb_(HSk22CYOAw=AXgjOq&)u{XsEfdoS zX_?>{Ir23O`QlD_ee<$so@|Kx{ABN2ohO*+ea9^wh5>G8g^tI48Go(~q{Qtg_U5Ez znI5^n6wonztH9#x(>P{z-jgDFBs zXg4=IL##jr=uNGMg)NS>qC1T^c;0OK$n8os_x$ED7El-H^DA|NmeRgN^YN%c@aXPG zEGkkM5WUYh8EQrs{-}T~5RM_mMVIixwTHE*#!mm}QG4IH_@DClJC(D0PWF`Hnp|oplW0v_G-XT5# zaUqKY$?T%znGq}@llCL^D);#UYMceL>MC#mF{llMb!l3esa2+-TYQ#3sTZ*AD8iSo zJ~ZH8#1Jzx+^vZE{+a*46HB)~UZ5n;!V+EB%JL^1nDPf1x5r5U zh7cmr_^BPN!zkk!fH#2{Bm%Lw{@g{0_;PNt5HCz=7(WF;3<^1Lc|dC6s(Tm%$&YIEk8}5drXg^Je2xExin6j}->y~XXj~~^PN6e*S(m4)JBs5W;ucXC zUM$?y3UbG(X;#kI1ZJRNm!ek@f)%!T{eV-HZs-4807P$n_ff$Hhy%=eAtWtT5O>!o zkq=HAck1M|ydFI~?iIWQWPFm12Ji6DbZZUq{|F8^r~xK?&%V7*K-k5Y$(6OfR7YB@ z=ucNVH@{#kKzFaa|J>AV)C9dm#_K)%)LG+jn8td(7Lhug;~ra_J{dH5 z{8}*fl%1(V3fX>ftGv0-)H{+ulfz`&tqGa<=P<>ZeuhIz)lfF(wW1RR3%76jrC&?h zSO}*bN?{OwcU=KWBj@M*ke!YS=I>$EZVn!sRwA) zSyY45gdemqS#@&OZz+|wj;zE}LcOCFNk66gYHa#JYmHSW+^=8D{i@+!qJk9Z@Jq;) zX;Q>_%Qp{g?1KIUX;$zCWdt<2;PSprLvM>3GvIsZ=ZU_VyDlpnsDNFBh%g-@Bs-WF zEkAm=+GI|fuN;x4!YpXvrSv|u+6CHqQ#a)7m6?`q3nc-U(QD0H(;i0YkL3wJF_)-l zo&6B;rF-_n)=is`cRir+iWk{~i1-oid7Oy7KB#@8EatJ=$>im-!fY}cI0WYjj!1g+uZ|QuRg^?jdPR1+X=iE-bkjDNFW8D;MDXU z2`51gEF;kQ*^q9e0hBBlyjA4{gD&tHr25EPFDzZf*Q;IrW@FpH@@G?Oo$#bj`b|m9cySy_=D`j zGVGhrKW?~?0MZ+WQ((x$=HqP06a**2kGu?iw|W${#%pmOvk4Yf&4ozZpzCHzFBe3c zwn8TF&zD(I<`Oeb2tp(q;3A;ujt41ae<@N=EF~h2AM`kG~6=u;v~Nb%}aFCA^r)|F z7or82ZV|0_dFXRklEmmFA0(G&3ek)(js9B*WFZ{vm3G@Y&~Jx8)Y{R`bdfaIgOJzL z`cSJU#Tj>nZ--z(wetOXE#&HVoYj(GRlWPKcqokAJ#L~0PH?bbc;ErVbanmvjUxQ< zQVz)+gTj3vy@j`NHO(3d@*<5dMukK+n`K&3Z&O)}xnzle$`@mB6b8eHl2Zkn=NkuI zG+-wz)csq!LRziTPe@g)AnBxyac1%tsCR?h;axVe_X;=xu`Llp=f=@yGp|{#-sj#@ z?3A11%Mm5G=|6$42mbQodU)Z%2!Yca^uCvstWz44Mc0TQ3$>6smej7^kyDrM@9$Y5 zuQD~0?g#9n=;ErDa diff --git a/images/rename-prof.png b/images/rename-prof.png index 789f6fe6f7dc51f52e5266609a8a7fa29a34db2d..5f2cfc4532a01158970addec96fe21f0eb258cfd 100644 GIT binary patch literal 6190 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%0AT_Q+pXHatBt?usj|yycTKUd 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 TN*6=zz%9Z#Jrmu+(=hUXW5MOX diff --git a/images/room-list.png b/images/room-list.png index 34c93591a4e56d50413c37c3244fa7729207cc99..5a60398f8db7575307fd19d91ac0b1a8795869aa 100644 GIT binary patch literal 4839 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 diff --git a/images/search.png b/images/search.png index f299622fc00fd581ee7ecc5b7e9539222a83366a..384c3c533214d92769818d9d357293208a11e507 100644 GIT binary patch literal 4509 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 O;ADFjyK372*8c#W3?};k literal 8227 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 bJ{(ys9rD0CvyB4&%#Sc9S{mmNC>Q?==!Awi diff --git a/images/workflow-new1.png b/images/workflow-new1.png index ccc0e5fccaad1cd0de27631c1c56b86a9c8e72e3..25b498bca23326f9e5ea05471dfcdb275f4e4734 100644 GIT binary patch literal 5662 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 X3+v6wDh=8C=tWR0Y|S5=xySw=1!(tQ literal 9378 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 Suo(kG7<01q(Mn^O`hNiGHTyCE diff --git a/images/workflow-new2.png b/images/workflow-new2.png index 94456331608f732d8164db160c9d01cbc818a84a..74a4922be1e7e337676bbd4e8b2c028267f7b1f7 100644 GIT binary patch literal 6862 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 Q`h($ literal 11397 zcmX|nc|6qL_y5QYV-2B*Fe1xP+1D(QkSv+;lIg55OLRd55+(qP{+^1`A zvTgg?>o$j+F3nB(a*~{RGdp4@2m8H7Bbwe_I>XwaO)clf+e~><;97OEQkb)`UKtlY zMz`#>7QY;%pZ>;(Jz(yZKElM#$+xa)leQ!1w5wOPx12W+1<5`TE~)>d3!tk^aa zPR35w=jLtJ_DFgRA42BDp>139TS9mnhSnRFWvcHYh7G8211r(C>11hm3>V%&2=DCh z`aVhVyJY;#IH4A4M z8`kUpvS79ek>dTqdi^Ii*Cbez)eDFS&lAr}7gWMdbvom+?ddo5*>{5}wO zaud`qNI*UhkDG{`tiYHAne|i!M>HMWBk`!R^NLojUOB!QDGzMCD`5y_f;QHA_0?z7eE9B@{zq~2 z$N_CCii7fY(`3)}&Cl{2wDj7AcA3H5*N=EmSYGYxh>@tv-ceb|c*3ru`INp8Pssrk zLi#my)1@g<>s7#>r*gyh>V`e>(Mq!_nPKmrI)%TQPTT7KYUwXd4{Z055R!LrwdCT! zr|ccj74s??aFJre6r@K0A4iRmPAZx{?vg%i*TP zNwIyelQ8}};n^XxDu+^-?;r0hRUqs)yr^|-^GPY5n3 z&)mTh&-UQ@=!7Bdu2g;M+GKe-X}#&R@3V{syi(>!{g*;>4ari9+r`1s7bC>7?|%%G zv-n64U^)^8ooR?+`S&%Bzl0ry93ZiiFrhH#JPKL)C9k!#`mo<&E*S@*1yRC%bZ&p} zV`kJ0UNOAb496{0D5QLJYcb{xbffD-yX&XJhgV#*zsfLO?v=4o2GDykT9q&9qO9YA--);4;V3p%jK4a6=HO;{hxw2H4fV*cYdlTWMz5|%!k*ZN^tt~ z;lDq*D^@R$DQLF!YsVBAZbWm5wBaBP{oieH?H}#PQ|GB|4?;V{ z>bt6HNoZ+;fA;~jv9IR*=CD75rcwB*JXmuvUxU4`(UkMO8d>84y;%L!4|q_mfXH)( z|J#%J;*XWD&X!C)Zqtp_7lGJ{T{~|(46c9sx%etUeeE!%b66Ofd^%Dg7=}tth1G zOa$+ufP$8?4kL;KAKG72de!V0!mn;%{{*%(nZIUNZ?W|_5u~W!bJI9ZJSy~QiFdtl zs`|05xO*@5?jTZZvs>oJ9EN@W1TPm8(DQyQik3Gd93DgHBlA_I>uP0uIi=LP|cnCjA3F-FN@F(1To96ed_RYk5;`OEV;NvSd zj`)=Rg_Fw zA~jqJN1^7KiA!GFxo`aJO|~dJjvr5!LY%o2 zj^#ytcnw)C7!af(5Z*)NQ&dorVq8xcSu4V zaX0?Wi2HAAyJwD%wa#>l*v=eXdnYitq$ADTSJs;)BY|hz8(Ox)?Vf@DZMEF#LVwWR zWJI$dq$!f$dVabSAQP3F51GmDbV?IUq@kT8>^^^Q+~pvv5?(Zmf35MSJtPWXGg!^k z8V?_(C1+?uvfjK(`tA@bascg-{Z<5`7QwX}$UmC;cX(dx+n13Dbww7|^;0;{F=g5Y z!L(M%R@W}3Z3d3&maNPG=qxlVm2kZladQ}zNEU6%8NrD>X?84f6(XQnTzDxSLX-&8 zirORH*G;!2x^0W+Uw!6s?6M92Q@lqu#^W z2Vr@CuCHt&Eq1ZdWbA{+7X5=+INQ@UNVc0*=Ij>_BU{(8Vktc?u`7SKL5DJJ>HIus`?u` zHy*<=GIkh65Ch&azqdy(#ReAJrtJ&~+29u9PH2|9yD#1iFzHEYkva6;wd$iVu-YJc zzL&L;TolVi=`jkwEc2+OV7hZE=B;MAc1_?P4FjhZ8{VkT;eWm<^UR< zgOd`&$nTYdS(Fp#VJ2FZPxU>%UO0EXSp}IJB8I|rw+`V$W?OphkIHkCy^e2A2h2`; zeLWe}&TWCa_vJtdwO5ZNyq(|s=Tz3teWxC23nHgX!00Q-Y_@iMLhZw!kZzDdg82X$ z2d1ca7;ic|S21|+l{=-syr#->_~KGUU!@XOOgEkH&Of3JJJmj{fs@q@GPhe`zYA47 zt_$ShmK+C0vFfYH3aeN?A0rDbYAqwp%%c3{Ax_{rY91fAOkT=?(-e=RUVijQi&%+* zwS?))0_EqkcxS2^ZLgH@fpJ?TA)T0{=wsVwAWlBKQFxgP#}`K9DrD;76aR&<$!7U2 zp1Dep$sfRo4=GpDZnFFpCxtyMT2=&rZK(@KA7iW8=Syn$^Yo6Ks<|>QsXLv`Lyu|Q zW%8bf*m#(c11Zn-Bs>c%i+$0?Zfr*3@qBB7)rNJJvUhvERcE)Q_+p;#s6d1hJ87&v zw_g-{O^2bS73U`2M>~l?r>qz}>h7OAA<&%3B{Jiy4@gg#Ae#2mG&h(k3iU}%MW4En z9(}6ldCuPGiLzwGaP6!Wb#5xk>N zN&mIw3AIR|&f@Y-G~*RPRu24@&&aG~y*QgpMUA7Rm@bNHAU62ILh4BT6q}E>?WdAQ zey5(&A~(jP>l@9;sDF7VLluggl>Co?zaZ82vFU6IbDlG{FfbsXG&G8?)~-MBePp3$ zLE+hphj~~!*dB?J<{Tm#fEVKT8dVRA{KfySS@!HIt(kt4HzSy1v?!?KdOp3Sm(Jc8 zGjZ`hcy(psHRask{GY`J%&6zs412XWo$V`{ExXF-t6Q22#py`d^nlHOID$m=6suy4 zQ&e7q+Je+|YTD@*-D!!Ldv$<_rtd7@@N8PG)t;ICDI#`Oec!INeCgY5rmdx?HsP>l zns}~Z+T`j+OReM7p+P(9)oH5#1iCTXn}lN0YG_gzHm*n@gI$>Y?}t zra56EBr)#tqG~{e45;N#WE?2cYAtz*5`lJ7 z#_?knXQJA_LubLZdjHQ%@~XR)Rg({MUy)e-+V$LG39&M+9P0`Ri!22~-B;r;&oW3! z@e^t-dws{cO{h`dArJG1Sh8!jc`dvc-@?pG85v$P)+`bou(_Fz?fZvR7UR^w)YmAc zt7D{~D&_1=QHmt&)@D3n=ERE}RWPH1A6>mK48)3u`BlP_i%p`?Q6A=LUc5%I~D(#!4ocWkPsJj3j+WLiIuBKHufTtDDNVd!Dk)#IBZkM;L}*L1JQjNouNZL*KWROUE%*qmlQjAJ>s{~ zP1_TArHg`Xvv$lM>~4V73I%1bfs+bgO(hFZdcU zOX`dUw|IA3Fv3=to4dPc9_8 zKCze_xSWNUkLw}b2d@%r?J8F_#;iwxoMJ!DkC3X+t?7uIVf-bkQY$QY8OM4EKd2u? z5{ok%x?1M~kf1gGfz;INsJm@!7HZa90Pknf(yBXfLn5}b*-3Dl+tH9p+J+_NA*Hjr zR2X6?XnB%`B`$u!K{sB(eD|CqZc@WHn_}`ON90U70o;2Thf4^7NU! zv28sR>`*o)LVp|JdlfvW;Z*;0q(A?d1#Y3*Mgap~qG4Z()-N%M3Vr!5PRW!Ny$th~aI2NO}s zkICU8warxz0Jg2a^U{Q@1b61h{p%?X)FV+rzx%U5-a(NtHB7v1Kg;sK+`vLONx7-b z-ZQBNY>q?wdJ2mIxBgcSS2L4eeF%pMUW2C&KX+|yscph!F4x_HSWw@tv;Vnkyl6oq zI_;AZhf{7)#7ViHuALci^(remI@1R6KIO+HfMnUV@Q0(~@3N=Fbhoc7a#O??Jv**r zFq!Ehnhy+#ugwtLSq8940WCO>q`lLtd}yb5&DC`M#v?dLXo7f{+!7t1qI#AJe^d_@ z)}Fe5gaiNYyq`KK6uLfPuL8IU00Y*^CR3ZO&K zHhAJFqw%F5##;+kUi-I0+m}&Q`l@{0aks>ZYaY3PNIggONp>o^RW_EWzSrsIDM z30bvURLGNhcN>@A)rdlWBBYc=3mHGD4G^hOrWFr18MV$*^RxOiq-S=$U-zRUr-QGP zMetH@pS#%uwtWa$X?uEj9ttRXx|1+TK2vAec?Rm->u2h-;WXQbU|+=FdUuv;Utujk zU$1ob%FRH%j~~_=?juob-&5m1lXJQ&2*azR9D8Og1mo+67Ce8wRv}@WUVmHb;g ziAZ3(-KbiXR#@DI#QV79i&WibxJ0c@I-TkC0KUuJ$^4v+$sylHlQ#YG4jpl^Qeb)L zLOs2D`Yur+ZYAWk-QiEU5E1xbkQRSS~@XIh;5mu#nF?mA=7uJM3+n29uX z7=QL~k#B82@i|R5Wnd;hzr}-t5@Nz8xhNI8#00MKYa|{K*A`N;ZT{WSNAE|-D|XA# za*h{g1B?^{A>M|i5TiItV($i@o25T{=i~b;jW#h8-|l_Cx-amkyxfA__&z`J zVaPb!%3Qh3N$1O0-Zn94l54#8N$}lngQru0cFOvopdDm5+NM7H21Q%nR}^rwtX!r1004jCIMh2^Fcxq5elopJ^Hf;Uy&xch zPmu^UH|yZk1huS^+4TT%^t>6;{q7J*p7ZNIBgJ|tEbMnTfjU}Q4J%eOPo%$awe&#I zFz*UUY(fc?&Cg+`MNuGvnXe&3zWEu}7>^__MLj0WbeCKWo`D66_Z!jkvIg~x>4lbLOJapJVy zP(mNWF3?=NFZ=>6n8Lx${Kzj9W|QXhmZW910xL%=fJ0|7##zxf>KZMWiM}lOjx9HP zsk2>lC^QQk3O8>qtBhm4C>{lxHf9k2?e`a><^y*R5hF|U;zaKE$Tacv%0*|&YzzElj z!dLvit5I8RI%K>~#n(J+%clP_TQIE}j~o~P1YsJNI9)yXi%;l^An<1z*YgE!EiL7> z6CqB`UWd6Hi|p5jOLUFHmETnVNzSIHb_)JGYgl$Rl2{lGM4H~`dat=DQ>Nc!$Vdwd z@gYrCrUo#y;vprFU{J{1PwsIJL{6C~8yLQcaLI$Zln#Cj_j>aJKS~G6){B#pF4ZtUaCSEfq7YpwD9WN?RWPb)e$P{9d8nJuS*_|J8O!&I4&MLyOkTv~#BIkk zT{O$@h<0n7ZBfbYrOA{$8<%Wz6tF8h7v41Tr#7;3Z*hlaOq!<1fec+Q*V*qsX^?@6 z+2h8lfjmv8z)Q)E4o%arCA1f%tnhuON&P9?9bsT)xuy>74(Q#}c~=f@4;7C&{MpcZ zhLnKUPOa}Tg2@;3l}uGg>%3&$YcIB6-xXQ1t}A(V;J>jNNx9FwZX8n}IR~dLH@z-8 z2{_5AvavgjS5DF5jgGW_%^a6;mBT-Xq2SJkv9@`4E9Jo#fI5^;KWXb3{o3(=57}O% zMm1#|y=2Ers}QMKuw)Z|nHUgnw5hvd_4A#p$ynzmE?T_|LgphYu{SC(Ko{8Eoq)?Y zkv^^(|lsVI*IM^CCf3AudeJmFn|R!3@xy!DUpvh2!XP^5LZ0 z$7mEJB=W|(cn_ABKIXuOD|~pskSs}MZjpdOn1ja+KWYIeltQ`}VP#}!`7tmHsP}2D zD?w7nrZQ&}Z|!7u%*l_SJ3FZKVz6@SCvXAnb`Pl|E(hIg^qL+B$*kfP4~Cb$)Vca} z-+}H6+JozuGdrt zw8t?dp5@V0ZvR;8bqVjPmh&1rGE0`Vz@6EG@0& zgH<*LHyiA5$4QuIXR7D0XHsT-ZWrY-U>a0~B|_WrX0;V5UXu+Q4TqSeuW4>wr#&>M z$_MkJvFC6sM0Yz}qVdCuw$wkbC;SfcQ2Hx0L$^lw;;M`0_ zaogtS9WNY|rg6y^i3-jV{&e3vfZ|OOv&qR0lI9g!2QAU#plCUDRtWeOOU^*#BogJq zCI_=mgb`{ciN=ak%E@qp*T@atmUlx+V!EAIRR9_0${d+2(=gT?JW1>GVv=ezNIX_J z&-V_leT6zg6f;KVp~?)B+DpBZ6~V&)T8e0ohU}c>%0*i#Zn|hj@tX5ViI(dM#dCbb zTa_QSv#V@w6CVDmjIqizH{T&HOvnz$2bAjo=^X4stXe_on%m)1#ddTh?BHwB*W+Xf&c&2M$(F#Iq)QQ6vsU9Z_nXbW|DpvU8u{2ZimI4Wg5vQ3OPLqiG(>p8Wb{J z@#upPTp#j{q?iPnnLxK*>k_5q`>rai!8N0$(EVVqB8TH(5PE8%2wO%fCvBhY+lGG; ztzwy8soURM4&d!~pf%(|gV55}4=)nto(9b9vReSupCIuhBi)}|9U`B8=s0DFIb=17?_k^`zw9T=sCeVB&^_oz< z(|UhC=D^dcUt!3Ag&4T@o@PQIjfwUl+@vz61Q8m-fM()jUP^m7D>5WJbMGYn>rkuU z&j~g+57Vs{N!jm*j?=zYsaF{jEesVfX3m=wt+I7io!pu-Q7P~djaxc`o-ZFu^5z7E zMmWjuZn{^#K-{N0<(@|~qqF5FTn1GiezA>vHM+u;e-&y?tzUDvBRwhvl7%@*?2*-5 zn8)iNa#>~O9*a}20w;d!7@o3oFYMm1|F?ck8}`e}-C4(q?Li?_oL4xJBSc4!ivdpy#8p;R86GLTl98F^LecDv@+$h3xW`iKgf^7YBnb;RO`(e>-}UKKSc zjp+hUwwTWyILNAwQ=^$$L_2(d?fc0}KKJ`GOP83L>vAjN8d;a>va@EzgSUREb`|7`Q1}2;SNbV0zFyJKq&8LNDVqVTdN{k`5mIre-c2M6Wg4_E}E59{cc6Y=Pc z=^G&oQbaFGeibMmzlvcxGT5xi!#aHZ_0+{B!(WLXeGSrF7Dm4|sAU%BR9lSBOt51? z^Int|e>Y059^jrrhoAQ{agi<_-fXDx|6@5bzrW;bJ{2c$((N4;aNN~hfuxP4UNI`6udRvW=x zc^Dq&j#M#v9IS!8bEWO;{7((MJOca6A{K$Y9=yy*AeL7?*!_K&fywy?z(qE$)C<=ir9@zmwDC(=K`)28 z_SyXEh%W=2lnV?6N;&cit*wur6=3_!I|1#NX6jR@*ib>z);elm!TQPA>Ft#7+)-T5 zFH^yU(&5~tQ6Pt)J=77S>TP&_*~;r?zT=b3TcKjlxz&+8GrtqBx3OtjO+c^}#s>w) z2bUvu0^nu#0-1(e-11?n&ZJ{&it2<*%K~f9B%VD zVL$*&;~S6s{$@iOG%8>LYxGNrI3^(fBhU3oHv!{uwD(RWH|_jEwl$UP-R4bk8XeR~Qtwubh-?CKd*>W!xsnf1)QTLR5Pp%~!M|0RqQOS77Fd zROU=$PRiwCwQG%?FW~k|Vj8z(>upCQVliRBjHsipUZMLX-MjccKAGErW124uf@!#v zMskf0BwiC91NBb-s0aQts?Dn(}4fkbH25%8%*iptV$~@`cvF(5AA=^DMo# zwqfq`kq_oAb-vVo)c?D7PTCn-{9|rJIW>Q%%}yH8F&F?=IC?fwxZ3xz#P zRhh+czljI3q+C_O$?Ul*{RU-Ws8>D3@y)bN9L-!i1BBE3{8KoM3)Cy6a#fB+yGJ`% z$Z}PLj1Fu0G2h;5EHMtB81m+b>1W#GCz#0NUfWfm+a?~%qiR1>0P`dmW(g!w5wCa% zv_YqLVrh@%v5;TnVMx6ORGd+G3tQiIf(6*n5q_MMYdKNl(SJv-VIqFI+Icr-B^z+= zo}-72!-J9d>Gf!7&a};F*hG-vz8`)T*eKLX(AXMHNsI0}bhZDnUz+>nveOc3Rl^d* z?`y_vf)nik%FE-<{|zzs`|4-qcZmlDSXauQ6Jkf8{JQsaI}BW9RyN*+9bU??>-l z{J9%&%)z>~C_+H>Our;Q@A_ZqZQv&Lg{kSE@BIvnXlWzr+8=JEpm48KDYY1nD)Mnh zr3awj@FCfW0ymgOIHdwF@(V)_Wp~90E%}kW*mRj#2ir35mG<4q)u+0$r(TE^4=c18 zC|!Le-#M-Rrm{8X)JtA@9`EBeptd{#1Mer!|dLF&>4}%(G#NZ(zlss8fLlz786N7k%OQM0XN*Sx%KXAjd^5 zT0OrVBMmko2PFY*%qMV!QTo&jMU|acLM6OwIM=p2$%EIq>U7yci(q~8+sIJg4S%28 z!S558iL(4s)3|%GwR;SJMYW1Ud4>!Cuu@|fHW#SgUVrKO5jSp-tukJ@m|JWAnY;E3xoX0G5_Ii z`v9f@`#+3DuJvE|eSYaLxY9ZhWFzXCXPsl4njv@gCjBH$O#dP=D6G7#T$*0YI#|p0 z8UQBRuR<>Ha|>KM_v!4k@7O1`pSJR*lSbuhNsT3LfdI&pV%l8z=6*GPfYs-#{92Opbx8g03glFx(`X{s+>F%yGK zX~ml#!0YV86stqsT1ED2O3xK$cRk3JjOFt$+b@MDV!^2u(8s*WU|ggz72Dz*W0-BppUVo9drXk}5WB0Dc=ZK6=2R>(hbe|w84RCX>nSB64q%g_#py!y4LywW{< zw`f1eZZyR5o;Ij{Q6K7KlM;?2FTSItuY`dPBMQaJL9r?fFyf){UpkbwJXoz*(}HrD z!Qbl-E2MRIUENK*<6(kNgdH7NF$xg2&Q1nHt_jK=%K;uBOrWS$a6lXA9178591PM8 z4&MC#Re)vz3Z|>+ejEmlcRU;WXx(gA8O}q)4lq*y)Ca(yBVynqC{!1DpWeAzvoTp9 QZ>iAov8Sj(QHCrfYl>)w!H6>E)gZh@mUu1o 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 DZgqQZ literal 8206 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 h-zo%P$${)f$vkycfLPokJ|H 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 YWODhH`r7>1Ghhj4L9^ahv=?UoAK7GmYybcN diff --git a/images/workshop-job-item.png b/images/workshop-job-item.png index 952f19ae00733dd764f606421d8e1ee3a9f53ae2..cef6919186c8e324a9354e4ee7d3884caa16341f 100644 GIT binary patch literal 4806 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 literal 8297 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 Jue9`F{~xbFjUNC2 literal 9278 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 f%A<8S0;K#F%U#1OKe-*or8!q|(C3Rfen$ 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 JTLU!s{{Rl?e^3Ab From 5b5c674f6ea774148a545547af2e76de2437c679 Mon Sep 17 00:00:00 2001 From: jj Date: Tue, 20 Nov 2012 21:15:09 +0100 Subject: [PATCH 03/35] ruby: update map_tile.mat_info for soil/stone special cases --- plugins/ruby/map.rb | 62 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/plugins/ruby/map.rb b/plugins/ruby/map.rb index 7c616d722..e9500efa3 100644 --- a/plugins/ruby/map.rb +++ b/plugins/ruby/map.rb @@ -159,8 +159,8 @@ module DFHack v.inorganic_mat if v end - # return the world_data.geo_biome for current tile - def geo_biome + # return the RegionMapEntry (from designation.biome) + def region_map_entry b = designation.biome wd = df.world.world_data @@ -174,7 +174,12 @@ module DFHack ry -= 1 if b < 3 and ry > 0 ry += 1 if b > 5 and ry < wd.world_height-1 - wd.geo_biomes[ wd.region_map[rx][ry].geo_index ] + wd.region_map[rx][ry] + end + + # return the world_data.geo_biome for current tile + def geo_biome + df.world.world_data.geo_biomes[ region_map_entry.geo_index ] end # return the world_data.geo_biome.layer for current tile @@ -182,14 +187,53 @@ module DFHack geo_biome.layers[designation.geolayer_index] end - # current tile mat_index (vein if applicable, or base material) - def mat_index - mat_index_vein or stone_layer.mat_index + # MaterialInfo: token for current tile, based on tilemat (vein, soil, plant, lava_stone...) + def mat_info + case tilemat + when :SOIL + base = stone_layer + if !df.world.raws.inorganics[base.mat_index].flags[:SOIL_ANY] + base = geo_biome.layers.find_all { |l| df.world.raws.inorganics[l.mat_index].flags[:SOIL_ANY] }.last + end + mat_index = (base ? base.mat_index : rand(df.world.raws.inorganics.length)) + MaterialInfo.new(0, mat_index) + + when :STONE + base = stone_layer + if df.world.raws.inorganics[base.mat_index].flags[:SOIL_ANY] + base = geo_biome.layers.find { |l| !df.world.raws.inorganics[l.mat_index].flags[:SOIL_ANY] } + end + mat_index = (base ? base.mat_index : rand(df.world.raws.inorganics.length)) + MaterialInfo.new(0, mat_index) + + when :MINERAL + mat_index = (mat_index_vein || stone_layer.mat_index) + MaterialInfo.new(0, mat_index) + + when :LAVA_STONE + # XXX this is wrong + # maybe should search world.region_details.pos == biome_region_pos ? + idx = mapblock.region_offset[designation.biome] + mat_index = df.world.world_data.region_details[idx].lava_stone + MaterialInfo.new(0, mat_index) + + # TODO + #when :PLANT + #when :GRASS_DARK, :GRASS_DEAD, :GRASS_DRY, :GRASS_LIGHT + #when :FEATURE + #when :FROZEN_LIQUID + #when :CONSTRUCTION + else # AIR ASHES BROOK CAMPFIRE DRIFTWOOD FIRE HFS MAGMA POOL RIVER + MaterialInfo.new(-1, -1) + end end - # MaterialInfo: inorganic token for current tile - def mat_info - MaterialInfo.new(0, mat_index) + def mat_type + mat_info.mat_type + end + + def mat_index + mat_info.mat_index end def inspect From 0d9efec062f4fd63e46266e1cfecde7d726c11df Mon Sep 17 00:00:00 2001 From: Anuradha Dissanayake Date: Wed, 21 Nov 2012 20:17:36 +1300 Subject: [PATCH 04/35] Disable plugin in non construction menu --- plugins/automaterial.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/plugins/automaterial.cpp b/plugins/automaterial.cpp index 2e39f3411..d05e13a3e 100644 --- a/plugins/automaterial.cpp +++ b/plugins/automaterial.cpp @@ -102,19 +102,28 @@ void OutputHotkeyString(int &x, int &y, const char *text, const char *hotkey, bo static inline bool in_material_choice_stage() { return Gui::build_selector_hotkey(Core::getTopViewscreen()) && + ui_build_selector->building_type == df::building_type::Construction && ui->main.mode == ui_sidebar_mode::Build && ui_build_selector->stage == 2; } -static inline bool in_type_choice_stage() +static inline bool in_placement_stage() { return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) && ui->main.mode == ui_sidebar_mode::Build && ui_build_selector && - ui_build_selector->building_type >= 0 && + ui_build_selector->building_type == df::building_type::Construction && ui_build_selector->stage == 1; } +static inline bool in_type_choice_stage() +{ + return Gui::dwarfmode_hotkey(Core::getTopViewscreen()) && + ui->main.mode == ui_sidebar_mode::Build && + ui_build_selector && + ui_build_selector->building_type < 0; +} + static inline vector &get_curr_constr_prefs() { if (preferred_materials.find(ui_build_selector->building_subtype) == preferred_materials.end()) @@ -281,7 +290,7 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest } } } - else if (in_type_choice_stage()) + else if (in_placement_stage()) { if (input->count(interface_key::CUSTOM_A)) { @@ -358,7 +367,7 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest OutputHotkeyString(x, y, toggle_string.c_str(), "a", true, left_margin); } } - else if (in_type_choice_stage() && ui_build_selector->building_subtype != 7) + else if (in_placement_stage() && ui_build_selector->building_subtype != 7) { int left_margin = gps->dimx - 30; int x = left_margin; From 2a83d9229094eb38628c422ede9d1b28495cd8ec Mon Sep 17 00:00:00 2001 From: Anuradha Dissanayake Date: Wed, 21 Nov 2012 23:45:26 +1300 Subject: [PATCH 05/35] Code cleanup --- plugins/automaterial.cpp | 124 ++++++++++++++------------------------- 1 file changed, 45 insertions(+), 79 deletions(-) diff --git a/plugins/automaterial.cpp b/plugins/automaterial.cpp index d05e13a3e..ac5a4ae22 100644 --- a/plugins/automaterial.cpp +++ b/plugins/automaterial.cpp @@ -14,13 +14,14 @@ // DF data structure definition headers #include "DataDefs.h" #include "MiscUtils.h" -#include "df/viewscreen_dwarfmodest.h" -#include "df/ui_build_selector.h" #include "df/build_req_choice_genst.h" #include "df/build_req_choice_specst.h" +#include "df/construction_type.h" #include "df/item.h" - #include "df/ui.h" +#include "df/ui_build_selector.h" +#include "df/viewscreen_dwarfmodest.h" + #include "modules/Gui.h" #include "modules/Screen.h" @@ -34,7 +35,6 @@ using df::global::gps; using df::global::ui; using df::global::ui_build_selector; - DFHACK_PLUGIN("automaterial"); struct MaterialDescriptor @@ -55,12 +55,10 @@ struct MaterialDescriptor } }; -typedef int16_t construction_type; - -static map last_used_material; -static map last_moved_material; -static map< construction_type, vector > preferred_materials; -static map< construction_type, df::interface_key > hotkeys; +static map last_used_material; +static map last_moved_material; +static map< int16_t, vector > preferred_materials; +static map< int16_t, df::interface_key > hotkeys; static bool last_used_moved = false; static bool auto_choose_materials = true; static bool auto_choose_attempted = true; @@ -71,7 +69,6 @@ static command_result automaterial_cmd(color_ostream &out, vector & par return CR_OK; } - DFhackCExport command_result plugin_shutdown ( color_ostream &out ) { return CR_OK; @@ -183,7 +180,6 @@ static MaterialDescriptor get_material_in_list(size_t i) return result; } - static bool is_material_in_autoselect(size_t &i, MaterialDescriptor &material) { for (i = 0; i < get_curr_constr_prefs().size(); i++) @@ -225,27 +221,6 @@ static bool move_material_to_top(MaterialDescriptor &material) return false; } -static bool choose_materials() -{ - size_t size = ui_build_selector->choices.size(); - for (size_t i = 0; i < size; i++) - { - MaterialDescriptor material = get_material_in_list(i); - size_t j; - if (is_material_in_autoselect(j, material)) - { - ui_build_selector->sel_index = i; - std::set< df::interface_key > keys; - keys.insert(df::interface_key::SELECT_ALL); - Core::getTopViewscreen()->feed(&keys); - if (!in_material_choice_stage()) - return true; - } - } - - return false; -} - static bool check_autoselect(MaterialDescriptor &material, bool toggle) { size_t idx; @@ -269,6 +244,27 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest { typedef df::viewscreen_dwarfmodest interpose_base; + bool choose_materials() + { + size_t size = ui_build_selector->choices.size(); + for (size_t i = 0; i < size; i++) + { + MaterialDescriptor material = get_material_in_list(i); + size_t j; + if (is_material_in_autoselect(j, material)) + { + ui_build_selector->sel_index = i; + std::set< df::interface_key > keys; + keys.insert(df::interface_key::SELECT_ALL); + this->feed(&keys); + if (!in_material_choice_stage()) + return true; + } + } + + return false; + } + DEFINE_VMETHOD_INTERPOSE(void, feed, (set *input)) { if (in_material_choice_stage()) @@ -302,15 +298,17 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest } } - construction_type last_used_constr_subtype = (in_material_choice_stage()) ? ui_build_selector->building_subtype : -1; + int16_t last_used_constr_subtype = (in_material_choice_stage()) ? ui_build_selector->building_subtype : -1; INTERPOSE_NEXT(feed)(input); - if (revert_to_last_used_type && last_used_constr_subtype >= 0 && !in_material_choice_stage()) + if (revert_to_last_used_type && + last_used_constr_subtype >= 0 && + !in_material_choice_stage() && + hotkeys.find(last_used_constr_subtype) != hotkeys.end()) { input->clear(); - std::set< df::interface_key > keys; - keys.insert(hotkeys[last_used_constr_subtype]); - Core::getTopViewscreen()->feed(&keys); + input->insert(hotkeys[last_used_constr_subtype]); + this->feed(input); } } @@ -394,46 +392,14 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector Date: Wed, 21 Nov 2012 14:56:41 +0400 Subject: [PATCH 06/35] Add a couple of screenshots for tweaks, and comment on example config keys. --- NEWS | 6 +-- Readme.html | 79 +++++++++++++++++++++++-------------- Readme.rst | 44 +++++++++++++++------ images/tweak-mil-color.png | Bin 0 -> 6967 bytes images/tweak-plate.png | Bin 0 -> 3365 bytes 5 files changed, 85 insertions(+), 44 deletions(-) create mode 100644 images/tweak-mil-color.png create mode 100644 images/tweak-plate.png diff --git a/NEWS b/NEWS index 2cde6ba68..f14bcb1b4 100644 --- a/NEWS +++ b/NEWS @@ -10,13 +10,13 @@ DFHack future - fastdwarf: new mode using debug flags, and some internal consistency fixes. - added a small stand-alone utility for applying and removing binary patches. - removebadthoughts: add --dry-run option - New tweaks: - - tweak military-training: speed up melee squad training up to 10x (depends on unit count). - superdwarf: work in adventure mode too + New tweaks: + - tweak military-training: speed up melee squad training up to 10x (normally 3-5x). New scripts: - binpatch: the same as the stand-alone binpatch.exe, but works at runtime. - region-pops: displays animal populations of the region and allows tweaking them. - - lua: lua interpreter. + - lua: lua interpreter front-end converted to a script from a native command. - dfusion: misc scripts with a text based menu. - embark: lets you embark anywhere. New GUI scripts: diff --git a/Readme.html b/Readme.html index 137971abd..f520e1a82 100644 --- a/Readme.html +++ b/Readme.html @@ -1840,43 +1840,55 @@ they are scuttled. -stable-cursor:Saves the exact cursor position between t/q/k/d/etc menus of dwarfmode. +stable-cursor:

Saves the exact cursor position between t/q/k/d/etc menus of dwarfmode.

+ -patrol-duty:Makes Train orders not count as patrol duty to stop unhappy thoughts. -Does NOT fix the problem when soldiers go off-duty (i.e. civilian). +patrol-duty:

Makes Train orders not count as patrol duty to stop unhappy thoughts. +Does NOT fix the problem when soldiers go off-duty (i.e. civilian).

+ readable-build-plate: - Fixes rendering of creature weight limits in pressure plate build menu. + 

Fixes rendering of creature weight limits in pressure plate build menu.

+images/tweak-plate.png + -stable-temp:Fixes performance bug 6012 by squashing jitter in temperature updates. -In very item-heavy forts with big stockpiles this can improve FPS by 50-100% +stable-temp:

Fixes performance bug 6012 by squashing jitter in temperature updates. +In very item-heavy forts with big stockpiles this can improve FPS by 50-100%

+ -fast-heat:Further improves temperature update performance by ensuring that 1 degree +fast-heat:

Further improves temperature update performance by ensuring that 1 degree of item temperature is crossed in no more than specified number of frames when updating from the environment temperature. This reduces the time it -takes for stable-temp to stop updates again when equilibrium is disturbed. +takes for stable-temp to stop updates again when equilibrium is disturbed.

+ -fix-dimensions:Fixes subtracting small amount of thread/cloth/liquid from a stack +fix-dimensions:

Fixes subtracting small amount of thread/cloth/liquid from a stack by splitting the stack and subtracting from the remaining single item. -This is a necessary addition to the binary patch in bug 808. +This is a necessary addition to the binary patch in bug 808.

+ advmode-contained: - Works around bug 6202, i.e. custom reactions with container inputs + 

Works around bug 6202, i.e. custom reactions with container inputs in advmode. The issue is that the screen tries to force you to select the contents separately from the container. This forcefully skips child -reagents. +reagents.

+ -fast-trade:Makes Shift-Enter in the Move Goods to Depot and Trade screens select -the current item (fully, in case of a stack), and scroll down one line. +fast-trade:

Makes Shift-Enter in the Move Goods to Depot and Trade screens select +the current item (fully, in case of a stack), and scroll down one line.

+ military-stable-assign: - Preserve list order and cursor position when assigning to squad, + 

Preserve list order and cursor position when assigning to squad, i.e. stop the rightmost list of the Positions page of the military -screen from constantly resetting to the top. +screen from constantly resetting to the top.

+ military-color-assigned: - Color squad candidates already assigned to other squads in brown/green -to make them stand out more in the list. + 

Color squad candidates already assigned to other squads in yellow/green +to make them stand out more in the list.

+images/tweak-mil-color.png + @@ -2826,14 +2838,14 @@ key while search is active clears the search instead of executing the trade.

gui/liquids

-

To use, bind to a key and activate in the 'k' mode.

+

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

images/liquids.png

While active, use the suggested keys to switch the usual liquids parameters, and Enter to select the target area and apply changes.

gui/mechanisms

-

To use, bind to a key and activate in the 'q' mode.

+

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

images/mechanisms.png

Lists mechanisms connected to the building, and their links. Navigating the list centers the view on the relevant linked buildings.

@@ -2861,18 +2873,21 @@ their species string.

The building or unit options are automatically assumed when in relevant ui state.

+

The example config binds building/unit rename to Ctrl-Shift-N, and +unit profession change to Ctrl-Shift-T.

gui/room-list

-

To use, bind to a key and activate in the 'q' mode, either immediately or after opening -the assign owner page.

+

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

images/room-list.png

The script lists other rooms owned by the same owner, or by the unit selected in the assign list, and allows unassigning them.

gui/choose-weapons

-

Bind to a key, and activate in the Equip->View/Customize page of the military screen.

+

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

Depending on the cursor location, it rewrites all 'individual choice weapon' entries in the selected squad or position to use a specific weapon type matching the assigned unit's top skill. If the cursor is in the rightmost list over a weapon entry, it rewrites @@ -2882,14 +2897,16 @@ and may lead to inappropriate weapons being selected.

gui/guide-path

-

Bind to a key, and activate in the Hauling menu with the cursor over a Guide order.

+

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

images/guide-path.png

The script displays the cached path that will be used by the order; the game computes it when the order is executed for the first time.

gui/workshop-job

-

Bind to a key, and activate with a job selected in a workshop in the 'q' mode.

+

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

images/workshop-job.png

The script shows a list of the input reagents of the selected job, and allows changing them like the job item-type and job item-material commands.

@@ -2924,7 +2941,8 @@ you have to unset the material first.

gui/workflow

-

Bind to a key, and activate with a job selected in a workshop in the 'q' mode.

+

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

images/workflow.png

This script provides a simple interface to constraints managed by the workflow plugin. When active, it displays a list of all constraints applicable to the @@ -2953,7 +2971,8 @@ suit your need, and set the item count range.

gui/assign-rack

-

Bind to a key, and activate when viewing a weapon rack in the 'q' mode.

+

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

images/assign-rack.png

This script is part of a group of related fixes to make the armory storage work again. The existing issues are:

@@ -3002,7 +3021,8 @@ e.g. like making siegers bring their own, are something only Toady can do.

Configuration UI

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

+script. Bind it to a key (the example config uses Alt-A) and activate after selecting +a siege engine in 'q' mode.

images/siege-engine.png

The main mode displays the current target, selected ammo item type, linked stockpiles and the allowed operator skill range. The map tile color is changed to signify if it can be @@ -3026,7 +3046,8 @@ menu.

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

The configuration front-end is implemented by the gui/power-meter script. Bind it to a -key and activate after selecting Pressure Plate in the build menu.

+key (the example config uses Ctrl-Shift-M) and activate after selecting Pressure Plate +in the build menu.

images/power-meter.png

The script follows the general look and feel of the regular pressure plate build configuration page, but configures parameters relevant to the modded power meter building.

diff --git a/Readme.rst b/Readme.rst index 4488490dd..1f5ac08fd 100644 --- a/Readme.rst +++ b/Readme.rst @@ -1077,6 +1077,9 @@ Subcommands that persist until disabled or DF quit: :patrol-duty: Makes Train orders not count as patrol duty to stop unhappy thoughts. Does NOT fix the problem when soldiers go off-duty (i.e. civilian). :readable-build-plate: Fixes rendering of creature weight limits in pressure plate build menu. + + .. image:: images/tweak-plate.png + :stable-temp: Fixes performance bug 6012 by squashing jitter in temperature updates. In very item-heavy forts with big stockpiles this can improve FPS by 50-100% :fast-heat: Further improves temperature update performance by ensuring that 1 degree @@ -1095,9 +1098,16 @@ Subcommands that persist until disabled or DF quit: :military-stable-assign: Preserve list order and cursor position when assigning to squad, i.e. stop the rightmost list of the Positions page of the military screen from constantly resetting to the top. -:military-color-assigned: Color squad candidates already assigned to other squads in brown/green +:military-color-assigned: Color squad candidates already assigned to other squads in yellow/green to make them stand out more in the list. + .. image:: images/tweak-mil-color.png + +:military-training: Speeds up melee squad training by removing an almost certainly + unintended inverse dependency of training speed on unit count + (i.e. the more units you have, the slower it becomes), and making + the units spar more. + fix-armory ---------- @@ -2039,7 +2049,7 @@ key while search is active clears the search instead of executing the trade. gui/liquids =========== -To use, bind to a key and activate in the 'k' mode. +To use, bind to a key (the example config uses Alt-L) and activate in the 'k' mode. .. image:: images/liquids.png @@ -2050,7 +2060,7 @@ to select the target area and apply changes. gui/mechanisms ============== -To use, bind to a key and activate in the 'q' mode. +To use, bind to a key (the example config uses Ctrl-M) and activate in the 'q' mode. .. image:: images/mechanisms.png @@ -2088,12 +2098,15 @@ via a simple dialog in the game ui. The ``building`` or ``unit`` options are automatically assumed when in relevant ui state. +The example config binds building/unit rename to Ctrl-Shift-N, and +unit profession change to Ctrl-Shift-T. + gui/room-list ============= -To use, bind to a key and activate in the 'q' mode, either immediately or after opening -the assign owner page. +To use, bind to a key (the example config uses Alt-R) and activate in the 'q' mode, +either immediately or after opening the assign owner page. .. image:: images/room-list.png @@ -2104,7 +2117,8 @@ list, and allows unassigning them. gui/choose-weapons ================== -Bind to a key, and activate in the Equip->View/Customize page of the military screen. +Bind to a key (the example config uses Ctrl-W), and activate in the Equip->View/Customize +page of the military screen. Depending on the cursor location, it rewrites all 'individual choice weapon' entries in the selected squad or position to use a specific weapon type matching the assigned @@ -2118,7 +2132,8 @@ and may lead to inappropriate weapons being selected. gui/guide-path ============== -Bind to a key, and activate in the Hauling menu with the cursor over a Guide order. +Bind to a key (the example config uses Alt-P), and activate in the Hauling menu with +the cursor over a Guide order. .. image:: images/guide-path.png @@ -2129,7 +2144,8 @@ computes it when the order is executed for the first time. gui/workshop-job ================ -Bind to a key, and activate with a job selected in a workshop in the 'q' mode. +Bind to a key (the example config uses Alt-A), and activate with a job selected in +a workshop in the 'q' mode. .. image:: images/workshop-job.png @@ -2176,7 +2192,8 @@ you have to unset the material first. gui/workflow ============ -Bind to a key, and activate with a job selected in a workshop in the 'q' mode. +Bind to a key (the example config uses Alt-W), and activate with a job selected +in a workshop in the 'q' mode. .. image:: images/workflow.png @@ -2217,7 +2234,8 @@ If you don't need advanced settings, you can just press 'y' to confirm creation. gui/assign-rack =============== -Bind to a key, and activate when viewing a weapon rack in the 'q' mode. +Bind to a key (the example config uses P), and activate when viewing a weapon +rack in the 'q' mode. .. image:: images/assign-rack.png @@ -2278,7 +2296,8 @@ Configuration UI ---------------- The configuration front-end to the plugin is implemented by the gui/siege-engine -script. Bind it to a key and activate after selecting a siege engine in 'q' mode. +script. Bind it to a key (the example config uses Alt-A) and activate after selecting +a siege engine in 'q' mode. .. image:: images/siege-engine.png @@ -2310,7 +2329,8 @@ The power-meter plugin implements a modified pressure plate that detects power b supplied to gear boxes built in the four adjacent N/S/W/E tiles. The configuration front-end is implemented by the gui/power-meter script. Bind it to a -key and activate after selecting Pressure Plate in the build menu. +key (the example config uses Ctrl-Shift-M) and activate after selecting Pressure Plate +in the build menu. .. image:: images/power-meter.png diff --git a/images/tweak-mil-color.png b/images/tweak-mil-color.png new file mode 100644 index 0000000000000000000000000000000000000000..b4a012cabf69fe7ab62d0941dcd018f946c86eab GIT binary patch literal 6967 zcmZ{Jby!qgwEhG`4KX04)F2_<(hMUxbP5b1(k0!^AZftRA)$mwhjd8^LwBbjA_5=M zDPF!`-g}?t{&DtN=Y7t*pMCaP>+G}N9jBwELQ4FA7ytl}s-hJ2001x?008phf$xw3 z@F3Bhq1VwcPznzZ2ZV=rc6R>#`}Yn5+%@5Vf8D=-3nJb&-XTCMbrnT01&PMd-3^gD z3he~|kY(Rpy+EI{NDKh*KwnkyiGly(e$KAPG55XxH5yS>2nnf;JGjevo9emWx-KMB z7rd=77%Jz!0DZ5{Yw9^FeEidc4Gj;qqP>0A`}ej{!snc$EoH&>YVCEA__o>kk7boP z$^Npdg54JXb=Li$>sb2jmP#*DI87%#wA`v({JF*j0Y~Tq?Mq^sPVo-l(XtW2Wb>#` z&aT<{+2PrffVL3tl_iz!ZVrw)AMBp2Q5JnQkDkcZ-12zHXOhBYq*tM)V|}B^$JUB>p?j3!rk7B?={=6&r27Ac`d= z!cVj#>+K!>%@T8>F{7rf<}QPsjFIyrjg+zGgA=49h>}wgvlzkRP!glAQgS*>nn!Lm%c0j6dNF`A6Z#$TX zCinqL*wgWz+cA=yYDQ>wXpmz!5&5joMoA?rkKWIH+DVc2=LXkLctXIvm9q~Lf_@AU z*UMdedpB6<_Xw|dw8CTOELZG*QxjW)<_B1F_)@iIRe9bJWb4DTn0`#FC$pSQcs$v1 zM7Uo1ONkre)P}fZVwME3)|$5zww1=tjUOP7{&YF9@E{|k8m-}EK}em%Fgw7)$B$KO<2iy8X6>*nCvYAK;L@F|p z_EC>Tqc*%>3RYS|xbkgXZNN`~Sw5TrFi4|!$imsa4{R=%#n#o8#O1>!XmXBqVT-eiavvu!wP0DC19nfdklgan;~w&Y>&Qk^zrEb%lY=P*GIAh^yxscg zDp~rZs51klV0I-o`wDXRsMZR#>$jipDcoiV(4dJcMUV#Q>TE<7uj(B`WW#JbtrP0|5#`Ej zy3NZFTQ;+tOkr-p$6Sx7@XVm~g!+h!G?v7GjeJxuUr}#PQoi;r;!Ov31yK)yqU!bC zL;8bLc&qF2P<*U-5h_#My3w-zWk8m%vEtybN9qAvrNv;?Arfk&dr6CqbuReB_DZrY zur~uACMVa3wyi;!d6UFia1B8!=EQ#y1=lz*%0Ad@CEs32P3#)l4lY9i?6$?23EzOw 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 Date: Thu, 22 Nov 2012 02:57:55 +0100 Subject: [PATCH 07/35] add scripts/lever, add binary patches section in NEWS file --- NEWS | 9 ++++ scripts/lever.rb | 109 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 scripts/lever.rb diff --git a/NEWS b/NEWS index f14bcb1b4..e12608d34 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,7 @@ DFHack future - lua: lua interpreter front-end converted to a script from a native command. - dfusion: misc scripts with a text based menu. - embark: lets you embark anywhere. + - lever: list and pull fort levers from the dfhack console. New GUI scripts: - gui/guide-path: displays the cached path for minecart Guide orders. - gui/workshop-job: displays inputs of a workshop job and allows tweaking them. @@ -26,6 +27,14 @@ DFHack future - gui/assign-rack: works together with a binary patch to fix weapon racks. - gui/gm-editor: an universal editor for lots of dfhack things. - gui/companion-order: a adventure mode command interface for your companions. + New binary patches: + - armorstand-capacity + - custom-reagent-size + - deconstruct-heapfall + - deconstruct-teleport + - hospital-overstocking + - training-ammo + - weaponrack-unassign Workflow plugin: - properly considers minecarts assigned to routes busy. - code for deducing job outputs rewritten in lua for flexibility. diff --git a/scripts/lever.rb b/scripts/lever.rb new file mode 100644 index 000000000..2012f7297 --- /dev/null +++ b/scripts/lever.rb @@ -0,0 +1,109 @@ +# control your levers from the dfhack console + +def lever_pull_job(bld) + ref = DFHack::GeneralRefBuildingHolderst.cpp_new + ref.building_id = bld.id + + job = DFHack::Job.cpp_new + job.job_type = :PullLever + job.pos = [bld.centerx, bld.centery, bld.z] + job.general_refs << ref + bld.jobs << job + df.job_link job +end + +def lever_pull_cheat(bld) + bld.state = (bld.state == 0 ? 1 : 0) + + bld.linked_mechanisms.each { |i| + i.general_refs.grep(DFHack::GeneralRefBuildingHolderst).each { |r| + tg = r.building_tg + next if tg.gate_flags.closing or tg.gate_flags.opening + r.building_tg.setTriggerState(tg.gate_flags.closed ? 0 : 1) + } + } + + puts lever_descr(bld) +end + +def lever_descr(bld, idx=nil) + ret = [] + + # lever description + descr = '' + descr << "#{idx}: " if idx + descr << "lever ##{bld.id} @[#{bld.centerx}, #{bld.centery}, #{bld.z}] #{bld.state == 0 ? '\\' : '/'}" + + bld.linked_mechanisms.map { |i| + i.general_refs.grep(DFHack::GeneralRefBuildingHolderst) + }.flatten.each { |r| + # linked building description + tg = r.building_tg + state = tg.gate_flags.closed ? 'closed' : 'opened' + state << ', closing' if tg.gate_flags.closing + state << ', opening' if tg.gate_flags.opening + + ret << (descr + " linked to #{tg._rtti_classname} ##{tg.id} @[#{tg.centerx}, #{tg.centery}, #{tg.z}] #{state}") + + # indent other links + descr = descr.gsub(/./, ' ') + } + + ret << descr if ret.empty? + + ret +end + +def lever_list + @lever_list = [] + df.world.buildings.other[:TRAP].find_all { |bld| + bld.trap_type == :Lever + }.sort_by { |bld| bld.id }.each { |bld| + puts lever_descr(bld, @lever_list.length) + @lever_list << bld.id + } +end + +case $script_args[0] +when 'pull' + cheat = $script_args.delete('--cheat') || $script_args.delete('--now') + + id = $script_args[1].to_i + id = @lever_list[id] || id + bld = df.building_find(id) + raise 'invalid lever id' if not bld + + if cheat + lever_pull_cheat(bld) + else + lever_pull_job(bld) + end + +when 'list' + lever_list + +when /^\d+$/ + id = $script_args[0].to_i + id = @lever_list[id] || id + bld = df.building_find(id) + raise 'invalid lever id' if not bld + + puts lever_descr(bld) + +else + puts < Date: Thu, 22 Nov 2012 03:17:41 +0100 Subject: [PATCH 08/35] script/lever: synchronize linked buildings as the game does --- scripts/lever.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/scripts/lever.rb b/scripts/lever.rb index 2012f7297..2c7735146 100644 --- a/scripts/lever.rb +++ b/scripts/lever.rb @@ -13,16 +13,14 @@ def lever_pull_job(bld) end def lever_pull_cheat(bld) - bld.state = (bld.state == 0 ? 1 : 0) - bld.linked_mechanisms.each { |i| i.general_refs.grep(DFHack::GeneralRefBuildingHolderst).each { |r| - tg = r.building_tg - next if tg.gate_flags.closing or tg.gate_flags.opening - r.building_tg.setTriggerState(tg.gate_flags.closed ? 0 : 1) + r.building_tg.setTriggerState(bld.state) } } + bld.state = (bld.state == 0 ? 1 : 0) + puts lever_descr(bld) end From e7905a5cff2b6174d92527ab6bbdd8358b98b877 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 22 Nov 2012 19:38:45 +0400 Subject: [PATCH 09/35] Add docs for the automaterial plugin, and use the new Painter class. --- NEWS | 3 + Readme.html | 123 ++++++++++++++++++++----------- Readme.rst | 39 ++++++++++ images/automaterial-mat.png | Bin 0 -> 5187 bytes images/automaterial-pos.png | Bin 0 -> 3007 bytes library/include/modules/Screen.h | 4 + plugins/automaterial.cpp | 69 ++++++----------- 7 files changed, 147 insertions(+), 91 deletions(-) create mode 100644 images/automaterial-mat.png create mode 100644 images/automaterial-pos.png diff --git a/NEWS b/NEWS index e12608d34..6ba9a769f 100644 --- a/NEWS +++ b/NEWS @@ -47,6 +47,9 @@ DFHack future properly designated barracks be used again for storage of squad equipment. New Search plugin by falconne: Adds an incremental search function to the Stocks, Trading and Unit List screens. + New AutoMaterial plugin by falconne: + Makes building constructions (walls, floors, fortifications, etc) a little bit easier by + saving you from having to trawl through long lists of materials each time you place one. Dfusion plugin: Reworked to make use of lua modules, now all the scripts can be used from other scripts. diff --git a/Readme.html b/Readme.html index f520e1a82..5b231b429 100644 --- a/Readme.html +++ b/Readme.html @@ -508,33 +508,34 @@ access DF memory and allow for easier development of new tools.

  • In-game interface tools
  • -
  • Behavior Mods
  • @@ -2836,15 +2846,42 @@ are actually visible in the list; the same effect applies to the Trade Value numbers displayed by the screen. Because of this, pressing the 't' key while search is active clears the search instead of executing the trade.

    +
    +

    AutoMaterial

    +

    The automaterial plugin makes building constructions (walls, floors, fortifications, +etc) a little bit easier by saving you from having to trawl through long lists of +materials each time you place one.

    +

    Firstly, it moves the last used material for a given construction type to the top of +the list, if there are any left. So if you build a wall with chalk blocks, the next +time you place a wall the chalk blocks will be at the top of the list, regardless of +distance (it only does this in "grouped" mode, as individual item lists could be huge). +This should mean you can place most constructions without having to search for your +preferred material type.

    +images/automaterial-mat.png +

    Pressing 'a' while highlighting any material will enable that material for "auto select" +for this construction type. You can enable multiple materials as autoselect. Now the next +time you place this type of construction, the plugin will automatically choose materials +for you from the kinds you enabled. If there is enough to satisfy the whole placement, +you won't be prompted with the material screen - the construction will be placed and you +will be back in the construction menu as if you did it manually.

    +

    When choosing the construction placement, you will see a couple of options:

    +images/automaterial-pos.png +

    Use 'a' here to temporarily disable the material autoselection, e.g. if you need +to go to the material selection screen so you can toggle some materials on or off.

    +

    The other option (auto type selection, off by default) can be toggled on with 't'. If you +toggle this option on, instead of returning you to the main construction menu after selecting +materials, it returns you back to this screen. If you use this along with several autoselect +enabled materials, you should be able to place complex constructions more conveniently.

    +
    -

    gui/liquids

    +

    gui/liquids

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

    images/liquids.png

    While active, use the suggested keys to switch the usual liquids parameters, and Enter to select the target area and apply changes.

    -

    gui/mechanisms

    +

    gui/mechanisms

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

    images/mechanisms.png

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

    -

    gui/rename

    +

    gui/rename

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

      @@ -2877,7 +2914,7 @@ their species string.

      unit profession change to Ctrl-Shift-T.

    -

    gui/room-list

    +

    gui/room-list

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

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

    list, and allows unassigning them.

    -

    gui/choose-weapons

    +

    gui/choose-weapons

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

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

    and may lead to inappropriate weapons being selected.

    -

    gui/guide-path

    +

    gui/guide-path

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

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

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

    -

    gui/workshop-job

    +

    gui/workshop-job

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

    images/workshop-job.png @@ -2940,7 +2977,7 @@ and then try to change the input item type, now it won't let you select plan you have to unset the material first.

    -

    gui/workflow

    +

    gui/workflow

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

    images/workflow.png @@ -2970,7 +3007,7 @@ suit your need, and set the item count range.

    If you don't need advanced settings, you can just press 'y' to confirm creation.

    -

    gui/assign-rack

    +

    gui/assign-rack

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

    images/assign-rack.png @@ -2995,7 +3032,7 @@ of currently assigned racks for every valid squad.

    -

    Behavior Mods

    +

    Behavior Mods

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

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

    -

    Siege Engine

    +

    Siege Engine

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

    -

    Rationale

    +

    Rationale

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

    -

    Configuration UI

    +

    Configuration UI

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

    @@ -3042,7 +3079,7 @@ menu.

    -

    Power Meter

    +

    Power Meter

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

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

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

    -

    Steam Engine

    +

    Steam Engine

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

    -

    Rationale

    +

    Rationale

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

    -

    Construction

    +

    Construction

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

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

    -

    Operation

    +

    Operation

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

    -

    Explosions

    +

    Explosions

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

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

    -

    Save files

    +

    Save files

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

    -

    Add Spatter

    +

    Add Spatter

    This plugin makes reactions with names starting with SPATTER_ADD_ produce contaminants on the items instead of improvements. The produced contaminants are immune to being washed away by water or destroyed by diff --git a/Readme.rst b/Readme.rst index 1f5ac08fd..e6554cac0 100644 --- a/Readme.rst +++ b/Readme.rst @@ -1968,6 +1968,9 @@ are mostly implemented by lua scripts. In order to avoid user confusion, as a matter of policy all these tools display the word "DFHack" on the screen somewhere while active. + When that is not appropriate because they merely add keybinding hints to + existing DF screens, they deliberately use red instead of green for the key. + As an exception, the tweak plugin described above does not follow this guideline because it arguably just fixes small usability bugs in the game UI. @@ -2046,6 +2049,42 @@ Value numbers displayed by the screen. Because of this, pressing the 't' key while search is active clears the search instead of executing the trade. +AutoMaterial +============ + +The automaterial plugin makes building constructions (walls, floors, fortifications, +etc) a little bit easier by saving you from having to trawl through long lists of +materials each time you place one. + +Firstly, it moves the last used material for a given construction type to the top of +the list, if there are any left. So if you build a wall with chalk blocks, the next +time you place a wall the chalk blocks will be at the top of the list, regardless of +distance (it only does this in "grouped" mode, as individual item lists could be huge). +This should mean you can place most constructions without having to search for your +preferred material type. + +.. image:: images/automaterial-mat.png + +Pressing 'a' while highlighting any material will enable that material for "auto select" +for this construction type. You can enable multiple materials as autoselect. Now the next +time you place this type of construction, the plugin will automatically choose materials +for you from the kinds you enabled. If there is enough to satisfy the whole placement, +you won't be prompted with the material screen - the construction will be placed and you +will be back in the construction menu as if you did it manually. + +When choosing the construction placement, you will see a couple of options: + +.. image:: images/automaterial-pos.png + +Use 'a' here to temporarily disable the material autoselection, e.g. if you need +to go to the material selection screen so you can toggle some materials on or off. + +The other option (auto type selection, off by default) can be toggled on with 't'. If you +toggle this option on, instead of returning you to the main construction menu after selecting +materials, it returns you back to this screen. If you use this along with several autoselect +enabled materials, you should be able to place complex constructions more conveniently. + + gui/liquids =========== diff --git a/images/automaterial-mat.png b/images/automaterial-mat.png new file mode 100644 index 0000000000000000000000000000000000000000..5517bbc6d33636b9842da1b712cac161a74a4f39 GIT binary patch literal 5187 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 literal 0 HcmV?d00001 diff --git a/images/automaterial-pos.png b/images/automaterial-pos.png new file mode 100644 index 0000000000000000000000000000000000000000..959573643a8d8a0ba3e9c686dd80e1885f4ad318 GIT binary patch literal 3007 zcma)83pA8l8~(;H?lYt0n&~5)Fw{&JC#h!43?ov;tx?By5JHBCqA}w#-T0Ktp_|0y zc2pB8w;V|$Ni^i{BywDT@bn6B z@94%XxP$Pqv!TkWdGn{>f&5WAGXen6m*KYwaqLrK0sts<+EU5R$NOdm>q7f2RXN_M zO<*2#aaTpt|VB9KDWJ%e$eF^RMY$C z__mg`x092F7Pl+gf2-=Ues};a#Z>IDEDe60c7{cY+EEvG_e4tW z4lT}TB~ECxqJffO6kDF!Xdcx58C&d7+E-Rp8uI6LT&8E|krF}lo^^9R^IP*$`1ASU zuFDZ)EBY6z4MkIz`lAwR>vPnt!LyY}g4*QA9g2!01y6UYvDR?QrXP6P#x=Wj9%)36 zkTTk_P;IX)_4d8c-OyUmRJkHGS_LVIo2!xc!IvPv8mO^?$>%5o6fvjj7%yi6G?8V5 zqPQ74`IcQlk?vE^Rk(OAa;*P|w`ab`8}o|^(@|>F^Y*uD+;(tv5RSi4-<9nDu*i%{ zxrb{c--fzV6>Mhc_&bu-!ylcpdUN_DjB~st0j9wa&6Chf?@JuXtMT|FMa4|uN_W9 zhD2}7hw)un!alO(tBb2Pz2C)Eoj&D~Ro9?(EYo11CqlYu)?hR1LEdZf0MH$u=_i3U z$V`YRRb6XbOfgKE-wU%+iqxOZh%Bi+<= zKU$0IJycjj1lE4pz!_a#dN>Ud@}6n3diLog@C`*Sw}k$2y(dyNE~tqHc-0#67jm#8 z7gSb@&zf*go~*rCe6bkWsmy2_m(|yVu3cLJY?0I_(9+!{BwefUqNLGnX-Sq&1a~XR z5%kwU7*eNHjI6#9lostncL$A&A~G|3T-0LdK{0YUu|7E#U|_=jL-x})HB&K68e>j4 zt1~(p!_QJ^%4z zZ>Roo<@{HhS1u2GWhYoVW5N3+rMC;t06c0jzeW4 zh3n>jRb2~D&gj^hBn@^P)~VKbG5Ljd5EDl6b>Uf2t*;zR90wqhcQ}PRrldW&^uoRl14v=6*ucOEGv8sy=JLd;V8BNXRF_rZK=2Mf5(N)^`yZ`>k7DA>!_6!e%J&THxGdp@ zht=N@b^Ob2s-x{y_dY`Jy8g{O;txoA&P`!X-ld(HP zTjZMRmLH|yr~ummvQ|o;fByQ7HOz(`uV=G1m+y5>0!E2CZA!yh`MNjCg`Wy(fx@sB zN`bs$S4^~Ht%^9LtYet4P5ZU*b47RTl@lY5Br`{gboLiVQjuSqdC|KWL4av%6Z_)r z{jC-O`=c+#SK=}GjW$uKCGsGF{?I*ZcPIl(dX8cQO|LugN|+d#UAHYDd;GpwiprdZ z9cQeXZL1g2Bx~+;i1~zDYYnK=y{RN9uri(U4`wbd-|2YDiu(u^mkV*FKdr;0y4Huvh@`=) zt$XS@hh(Ykt*g35@psiTtE8}+VZa0W#AxfY$QL^c`p)hK!|%og6`GRFx+#|Y2}4f; zzdtu}P$rgSrb=nVjpW-JYJ>H8#~$E690D<|y44?dKd-y?$%|Qd26tT@EtH^I%ii0J1aa7k|;p7bO z7^ys?xaRWhUE5pRTP5l>oI|Qj;yrjiMmK4>G#xF)p1|eHmb*e;9$DDm_a<=;{gf;g zuof;UAhw5Tj=y(tT{5Ek=C7r67m`y)b>lr;HF^!eWt2Yg*q)y_1IGM?j_0E5%ST3a%{IBs3GI7A7n01Pip!cOf2CC@oD6ZuKGh=>zjM#XW{&EzCcmqaWiXR{ zRMQUk&?Mcx+Yt(zC)#eif6m1)X@(&dem&&Z70l$d9?)6i6~w$bu500hA)omoXnfgv zAb-!6r6gfq*4Eo8iEkVU73aptOKrQvLTeuXsL_;%Uzr8{{imB*TaA+|-1eqs-O<{a z=-v%NvEc-5_hw=Aq}uNg&9rpI?_I!p%!i~B7!cHsi53elh{QH#Ms|YuA%RWVktT(l zd&=y?S|*ic^#RlISdDV<2y> +#include #include "DataDefs.h" #include "df/graphic.h" @@ -51,6 +53,8 @@ namespace DFHack { class Core; + typedef std::set interface_key_set; + /** * The Screen module * \ingroup grp_modules diff --git a/plugins/automaterial.cpp b/plugins/automaterial.cpp index ac5a4ae22..9f383b935 100644 --- a/plugins/automaterial.cpp +++ b/plugins/automaterial.cpp @@ -74,28 +74,6 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out ) return CR_OK; } - -void OutputString(int8_t color, int &x, int &y, const std::string &text, bool newline = false, int left_margin = 0) -{ - Screen::paintString(Screen::Pen(' ', color, 0), x, y, text); - if (newline) - { - ++y; - x = left_margin; - } - else - x += text.length(); -} - -void OutputHotkeyString(int &x, int &y, const char *text, const char *hotkey, bool newline = false, int left_margin = 0, int8_t color = COLOR_WHITE) -{ - OutputString(10, x, y, hotkey); - string display(": "); - display.append(text); - OutputString(color, x, y, display, newline, left_margin); -} - - static inline bool in_material_choice_stage() { return Gui::build_selector_hotkey(Core::getTopViewscreen()) && @@ -137,7 +115,7 @@ static inline MaterialDescriptor &get_last_used_material() return last_used_material[ui_build_selector->building_subtype]; } -static void set_last_used_material(MaterialDescriptor &matetial) +static void set_last_used_material(const MaterialDescriptor &matetial) { last_used_material[ui_build_selector->building_subtype] = matetial; } @@ -150,7 +128,7 @@ static MaterialDescriptor &get_last_moved_material() return last_moved_material[ui_build_selector->building_subtype]; } -static void set_last_moved_material(MaterialDescriptor &matetial) +static void set_last_moved_material(const MaterialDescriptor &matetial) { last_moved_material[ui_build_selector->building_subtype] = matetial; } @@ -306,9 +284,9 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest !in_material_choice_stage() && hotkeys.find(last_used_constr_subtype) != hotkeys.end()) { - input->clear(); - input->insert(hotkeys[last_used_constr_subtype]); - this->feed(input); + interface_key_set keys; + keys.insert(hotkeys[last_used_constr_subtype]); + INTERPOSE_NEXT(feed)(&keys); } } @@ -349,47 +327,42 @@ struct jobutils_hook : public df::viewscreen_dwarfmodest MaterialDescriptor material = get_material_in_list(ui_build_selector->sel_index); if (material.valid) { - int left_margin = gps->dimx - 30; - int x = left_margin; - int y = 25; - - string toggle_string = "Enable"; string title = "Disabled"; if (check_autoselect(material, false)) { - toggle_string = "Disable"; title = "Enabled"; } - OutputString(COLOR_BROWN, x, y, "DFHack Autoselect: " + title, true, left_margin); - OutputHotkeyString(x, y, toggle_string.c_str(), "a", true, left_margin); + auto dims = Gui::getDwarfmodeViewDims(); + Screen::Painter dc(dims.menu()); + + dc.seek(1,24).key_pen(COLOR_LIGHTRED).pen(COLOR_WHITE); + dc.key(interface_key::CUSTOM_A).string(": Autoselect "+title); } } - else if (in_placement_stage() && ui_build_selector->building_subtype != 7) + else if (in_placement_stage() && ui_build_selector->building_subtype < construction_type::TrackN) { - int left_margin = gps->dimx - 30; - int x = left_margin; - int y = 25; + string autoselect_toggle = (auto_choose_materials) ? "Disable" : "Enable"; + string revert_toggle = (revert_to_last_used_type) ? "Disable" : "Enable"; - string autoselect_toggle_string = (auto_choose_materials) ? "Disable Auto Mat-select" : "Enable Auto Mat-select"; - string revert_toggle_string = (revert_to_last_used_type) ? "Disable Auto Type-select" : "Enable Auto Type-select"; + auto dims = Gui::getDwarfmodeViewDims(); + Screen::Painter dc(dims.menu()); - OutputString(COLOR_BROWN, x, y, "DFHack Options", true, left_margin); - OutputHotkeyString(x, y, autoselect_toggle_string.c_str(), "a", true, left_margin); - OutputHotkeyString(x, y, revert_toggle_string.c_str(), "t", true, left_margin); + dc.seek(1,23).key_pen(COLOR_LIGHTRED).pen(COLOR_WHITE); + dc.key(interface_key::CUSTOM_A).string(": "+autoselect_toggle+" Auto Mat-Select").newline(1); + dc.key(interface_key::CUSTOM_T).string(": "+revert_toggle+" Auto Type-Select"); } } }; -color_ostream_proxy console_out(Core::getInstance().getConsole()); - - IMPLEMENT_VMETHOD_INTERPOSE(jobutils_hook, feed); IMPLEMENT_VMETHOD_INTERPOSE(jobutils_hook, render); DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) { - if (!gps || !INTERPOSE_HOOK(jobutils_hook, feed).apply() || !INTERPOSE_HOOK(jobutils_hook, render).apply()) + if (!gps || !ui_build_selector || + !INTERPOSE_HOOK(jobutils_hook, feed).apply() || + !INTERPOSE_HOOK(jobutils_hook, render).apply()) out.printerr("Could not insert jobutils hooks!\n"); hotkeys[construction_type::Wall] = df::interface_key::HOTKEY_BUILDING_CONSTRUCTION_WALL; From 2a0d04804068a3e63866fa128711a0d1c2add8b4 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 22 Nov 2012 20:08:47 +0400 Subject: [PATCH 10/35] Make tweak stable-cursor interact with the build menu properly. --- NEWS | 1 + plugins/tweak.cpp | 22 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 6ba9a769f..463ebb47a 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ DFHack future - added a small stand-alone utility for applying and removing binary patches. - removebadthoughts: add --dry-run option - superdwarf: work in adventure mode too + - tweak stable-cursor: carries cursor location from/to Build menu. New tweaks: - tweak military-training: speed up melee squad training up to 10x (normally 3-5x). New scripts: diff --git a/plugins/tweak.cpp b/plugins/tweak.cpp index 7143e715e..70d915ffc 100644 --- a/plugins/tweak.cpp +++ b/plugins/tweak.cpp @@ -212,15 +212,31 @@ struct stable_cursor_hook : df::viewscreen_dwarfmodest { typedef df::viewscreen_dwarfmodest interpose_base; + bool check_default() + { + switch (ui->main.mode) { + case ui_sidebar_mode::Default: + return true; + + case ui_sidebar_mode::Build: + return ui_build_selector && + (ui_build_selector->building_type < 0 || + ui_build_selector->stage < 1); + + default: + return false; + } + } + DEFINE_VMETHOD_INTERPOSE(void, feed, (set *input)) { - bool was_default = (ui->main.mode == df::ui_sidebar_mode::Default); + bool was_default = check_default(); df::coord view = Gui::getViewportPos(); df::coord cursor = Gui::getCursorPos(); INTERPOSE_NEXT(feed)(input); - bool is_default = (ui->main.mode == df::ui_sidebar_mode::Default); + bool is_default = check_default(); df::coord cur_cursor = Gui::getCursorPos(); if (is_default && !was_default) @@ -241,7 +257,7 @@ struct stable_cursor_hook : df::viewscreen_dwarfmodest tmp.insert(interface_key::CURSOR_UP_Z); INTERPOSE_NEXT(feed)(&tmp); } - else if (cur_cursor.isValid()) + else if (!is_default && cur_cursor.isValid()) { last_cursor = df::coord(); } From e3eb325d3680aa06b5fa0cde68da186345858e34 Mon Sep 17 00:00:00 2001 From: Quietust Date: Fri, 23 Nov 2012 19:18:56 -0600 Subject: [PATCH 11/35] Minimize references to gps->dimx/dimy --- library/modules/Screen.cpp | 45 ++++++++++++++------------ plugins/manipulator.cpp | 66 ++++++++++++++++++++------------------ plugins/search.cpp | 8 +++-- 3 files changed, 64 insertions(+), 55 deletions(-) diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index f2d1f2d5d..cd20bc25e 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -110,10 +110,10 @@ bool Screen::paintTile(const Pen &pen, int x, int y) { if (!gps || !pen.valid()) return false; - int dimx = gps->dimx, dimy = gps->dimy; - if (x < 0 || x >= dimx || y < 0 || y >= dimy) return false; + auto dim = getWindowSize(); + if (x < 0 || x >= dim.x || y < 0 || y >= dim.y) return false; - doSetTile(pen, x*dimy + y); + doSetTile(pen, x*dim.y + y); return true; } @@ -121,11 +121,11 @@ Pen Screen::readTile(int x, int y) { if (!gps) return Pen(0,0,0,-1); - int dimx = gps->dimx, dimy = gps->dimy; - if (x < 0 || x >= dimx || y < 0 || y >= dimy) + auto dim = getWindowSize(); + if (x < 0 || x >= dim.x || y < 0 || y >= dim.y) return Pen(0,0,0,-1); - int index = x*dimy + y; + int index = x*dim.y + y; auto screen = gps->screen + index*4; if (screen[3] & 0x80) return Pen(0,0,0,-1); @@ -154,14 +154,15 @@ Pen Screen::readTile(int x, int y) bool Screen::paintString(const Pen &pen, int x, int y, const std::string &text) { - if (!gps || y < 0 || y >= gps->dimy) return false; + auto dim = getWindowSize(); + if (!gps || y < 0 || y >= dim.y) return false; Pen tmp(pen); bool ok = false; for (size_t i = -std::min(0,x); i < text.size(); i++) { - if (x + i >= size_t(gps->dimx)) + if (x + i >= size_t(dim.x)) break; tmp.ch = text[i]; @@ -175,17 +176,18 @@ bool Screen::paintString(const Pen &pen, int x, int y, const std::string &text) bool Screen::fillRect(const Pen &pen, int x1, int y1, int x2, int y2) { + auto dim = getWindowSize(); if (!gps || !pen.valid()) return false; if (x1 < 0) x1 = 0; if (y1 < 0) y1 = 0; - if (x2 >= gps->dimx) x2 = gps->dimx-1; - if (y2 >= gps->dimy) y2 = gps->dimy-1; + if (x2 >= dim.x) x2 = dim.x-1; + if (y2 >= dim.y) y2 = dim.y-1; if (x1 > x2 || y1 > y2) return false; for (int x = x1; x <= x2; x++) { - int index = x*gps->dimy; + int index = x*dim.y; for (int y = y1; y <= y2; y++) doSetTile(pen, index+y); @@ -198,32 +200,33 @@ bool Screen::drawBorder(const std::string &title) { if (!gps) return false; - int dimx = gps->dimx, dimy = gps->dimy; + auto dim = getWindowSize(); Pen border('\xDB', 8); Pen text(0, 0, 7); Pen signature(0, 0, 8); - for (int x = 0; x < dimx; x++) + for (int x = 0; x < dim.x; x++) { - doSetTile(border, x * dimy + 0); - doSetTile(border, x * dimy + dimy - 1); + doSetTile(border, x * dim.y + 0); + doSetTile(border, x * dim.y + dim.y - 1); } - for (int y = 0; y < dimy; y++) + for (int y = 0; y < dim.y; y++) { - doSetTile(border, 0 * dimy + y); - doSetTile(border, (dimx - 1) * dimy + y); + doSetTile(border, 0 * dim.y + y); + doSetTile(border, (dim.x - 1) * dim.y + y); } - paintString(signature, dimx-8, dimy-1, "DFHack"); + paintString(signature, dim.x-8, dim.y-1, "DFHack"); - return paintString(text, (dimx - title.length()) / 2, 0, title); + return paintString(text, (dim.x - title.length()) / 2, 0, title); } bool Screen::clear() { if (!gps) return false; - return fillRect(Pen(' ',0,0,false), 0, 0, gps->dimx-1, gps->dimy-1); + auto dim = getWindowSize(); + return fillRect(Pen(' ',0,0,false), 0, 0, dim.x-1, dim.y-1); } bool Screen::invalidate() diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index 79999d468..59b257979 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -456,11 +456,13 @@ void viewscreen_unitlaborsst::refreshNames() void viewscreen_unitlaborsst::calcSize() { - num_rows = gps->dimy - 10; + auto dim = Screen::getWindowSize(); + + num_rows = dim.y - 10; if (num_rows > units.size()) num_rows = units.size(); - int num_columns = gps->dimx - DISP_COLUMN_MAX - 1; + int num_columns = dim.x - DISP_COLUMN_MAX - 1; // min/max width of columns int col_minwidth[DISP_COLUMN_MAX]; @@ -940,10 +942,11 @@ void viewscreen_unitlaborsst::render() dfhack_viewscreen::render(); + auto dim = Screen::getWindowSize(); + Screen::clear(); Screen::drawBorder(" Dwarf Manipulator - Manage Labors "); - Screen::paintString(Screen::Pen(' ', 7, 0), col_offsets[DISP_COLUMN_HAPPINESS], 2, "Hap."); Screen::paintString(Screen::Pen(' ', 7, 0), col_offsets[DISP_COLUMN_NAME], 2, "Name"); Screen::paintString(Screen::Pen(' ', 7, 0), col_offsets[DISP_COLUMN_PROFESSION], 2, "Profession"); @@ -1116,48 +1119,48 @@ void viewscreen_unitlaborsst::render() canToggle = (cur->allowEdit) && (columns[sel_column].labor != unit_labor::NONE); } - int x = 2; - OutputString(10, x, gps->dimy - 3, Screen::getKeyDisplay(interface_key::SELECT)); - OutputString(canToggle ? 15 : 8, x, gps->dimy - 3, ": Toggle labor, "); + int x = 2, y = dim.y - 3; + OutputString(10, x, dim.y - 3, Screen::getKeyDisplay(interface_key::SELECT)); + OutputString(canToggle ? 15 : 8, x, y, ": Toggle labor, "); - OutputString(10, x, gps->dimy - 3, Screen::getKeyDisplay(interface_key::SELECT_ALL)); - OutputString(canToggle ? 15 : 8, x, gps->dimy - 3, ": Toggle Group, "); + OutputString(10, x, dim.y - 3, Screen::getKeyDisplay(interface_key::SELECT_ALL)); + OutputString(canToggle ? 15 : 8, x, y, ": Toggle Group, "); - OutputString(10, x, gps->dimy - 3, Screen::getKeyDisplay(interface_key::UNITJOB_VIEW)); - OutputString(15, x, gps->dimy - 3, ": ViewCre, "); + OutputString(10, x, y, Screen::getKeyDisplay(interface_key::UNITJOB_VIEW)); + OutputString(15, x, y, ": ViewCre, "); - OutputString(10, x, gps->dimy - 3, Screen::getKeyDisplay(interface_key::UNITJOB_ZOOM_CRE)); - OutputString(15, x, gps->dimy - 3, ": Zoom-Cre"); + OutputString(10, x, y, Screen::getKeyDisplay(interface_key::UNITJOB_ZOOM_CRE)); + OutputString(15, x, y, ": Zoom-Cre"); - x = 2; - OutputString(10, x, gps->dimy - 2, Screen::getKeyDisplay(interface_key::LEAVESCREEN)); - OutputString(15, x, gps->dimy - 2, ": Done, "); + x = 2; y = dim.y - 2; + OutputString(10, x, y, Screen::getKeyDisplay(interface_key::LEAVESCREEN)); + OutputString(15, x, y, ": Done, "); - OutputString(10, x, gps->dimy - 2, Screen::getKeyDisplay(interface_key::SECONDSCROLL_DOWN)); - OutputString(10, x, gps->dimy - 2, Screen::getKeyDisplay(interface_key::SECONDSCROLL_UP)); - OutputString(15, x, gps->dimy - 2, ": Sort by Skill, "); + OutputString(10, x, y, Screen::getKeyDisplay(interface_key::SECONDSCROLL_DOWN)); + OutputString(10, x, y, Screen::getKeyDisplay(interface_key::SECONDSCROLL_UP)); + OutputString(15, x, y, ": Sort by Skill, "); - OutputString(10, x, gps->dimy - 2, Screen::getKeyDisplay(interface_key::SECONDSCROLL_PAGEDOWN)); - OutputString(10, x, gps->dimy - 2, Screen::getKeyDisplay(interface_key::SECONDSCROLL_PAGEUP)); - OutputString(15, x, gps->dimy - 2, ": Sort by ("); - OutputString(10, x, gps->dimy - 2, Screen::getKeyDisplay(interface_key::CHANGETAB)); - OutputString(15, x, gps->dimy - 2, ") "); + OutputString(10, x, y, Screen::getKeyDisplay(interface_key::SECONDSCROLL_PAGEDOWN)); + OutputString(10, x, y, Screen::getKeyDisplay(interface_key::SECONDSCROLL_PAGEUP)); + OutputString(15, x, y, ": Sort by ("); + OutputString(10, x, y, Screen::getKeyDisplay(interface_key::CHANGETAB)); + OutputString(15, x, y, ") "); switch (altsort) { case ALTSORT_NAME: - OutputString(15, x, gps->dimy - 2, "Name"); + OutputString(15, x, y, "Name"); break; case ALTSORT_PROFESSION: - OutputString(15, x, gps->dimy - 2, "Profession"); + OutputString(15, x, y, "Profession"); break; case ALTSORT_HAPPINESS: - OutputString(15, x, gps->dimy - 2, "Happiness"); + OutputString(15, x, y, "Happiness"); break; case ALTSORT_ARRIVAL: - OutputString(15, x, gps->dimy - 2, "Arrival"); + OutputString(15, x, y, "Arrival"); break; default: - OutputString(15, x, gps->dimy - 2, "Unknown"); + OutputString(15, x, y, "Unknown"); break; } } @@ -1193,9 +1196,10 @@ struct unitlist_hook : df::viewscreen_unitlistst if (units[page].size()) { - int x = 2; - OutputString(12, x, gps->dimy - 2, Screen::getKeyDisplay(interface_key::UNITVIEW_PRF_PROF)); - OutputString(15, x, gps->dimy - 2, ": Manage labors (DFHack)"); + auto dim = Screen::getWindowSize(); + int x = 2, y = dim.y - 2; + OutputString(12, x, y, Screen::getKeyDisplay(interface_key::UNITVIEW_PRF_PROF)); + OutputString(15, x, y, ": Manage labors (DFHack)"); } } }; diff --git a/plugins/search.cpp b/plugins/search.cpp index cc3f29c12..742fa9277 100644 --- a/plugins/search.cpp +++ b/plugins/search.cpp @@ -329,8 +329,9 @@ protected: // Display hotkey message void print_search_option(int x, int y = -1) const { + auto dim = Screen::getWindowSize(); if (y == -1) - y = gps->dimy - 2; + y = dim.y - 2; OutputString((entry_mode) ? 4 : 12, x, y, string(1, select_key)); OutputString((entry_mode) ? 10 : 15, x, y, ": Search"); @@ -413,8 +414,9 @@ public: print_search_option(2); else { - int x = 2; - OutputString(15, x, gps->dimy - 2, "Tab to enable Search"); + auto dim = Screen::getWindowSize(); + int x = 2, y = dim.y - 2; + OutputString(15, x, y, "Tab to enable Search"); } } From 139fd07df3e738fec33842d645fb1ac947679e61 Mon Sep 17 00:00:00 2001 From: Quietust Date: Fri, 23 Nov 2012 19:23:06 -0600 Subject: [PATCH 12/35] missed a spot --- plugins/manipulator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index 59b257979..e8a91fdb6 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -1120,10 +1120,10 @@ void viewscreen_unitlaborsst::render() } int x = 2, y = dim.y - 3; - OutputString(10, x, dim.y - 3, Screen::getKeyDisplay(interface_key::SELECT)); + OutputString(10, x, y, Screen::getKeyDisplay(interface_key::SELECT)); OutputString(canToggle ? 15 : 8, x, y, ": Toggle labor, "); - OutputString(10, x, dim.y - 3, Screen::getKeyDisplay(interface_key::SELECT_ALL)); + OutputString(10, x, y, Screen::getKeyDisplay(interface_key::SELECT_ALL)); OutputString(canToggle ? 15 : 8, x, y, ": Toggle Group, "); OutputString(10, x, y, Screen::getKeyDisplay(interface_key::UNITJOB_VIEW)); From 8429f651766566f697f36347faba23a98d987f72 Mon Sep 17 00:00:00 2001 From: jj Date: Thu, 22 Nov 2012 16:56:22 +0100 Subject: [PATCH 13/35] add scripts/stripcaged.rb and documentation --- NEWS | 1 + Readme.rst | 45 ++++++++++ scripts/stripcaged.rb | 194 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 240 insertions(+) create mode 100644 scripts/stripcaged.rb diff --git a/NEWS b/NEWS index 463ebb47a..65c647337 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,7 @@ DFHack future - dfusion: misc scripts with a text based menu. - embark: lets you embark anywhere. - lever: list and pull fort levers from the dfhack console. + - stripcaged: mark items inside cages for dumping, eg caged goblin weapons. New GUI scripts: - gui/guide-path: displays the cached path for minecart Guide orders. - gui/workshop-job: displays inputs of a workshop job and allows tweaking them. diff --git a/Readme.rst b/Readme.rst index e6554cac0..3434a240d 100644 --- a/Readme.rst +++ b/Readme.rst @@ -144,6 +144,16 @@ system console: The patches are expected to be encoded in text format used by IDA. + +Live patching +------------- + +As an alternative, you can use the ``binpatch`` dfhack command to apply/remove +patches live in memory during a DF session. + +In this case, updating symbols.xml is not necessary. + + ============================= Something doesn't work, help! ============================= @@ -1956,6 +1966,41 @@ embark ====== Allows to embark anywhere. Currently windows only. +lever +===== +Allow manipulation of in-game levers from the dfhack console. + +Can list levers, including state and links, with:: + + lever list + +To queue a job so that a dwarf will pull the lever 42, use ``lever pull 42``. +This is the same as 'q'uerying the building and queue a 'P'ull request. + +To magically toggle the lever immediately, use:: + + lever pull 42 --now + +stripcaged +========== +For dumping items inside cages. Will mark selected items for dumping, then +a dwarf may come and actually dump it. See also ``autodump``. + +With the ``items`` argument, only dumps items laying in the cage, excluding +stuff worn by caged creatures. ``weapons`` will dump worn weapons, ``armor`` +will dump everything worn by caged creatures (including armor and clothing), +and ``all`` will dump everything, on a creature or not. + +``stripcaged list`` will display on the dfhack console the list of all cages +and their item content. + +Without further arguments, all commands work on all cages and animal traps on +the map. With the ``here`` argument, considers only the in-game selected cage +(or the cage under the game cursor). To target only specific cages, you can +alternatively pass cage IDs as arguments:: + + stripcaged weapons 25321 34228 + ======================= In-game interface tools ======================= diff --git a/scripts/stripcaged.rb b/scripts/stripcaged.rb new file mode 100644 index 000000000..fa9c49552 --- /dev/null +++ b/scripts/stripcaged.rb @@ -0,0 +1,194 @@ +# mark stuff inside of cages for dumping. + +def plural(nr, name) + # '1 cage' / '4 cages' + "#{nr} #{name}#{'s' if nr > 1}" +end + +def cage_dump_items(list) + count = 0 + count_cage = 0 + list.each { |cage| + pre_count = count + cage.general_refs.each { |ref| + next unless ref.kind_of?(DFHack::GeneralRefContainsItemst) + next if ref.item_tg.flags.dump + count += 1 + ref.item_tg.flags.dump = true + } + count_cage += 1 if pre_count != count + } + + puts "Dumped #{plural(count, 'item')} in #{plural(count_cage, 'cage')}" +end + +def cage_dump_armor(list) + count = 0 + count_cage = 0 + list.each { |cage| + pre_count = count + cage.general_refs.each { |ref| + next unless ref.kind_of?(DFHack::GeneralRefContainsUnitst) + ref.unit_tg.inventory.each { |it| + next if it.mode != :Worn + next if it.item.flags.dump + count += 1 + it.item.flags.dump = true + } + } + count_cage += 1 if pre_count != count + } + + puts "Dumped #{plural(count, 'armor piece')} in #{plural(count_cage, 'cage')}" +end + +def cage_dump_weapons(list) + count = 0 + count_cage = 0 + list.each { |cage| + pre_count = count + cage.general_refs.each { |ref| + next unless ref.kind_of?(DFHack::GeneralRefContainsUnitst) + ref.unit_tg.inventory.each { |it| + next if it.mode != :Weapon + next if it.item.flags.dump + count += 1 + it.item.flags.dump = true + } + } + count_cage += 1 if pre_count != count + } + + puts "Dumped #{plural(count, 'weapon')} in #{plural(count_cage, 'cage')}" +end + +def cage_dump_all(list) + count = 0 + count_cage = 0 + list.each { |cage| + pre_count = count + cage.general_refs.each { |ref| + case ref + when DFHack::GeneralRefContainsItemst + next if ref.item_tg.flags.dump + count += 1 + ref.item_tg.flags.dump = true + when DFHack::GeneralRefContainsUnitst + ref.unit_tg.inventory.each { |it| + next if it.item.flags.dump + count += 1 + it.item.flags.dump = true + } + end + } + count_cage += 1 if pre_count != count + } + + puts "Dumped #{plural(count, 'item')} in #{plural(count_cage, 'cage')}" +end + + +def cage_dump_list(list) + count_total = Hash.new(0) + list.each { |cage| + count = Hash.new(0) + + cage.general_refs.each { |ref| + case ref + when DFHack::GeneralRefContainsItemst + count[ref.item_tg._rtti_classname] += 1 + when DFHack::GeneralRefContainsUnitst + ref.unit_tg.inventory.each { |it| + count[it.item._rtti_classname] += 1 + } + # TODO vermin ? + else + puts "unhandled ref #{ref.inspect}" if $DEBUG + end + } + + type = case cage + when DFHack::ItemCagest; 'Cage' + when DFHack::ItemAnimaltrapst; 'Animal trap' + else cage._rtti_classname + end + + puts "#{type} ##{cage.id}: ", count.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" } + + count.each { |k, v| count_total[k] += v } + } + + if list.length > 2 + puts '', "Total: ", count_total.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" } + end +end + + +# handle magic script arguments +here_only = $script_args.delete 'here' +if here_only + it = df.item_find + list = [it] + if not it.kind_of?(DFHack::ItemCagest) and not it.kind_of?(DFHack::ItemAnimaltrapst) + list = df.world.items.other[:ANY_CAGE_OR_TRAP].find_all { |i| df.at_cursor?(i) } + end + puts 'Please select a cage' if list.empty? + +elsif ids = $script_args.find_all { |arg| arg =~ /^\d+$/ } and ids.first + list = [] + ids.each { |id| + $script_args.delete id + if not it = df.item_find(id.to_i) + puts "Invalid item id #{id}" + elsif not it.kind_of?(DFHack::ItemCagest) and not it.kind_of?(DFHack::ItemAnimaltrapst) + puts "Item ##{id} is not a cage" + list << it + else + list << it + end + } + puts 'Please use a valid cage id' if list.empty? + +else + list = df.world.items.other[:ANY_CAGE_OR_TRAP] +end + + +# act +case $script_args[0] +when 'items' + cage_dump_items(list) if not list.empty? +when 'armor' + cage_dump_armor(list) if not list.empty? +when 'weapons' + cage_dump_weapons(list) if not list.empty? +when 'all' + cage_dump_all(list) if not list.empty? + +when 'list' + cage_dump_list(list) if not list.empty? + +else + puts < Date: Thu, 22 Nov 2012 17:42:10 +0100 Subject: [PATCH 14/35] scripts/lever: show pending jobs --- scripts/lever.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/lever.rb b/scripts/lever.rb index 2c7735146..59196f7d2 100644 --- a/scripts/lever.rb +++ b/scripts/lever.rb @@ -10,6 +10,8 @@ def lever_pull_job(bld) job.general_refs << ref bld.jobs << job df.job_link job + + puts lever_descr(bld) end def lever_pull_cheat(bld) @@ -31,6 +33,14 @@ def lever_descr(bld, idx=nil) descr = '' descr << "#{idx}: " if idx descr << "lever ##{bld.id} @[#{bld.centerx}, #{bld.centery}, #{bld.z}] #{bld.state == 0 ? '\\' : '/'}" + bld.jobs.each { |j| + if j.job_type == :PullLever + flags = '' + flags << ', repeat' if j.flags.repeat + flags << ', suspended' if j.flags.suspend + descr << " (pull order#{flags})" + end + } bld.linked_mechanisms.map { |i| i.general_refs.grep(DFHack::GeneralRefBuildingHolderst) From cb06c896984735c59a72570dd50f5dfc62bc40ab Mon Sep 17 00:00:00 2001 From: jj Date: Fri, 23 Nov 2012 17:20:16 +0100 Subject: [PATCH 15/35] stripcaged: dont list empty cages individually --- scripts/stripcaged.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/stripcaged.rb b/scripts/stripcaged.rb index fa9c49552..07694f711 100644 --- a/scripts/stripcaged.rb +++ b/scripts/stripcaged.rb @@ -90,6 +90,7 @@ end def cage_dump_list(list) count_total = Hash.new(0) + empty_cages = 0 list.each { |cage| count = Hash.new(0) @@ -113,13 +114,18 @@ def cage_dump_list(list) else cage._rtti_classname end - puts "#{type} ##{cage.id}: ", count.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" } + if count.empty? + empty_cages += 1 + else + puts "#{type} ##{cage.id}: ", count.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" } + end count.each { |k, v| count_total[k] += v } } if list.length > 2 puts '', "Total: ", count_total.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" } + puts "with #{plural(empty_cages, 'empty cage')}" end end From e73274d281e4f7f8b476a64a4854400dbb40c791 Mon Sep 17 00:00:00 2001 From: jj Date: Sat, 24 Nov 2012 16:05:03 +0100 Subject: [PATCH 16/35] ruby: add description field to onupdate_register --- plugins/ruby/README | 4 ++-- plugins/ruby/ruby.rb | 38 ++++++++++++++++++++------------------ scripts/autofarm.rb | 16 ++++++++-------- scripts/autounsuspend.rb | 6 +++--- scripts/magmasource.rb | 2 +- scripts/slayrace.rb | 2 +- scripts/superdwarf.rb | 4 ++-- 7 files changed, 37 insertions(+), 35 deletions(-) diff --git a/plugins/ruby/README b/plugins/ruby/README index 9246fec88..d35c34bbe 100644 --- a/plugins/ruby/README +++ b/plugins/ruby/README @@ -125,9 +125,9 @@ DFHack callbacks The plugin interfaces with dfhack 'onupdate' hook. To register ruby code to be run every graphic frame, use: - handle = df.onupdate_register { puts 'i love flooding the console' } + handle = df.onupdate_register('log') { puts 'i love flooding the console' } You can also rate-limit when your callback is called to a number of game ticks: - handle = df.onupdate_register(10) { puts '10 more in-game ticks elapsed' } + handle = df.onupdate_register('myname', 10) { puts '10 more in-game ticks elapsed' } In this case, the callback is called immediately, and then every X in-game ticks (advances only when the game is unpaused). To stop being called, use: diff --git a/plugins/ruby/ruby.rb b/plugins/ruby/ruby.rb index ab095e8d8..4fcb5543a 100644 --- a/plugins/ruby/ruby.rb +++ b/plugins/ruby/ruby.rb @@ -24,8 +24,9 @@ end module DFHack class OnupdateCallback - attr_accessor :callback, :timelimit, :minyear, :minyeartick - def initialize(cb, tl, initdelay=0) + attr_accessor :callback, :timelimit, :minyear, :minyeartick, :description + def initialize(descr, cb, tl, initdelay=0) + @description = descr @callback = cb @ticklimit = tl @minyear = (tl ? df.cur_year : 0) @@ -34,22 +35,21 @@ module DFHack # run callback if timedout def check_run(year, yeartick, yearlen) - if !@ticklimit - @callback.call - else - if year > @minyear or (year == @minyear and yeartick >= @minyeartick) - @minyear = year - @minyeartick = yeartick + @ticklimit - if @minyeartick > yearlen - @minyear += 1 - @minyeartick -= yearlen - end - @callback.call + if @ticklimit + return unless year > @minyear or (year == @minyear and yeartick >= @minyeartick) + @minyear = year + @minyeartick = yeartick + @ticklimit + if @minyeartick > yearlen + @minyear += 1 + @minyeartick -= yearlen end end + # t0 = Time.now + @callback.call + # dt = Time.now - t0 ; puts "rb cb #@description took #{'%.02f' % dt}s" if dt > 0.1 rescue df.onupdate_unregister self - puts_err "onupdate cb #$!", $!.backtrace + puts_err "onupdate #@description unregistered: #$!", $!.backtrace end def <=>(o) @@ -61,10 +61,11 @@ module DFHack attr_accessor :onupdate_list, :onstatechange_list # register a callback to be called every gframe or more - # ex: DFHack.onupdate_register { DFHack.world.units[0].counters.job_counter = 0 } - def onupdate_register(ticklimit=nil, initialtickdelay=0, &b) + # ex: DFHack.onupdate_register('fastdwarf') { DFHack.world.units[0].counters.job_counter = 0 } + def onupdate_register(descr, ticklimit=nil, initialtickdelay=0, &b) + raise ArgumentError, 'need a description as 1st arg' unless descr.kind_of?(::String) @onupdate_list ||= [] - @onupdate_list << OnupdateCallback.new(b, ticklimit, initialtickdelay) + @onupdate_list << OnupdateCallback.new(descr, b, ticklimit, initialtickdelay) DFHack.onupdate_active = true if onext = @onupdate_list.sort.first DFHack.onupdate_minyear = onext.minyear @@ -73,8 +74,9 @@ module DFHack @onupdate_list.last end - # delete the callback for onupdate ; use the value returned by onupdate_register + # delete the callback for onupdate ; use the value returned by onupdate_register or the description def onupdate_unregister(b) + b = @onupdate_list.find { |bb| bb.description == b } if b.kind_of?(String) @onupdate_list.delete b if @onupdate_list.empty? DFHack.onupdate_active = false diff --git a/scripts/autofarm.rb b/scripts/autofarm.rb index 098466745..c89cb9ff4 100644 --- a/scripts/autofarm.rb +++ b/scripts/autofarm.rb @@ -5,7 +5,7 @@ class AutoFarm @lastcounts = Hash.new(0) end - def setthreshold (id, v) + def setthreshold(id, v) if df.world.raws.plants.all.find { |r| r.id == id } @thresholds[id] = v.to_i else @@ -13,11 +13,11 @@ class AutoFarm end end - def setdefault (v) + def setdefault(v) @thresholds.default = v.to_i end - def is_plantable (plant) + def is_plantable(plant) season = df.cur_season harvest = df.cur_season_tick + plant.growdur * 10 will_finish = harvest < 10080 @@ -40,7 +40,7 @@ class AutoFarm return plantable end - def set_farms ( plants, farms) + def set_farms( plants, farms) return if farms.length == 0 if plants.length == 0 plants = [-1] @@ -66,7 +66,7 @@ class AutoFarm if (!i.flags.dump && !i.flags.forbid && !i.flags.garbage_collect && !i.flags.hostile && !i.flags.on_fire && !i.flags.rotten && !i.flags.trader && !i.flags.in_building && !i.flags.construction && - !i.flags.artifact1 && plantable.has_key? (i.mat_index)) + !i.flags.artifact1 && plantable.has_key?(i.mat_index)) counts[i.mat_index] = counts[i.mat_index] + i.stack_size end } @@ -95,13 +95,13 @@ class AutoFarm end } - set_farms (plants_s, farms_s) - set_farms (plants_u, farms_u) + set_farms(plants_s, farms_s) + set_farms(plants_u, farms_u) end def start - @onupdate = df.onupdate_register (100) { process } + @onupdate = df.onupdate_register('autofarm', 100) { process } @running = true end diff --git a/scripts/autounsuspend.rb b/scripts/autounsuspend.rb index 45dd8df4d..c7fe20748 100644 --- a/scripts/autounsuspend.rb +++ b/scripts/autounsuspend.rb @@ -26,7 +26,7 @@ class AutoUnsuspend end def start - @onupdate = df.onupdate_register (5) { process } + @onupdate = df.onupdate_register('autounsuspend', 5) { process } @running = true end @@ -36,7 +36,7 @@ class AutoUnsuspend end def status - stat = @running ? "Running." : "Loaded." + @running ? 'Running.' : 'Stopped.' end end @@ -53,6 +53,6 @@ else if $AutoUnsuspend puts $AutoUnsuspend.status else - puts "AI not started" + puts 'Not loaded.' end end diff --git a/scripts/magmasource.rb b/scripts/magmasource.rb index e97080834..c20199c2a 100644 --- a/scripts/magmasource.rb +++ b/scripts/magmasource.rb @@ -4,7 +4,7 @@ $magma_sources ||= [] case $script_args[0] when 'here' - $magma_onupdate ||= df.onupdate_register(12) { + $magma_onupdate ||= df.onupdate_register('magmasource', 12) { # called every 12 game ticks (100x a dwarf day) if $magma_sources.empty? df.onupdate_unregister($magma_onupdate) diff --git a/scripts/slayrace.rb b/scripts/slayrace.rb index 749d0189b..ca50020f7 100644 --- a/scripts/slayrace.rb +++ b/scripts/slayrace.rb @@ -21,7 +21,7 @@ slayit = lambda { |u| else # it's getting hot around here # !!WARNING!! do not call on a magma-safe creature - ouh = df.onupdate_register(1) { + ouh = df.onupdate_register("slayrace ensure #{u.id}", 1) { if u.flags1.dead df.onupdate_unregister(ouh) else diff --git a/scripts/superdwarf.rb b/scripts/superdwarf.rb index 6277db97f..eac9802fa 100644 --- a/scripts/superdwarf.rb +++ b/scripts/superdwarf.rb @@ -8,12 +8,12 @@ when 'add' if u = df.unit_find $superdwarf_ids |= [u.id] - if df.gamemode == :ADVENTURE + if df.gamemode == :ADVENTURE and not df.respond_to?(:cur_year_tick_advmode) onupdate_delay = nil else onupdate_delay = 1 end - $superdwarf_onupdate ||= df.onupdate_register(onupdate_delay) { + $superdwarf_onupdate ||= df.onupdate_register('superdwarf', onupdate_delay) { if $superdwarf_ids.empty? df.onupdate_unregister($superdwarf_onupdate) $superdwarf_onupdate = nil From 4dfe46e26f139167cc51ec689c19b3ba08747c0d Mon Sep 17 00:00:00 2001 From: jj Date: Sat, 24 Nov 2012 16:52:21 +0100 Subject: [PATCH 17/35] manipulator: fix column width calculations for 80x25 window --- plugins/manipulator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index e8a91fdb6..57c9390bb 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -469,10 +469,10 @@ void viewscreen_unitlaborsst::calcSize() int col_maxwidth[DISP_COLUMN_MAX]; col_minwidth[DISP_COLUMN_HAPPINESS] = 4; col_maxwidth[DISP_COLUMN_HAPPINESS] = 4; - col_minwidth[DISP_COLUMN_NAME] = 0; - col_maxwidth[DISP_COLUMN_NAME] = 0; - col_minwidth[DISP_COLUMN_PROFESSION] = 0; - col_maxwidth[DISP_COLUMN_PROFESSION] = 0; + col_minwidth[DISP_COLUMN_NAME] = 15; + col_maxwidth[DISP_COLUMN_NAME] = 15; // adjusted in the loop below + col_minwidth[DISP_COLUMN_PROFESSION] = 15; + col_maxwidth[DISP_COLUMN_PROFESSION] = 15; // adjusted in the loop below col_minwidth[DISP_COLUMN_LABORS] = num_columns*3/5; // 60% col_maxwidth[DISP_COLUMN_LABORS] = NUM_COLUMNS; From cdc44b74f2d8d353d0beab7e73bfa8bbf916151c Mon Sep 17 00:00:00 2001 From: Quietust Date: Sat, 24 Nov 2012 10:36:32 -0600 Subject: [PATCH 18/35] Fix possible crash when using shift+enter on cells that don't have labors --- plugins/manipulator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index 57c9390bb..d8b44f657 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -842,7 +842,7 @@ void viewscreen_unitlaborsst::feed(set *events) { df::unit *unit = cur->unit; const SkillColumn &col = columns[input_column]; - bool newstatus = !unit->status.labors[col.labor]; + bool newstatus = (col.labor == unit_labor::NONE) ? true : !unit->status.labors[col.labor]; for (int i = 0; i < NUM_COLUMNS; i++) { if (columns[i].group != col.group) From c58f30ba0095248512c3b1320de6869620794377 Mon Sep 17 00:00:00 2001 From: Quietust Date: Sat, 24 Nov 2012 10:37:22 -0600 Subject: [PATCH 19/35] Use teal background instead of red for no-labor cells --- plugins/manipulator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index d8b44f657..3e1a414ff 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -1060,7 +1060,7 @@ void viewscreen_unitlaborsst::render() } } else - bg = 4; + bg = 3; Screen::paintTile(Screen::Pen(c, fg, bg), col_offsets[DISP_COLUMN_LABORS] + col, 4 + row); } } From e9141f34f6dd9354a4eed0498aa72ff944cc1189 Mon Sep 17 00:00:00 2001 From: Quietust Date: Sat, 24 Nov 2012 11:13:54 -0600 Subject: [PATCH 20/35] Adjust minimum widths so they actually work at 80x25 without glitching out --- plugins/manipulator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index 3e1a414ff..88dc61726 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -469,10 +469,10 @@ void viewscreen_unitlaborsst::calcSize() int col_maxwidth[DISP_COLUMN_MAX]; col_minwidth[DISP_COLUMN_HAPPINESS] = 4; col_maxwidth[DISP_COLUMN_HAPPINESS] = 4; - col_minwidth[DISP_COLUMN_NAME] = 15; - col_maxwidth[DISP_COLUMN_NAME] = 15; // adjusted in the loop below - col_minwidth[DISP_COLUMN_PROFESSION] = 15; - col_maxwidth[DISP_COLUMN_PROFESSION] = 15; // adjusted in the loop below + col_minwidth[DISP_COLUMN_NAME] = 16; + col_maxwidth[DISP_COLUMN_NAME] = 16; // adjusted in the loop below + col_minwidth[DISP_COLUMN_PROFESSION] = 10; + col_maxwidth[DISP_COLUMN_PROFESSION] = 10; // adjusted in the loop below col_minwidth[DISP_COLUMN_LABORS] = num_columns*3/5; // 60% col_maxwidth[DISP_COLUMN_LABORS] = NUM_COLUMNS; From f091284a75b52b84dbe602d85345bae9bcfc2422 Mon Sep 17 00:00:00 2001 From: jj Date: Sun, 25 Nov 2012 17:29:03 +0100 Subject: [PATCH 21/35] ruby: avoid crash on ArgumentError in onupdate --- plugins/ruby/ruby.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ruby/ruby.rb b/plugins/ruby/ruby.rb index 4fcb5543a..b7f7590e9 100644 --- a/plugins/ruby/ruby.rb +++ b/plugins/ruby/ruby.rb @@ -47,7 +47,7 @@ module DFHack # t0 = Time.now @callback.call # dt = Time.now - t0 ; puts "rb cb #@description took #{'%.02f' % dt}s" if dt > 0.1 - rescue + rescue Exception df.onupdate_unregister self puts_err "onupdate #@description unregistered: #$!", $!.backtrace end From 76bb5f0196e5f57be0e7c3bdd4947c8bd6416fc3 Mon Sep 17 00:00:00 2001 From: jj Date: Mon, 26 Nov 2012 20:09:56 +0100 Subject: [PATCH 22/35] ruby: items in containers are free --- plugins/ruby/item.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ruby/item.rb b/plugins/ruby/item.rb index 469ec7449..0d65a707b 100644 --- a/plugins/ruby/item.rb +++ b/plugins/ruby/item.rb @@ -56,7 +56,7 @@ module DFHack def item_isfree(i) !i.flags.trader and !i.flags.in_job and - !i.flags.in_inventory and + (!i.flags.in_inventory or i.general_refs.grep(GeneralRefContainedInItemst).first) and !i.flags.removed and !i.flags.in_building and !i.flags.owned and From 536fd5546a8420340d0f6ca2fc8e5133bbda447b Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Tue, 27 Nov 2012 13:56:02 +0400 Subject: [PATCH 23/35] Update manipulator screenshots. --- Readme.html | 639 +++++++++++++++++++++------------------- Readme.rst | 8 +- images/manipulator.png | Bin 7373 -> 9024 bytes images/manipulator2.png | Bin 0 -> 8840 bytes 4 files changed, 348 insertions(+), 299 deletions(-) create mode 100644 images/manipulator2.png diff --git a/Readme.html b/Readme.html index 5b231b429..cdc4dd631 100644 --- a/Readme.html +++ b/Readme.html @@ -342,200 +342,205 @@ access DF memory and allow for easier development of new tools.

  • Using DFHack
  • -

    Something doesn't work, help!

    +

    Something doesn't work, help!

    First, don't panic :) Second, dfhack keeps a few log files in DF's folder - stderr.log and stdout.log. You can look at those and possibly find out what's happening. @@ -661,13 +672,13 @@ the issues tracker on github, contact me ( -

    The init file

    +

    The init file

    If your DF folder contains a file named dfhack.init, its contents will be run every time you start DF. This allows setting up keybindings. An example file is provided as dfhack.init-example - you can tweak it and rename to dfhack.init if you want to use this functionality.

    -

    Setting keybindings

    +

    Setting keybindings

    To set keybindings, use the built-in keybinding command. Like any other command it can be used at any time from the console, but it is also meaningful in the DFHack init file.

    @@ -712,7 +723,7 @@ for context foo/bar/baz, possible matches are
    -

    Commands

    +

    Commands

    DFHack command syntax consists of a command name, followed by arguments separated by whitespace. To include whitespace in an argument, quote it in double quotes. To include a double quote character, use \" inside double quotes.

    @@ -734,13 +745,13 @@ The following two command lines are exactly equivalent:

    to retrieve further help without having to look at this document. Alternatively, some accept a 'help'/'?' option on their command line.

    -

    Game progress

    +

    Game progress

    -

    die

    +

    die

    Instantly kills DF without saving.

    -

    forcepause

    +

    forcepause

    Forces DF to pause. This is useful when your FPS drops below 1 and you lose control of the game.

    @@ -751,12 +762,12 @@ control of the game.

    -

    nopause

    +

    nopause

    Disables pausing (both manual and automatic) with the exception of pause forced by 'reveal hell'. This is nice for digging under rivers.

    -

    fastdwarf

    +

    fastdwarf

    Controls speedydwarf and teledwarf. Speedydwarf makes dwarves move quickly and perform tasks quickly. Teledwarf makes dwarves move instantaneously, but do jobs at the same speed.

      @@ -773,29 +784,29 @@ that implements an even more aggressive version of speedydwarf.
    -

    Game interface

    +

    Game interface

    -

    follow

    +

    follow

    Makes the game view follow the currently highlighted unit after you exit from current menu/cursor mode. Handy for watching dwarves running around. Deactivated by moving the view manually.

    -

    tidlers

    +

    tidlers

    Toggle between all possible positions where the idlers count can be placed.

    -

    twaterlvl

    +

    twaterlvl

    Toggle between displaying/not displaying liquid depth as numbers.

    -

    copystock

    +

    copystock

    Copies the parameters of the currently highlighted stockpile to the custom stockpile settings and switches to custom stockpile placement mode, effectively allowing you to copy/paste stockpiles easily.

    -

    rename

    +

    rename

    Allows renaming various things.

    Options:

    @@ -829,9 +840,9 @@ siege engine or an activity zone.
    -

    Adventure mode

    +

    Adventure mode

    -

    adv-bodyswap

    +

    adv-bodyswap

    This allows taking control over your followers and other creatures in adventure mode. For example, you can make them pick up new arms and armor and equip them properly.

    @@ -844,7 +855,7 @@ properly.

    -

    advtools

    +

    advtools

    A package of different adventure mode tools (currently just one)

    Usage:

    @@ -867,9 +878,9 @@ on item type and being in shop.
    -

    Map modification

    +

    Map modification

    -

    changelayer

    +

    changelayer

    Changes material of the geology layer under cursor to the specified inorganic RAW material. Can have impact on all surrounding regions, not only your embark! By default changing stone to soil and vice versa is not allowed. By default @@ -944,7 +955,7 @@ You did save your game, right?

    -

    changevein

    +

    changevein

    Changes material of the vein under cursor to the specified inorganic RAW material. Only affects tiles within the current 16x16 block - for veins and large clusters, you will need to use this command multiple times.

    @@ -957,7 +968,7 @@ large clusters, you will need to use this command multiple times.

    -

    changeitem

    +

    changeitem

    Allows changing item material and base quality. By default the item currently selected in the UI will be changed (you can select items in the 'k' list or inside containers/inventory). By default change is only allowed if materials @@ -997,7 +1008,7 @@ crafters/haulers.

    -

    colonies

    +

    colonies

    Allows listing all the vermin colonies on the map and optionally turning them into honey bee colonies.

    Options:

    @@ -1012,12 +1023,12 @@ crafters/haulers.

    -

    deramp (by zilpin)

    +

    deramp (by zilpin)

    Removes all ramps designated for removal from the map. This is useful for replicating the old channel digging designation. It also removes any and all 'down ramps' that can remain after a cave-in (you don't have to designate anything for that to happen).

    -

    feature

    +

    feature

    Enables management of map features.

    • Discovering a magma feature (magma pool, volcano, magma sea, or curious @@ -1042,7 +1053,7 @@ that cavern to grow within your fortress.
    -

    liquids

    +

    liquids

    Allows adding magma, water and obsidian to the game. It replaces the normal dfhack command line and can't be used from a hotkey. Settings will be remembered as long as dfhack runs. Intended for use in combination with the command @@ -1055,13 +1066,13 @@ temperatures (creating heat traps). You've been warned.

    -

    liquids-here

    +

    liquids-here

    Run the liquid spawner with the current/last settings made in liquids (if no settings in liquids were made it paints a point of 7/7 magma by default).

    Intended to be used as keybinding. Requires an active in-game cursor.

    -

    tiletypes

    +

    tiletypes

    Can be used for painting map tiles and is an interactive command, much like liquids.

    The tool works with two set of options and a brush. The brush determines which @@ -1122,27 +1133,27 @@ up.

    For more details, see the 'help' command while using this.

    -

    tiletypes-commands

    +

    tiletypes-commands

    Runs tiletypes commands, separated by ;. This makes it possible to change tiletypes modes from a hotkey.

    -

    tiletypes-here

    +

    tiletypes-here

    Apply the current tiletypes options at the in-game cursor position, including the brush. Can be used from a hotkey.

    -

    tiletypes-here-point

    +

    tiletypes-here-point

    Apply the current tiletypes options at the in-game cursor position to a single tile. Can be used from a hotkey.

    -

    tubefill

    +

    tubefill

    Fills all the adamantine veins again. Veins that were empty will be filled in too, but might still trigger a demon invasion (this is a known bug).

    -

    extirpate

    +

    extirpate

    A tool for getting rid of trees and shrubs. By default, it only kills a tree/shrub under the cursor. The plants are turned into ashes instantly.

    Options:

    @@ -1162,20 +1173,20 @@ a tree/shrub under the cursor. The plants are turned into ashes instantly.

    -

    grow

    +

    grow

    Makes all saplings present on the map grow into trees (almost) instantly.

    -

    immolate

    +

    immolate

    Very similar to extirpate, but additionally sets the plants on fire. The fires can and will spread ;)

    -

    regrass

    +

    regrass

    Regrows grass. Not much to it ;)

    -

    weather

    +

    weather

    Prints the current weather map by default.

    Also lets you change the current weather to 'clear sky', 'rainy' or 'snowing'.

    Options:

    @@ -1196,9 +1207,9 @@ can and will spread ;)

    -

    Map inspection

    +

    Map inspection

    -

    cursecheck

    +

    cursecheck

    Checks a single map tile or the whole map/world for cursed creatures (ghosts, vampires, necromancers, werebeasts, zombies).

    With an active in-game cursor only the selected tile will be observed. @@ -1253,17 +1264,17 @@ of curses, for example.

    -

    flows

    +

    flows

    A tool for checking how many tiles contain flowing liquids. If you suspect that your magma sea leaks into HFS, you can use this tool to be sure without revealing the map.

    -

    probe

    +

    probe

    Can be used to determine tile properties like temperature.

    -

    prospect

    +

    prospect

    Prints a big list of all the present minerals and plants. By default, only the visible part of the map is scanned.

    Options:

    @@ -1282,7 +1293,7 @@ the visible part of the map is scanned.

    -

    Pre-embark estimate

    +

    Pre-embark estimate

    If prospect is called during the embark selection screen, it displays an estimate of layer stone availability.

    @@ -1307,7 +1318,7 @@ that is actually present.

    -

    reveal

    +

    reveal

    This reveals the map. By default, HFS will remain hidden so that the demons don't spawn. You can use 'reveal hell' to reveal everything. With hell revealed, you won't be able to unpause until you hide the map again. If you really want @@ -1316,34 +1327,34 @@ to unpause with hell revealed, use 'reveal demons'.

    you move. When you use it this way, you don't need to run 'unreveal'.

    -

    unreveal

    +

    unreveal

    Reverts the effects of 'reveal'.

    -

    revtoggle

    +

    revtoggle

    Switches between 'reveal' and 'unreveal'.

    -

    revflood

    +

    revflood

    This command will hide the whole map and then reveal all the tiles that have a path to the in-game cursor.

    -

    revforget

    +

    revforget

    When you use reveal, it saves information about what was/wasn't visible before revealing everything. Unreveal uses this information to hide things again. This command throws away the information. For example, use in cases where you abandoned with the fort revealed and no longer want the data.

    -

    showmood

    +

    showmood

    Shows all items needed for the currently active strange mood.

    -

    Designations

    +

    Designations

    -

    burrow

    +

    burrow

    Miscellaneous burrow control. Allows manipulating burrows and automated burrow expansion while digging.

    Options:

    @@ -1391,17 +1402,17 @@ Digging 1-wide corridors with the miner inside the burrow is SLOW.
    -

    digv

    +

    digv

    Designates a whole vein for digging. Requires an active in-game cursor placed over a vein tile. With the 'x' option, it will traverse z-levels (putting stairs between the same-material tiles).

    -

    digvx

    +

    digvx

    A permanent alias for 'digv x'.

    -

    digl

    +

    digl

    Designates layer stone for digging. Requires an active in-game cursor placed over a layer stone tile. With the 'x' option, it will traverse z-levels (putting stairs between the same-material tiles). With the 'undo' option it @@ -1409,11 +1420,11 @@ will remove the dig designation instead (if you realize that digging out a 50 z-level deep layer was not such a good idea after all).

    -

    diglx

    +

    diglx

    A permanent alias for 'digl x'.

    -

    digexp

    +

    digexp

    This command can be used for exploratory mining.

    See: http://df.magmawiki.com/index.php/DF2010:Exploratory_mining

    There are two variables that can be set: pattern and filter.

    @@ -1476,7 +1487,7 @@ z-level deep layer was not such a good idea after all).

    -

    digcircle

    +

    digcircle

    A command for easy designation of filled and hollow circles. It has several types of options.

    Shape:

    @@ -1539,7 +1550,7 @@ repeats with the last selected parameters.

    -

    digtype

    +

    digtype

    For every tile on the map of the same vein type as the selected tile, this command designates it to have the same designation as the selected tile. If the selected tile has no designation, they will be dig designated. If an argument is given, the designation of the selected tile is ignored, and all appropriate tiles are set to the specified designation.

    Options:

    @@ -1567,7 +1578,7 @@ If an argument is given, the designation of the selected tile is ignored, and al
    -

    filltraffic

    +

    filltraffic

    Set traffic designations using flood-fill starting at the cursor.

    Traffic Type Codes:

    @@ -1606,7 +1617,7 @@ If an argument is given, the designation of the selected tile is ignored, and al 'filltraffic H' - When used in a room with doors, it will set traffic to HIGH in just that room.
    -

    alltraffic

    +

    alltraffic

    Set traffic designations for every single tile of the map (useful for resetting traffic designations).

    Traffic Type Codes:

    @@ -1630,7 +1641,7 @@ If an argument is given, the designation of the selected tile is ignored, and al 'alltraffic N' - Set traffic to 'normal' for all tiles.
    -

    getplants

    +

    getplants

    This tool allows plant gathering and tree cutting by RAW ID. Specify the types of trees to cut down and/or shrubs to gather by their plant names, separated by spaces.

    @@ -1657,9 +1668,9 @@ all valid plant IDs will be listed.

    -

    Cleanup and garbage disposal

    +

    Cleanup and garbage disposal

    -

    clean

    +

    clean

    Cleans all the splatter that get scattered all over the map, items and creatures. In an old fortress, this can significantly reduce FPS lag. It can also spoil your !!FUN!!, so think before you use it.

    @@ -1693,12 +1704,12 @@ also spoil your !!FUN!!, so think before you use it.

    -

    spotclean

    +

    spotclean

    Works like 'clean map snow mud', but only for the tile under the cursor. Ideal if you want to keep that bloody entrance 'clean map' would clean up.

    -

    autodump

    +

    autodump

    This utility lets you quickly move all items designated to be dumped. Items are instantly moved to the cursor position, the dump flag is unset, and the forbid flag is set, as if it had been dumped normally. @@ -1725,17 +1736,17 @@ Be aware that any active dump item tasks still point at the item.

    -

    autodump-destroy-here

    +

    autodump-destroy-here

    Destroy items marked for dumping under cursor. Identical to autodump destroy-here, but intended for use as keybinding.

    -

    autodump-destroy-item

    +

    autodump-destroy-item

    Destroy the selected item. The item may be selected in the 'k' list, or inside a container. If called again before the game is resumed, cancels destroy.

    -

    cleanowned

    +

    cleanowned

    Confiscates items owned by dwarfs. By default, owned food on the floor and rotten items are confistacted and dumped.

    Options:

    @@ -1769,13 +1780,13 @@ worn items with 'X' damage and above.
    -

    Bugfixes

    +

    Bugfixes

    -

    drybuckets

    +

    drybuckets

    This utility removes water from all buckets in your fortress, allowing them to be safely used for making lye.

    -

    fixdiplomats

    +

    fixdiplomats

    Up to version 0.31.12, Elves only sent Diplomats to your fortress to propose tree cutting quotas due to a bug; once that bug was fixed, Elves stopped caring about excess tree cutting. This command adds a Diplomat position to all Elven @@ -1784,19 +1795,19 @@ to violate them and potentially start wars) in case you haven't already modified your raws accordingly.

    -

    fixmerchants

    +

    fixmerchants

    This command adds the Guild Representative position to all Human civilizations, allowing them to make trade agreements (just as they did back in 0.28.181.40d and earlier) in case you haven't already modified your raws accordingly.

    -

    fixveins

    +

    fixveins

    Removes invalid references to mineral inclusions and restores missing ones. Use this if you broke your embark with tools like tiletypes, or if you accidentally placed a construction on top of a valuable mineral floor.

    -

    tweak

    +

    tweak

    Contains various tweaks for minor bugs.

    One-shot subcommands:

    @@ -1902,7 +1913,7 @@ the units spar more.

    -

    fix-armory

    +

    fix-armory

    Enables a fix for storage of squad equipment in barracks.

    Specifically, it prevents your haulers from moving squad equipment to stockpiles, and instead queues jobs to store it on weapon racks, @@ -1956,9 +1967,9 @@ these rules is intended by Toady; the rest are invented by this plugin.

    -

    Mode switch and reclaim

    +

    Mode switch and reclaim

    -

    lair

    +

    lair

    This command allows you to mark the map as 'monster lair', preventing item scatter on abandon. When invoked as 'lair reset', it does the opposite.

    Unlike reveal, this command doesn't save the information about tiles - you @@ -1978,7 +1989,7 @@ won't be able to restore state of real monster lairs using 'lair reset'.

    -

    mode

    +

    mode

    This command lets you see and change the game mode directly. Not all combinations are good for every situation and most of them will produce undesirable results. There are a few good ones though.

    @@ -1998,9 +2009,9 @@ You just created a returnable mountain home and gained an adventurer.

    -

    Visualizer and data export

    +

    Visualizer and data export

    -

    ssense / stonesense

    +

    ssense / stonesense

    An isometric visualizer that runs in a second window. This requires working graphics acceleration and at least a dual core CPU (otherwise it will slow down DF).

    @@ -2013,19 +2024,19 @@ thread: http://df.magmawiki.com/index.php/Utility:Stonesense/Content_repository

    -

    mapexport

    +

    mapexport

    Export the current loaded map as a file. This will be eventually usable with visualizers.

    -

    dwarfexport

    +

    dwarfexport

    Export dwarves to RuneSmith-compatible XML.

    -

    Job management

    +

    Job management

    -

    job

    +

    job

    Command for general job query and manipulation.

    Options:
    @@ -2044,7 +2055,7 @@ in a workshop, or the unit/jobs screen.
    -

    job-material

    +

    job-material

    Alter the material of the selected job.

    Invoked as:

    @@ -2062,7 +2073,7 @@ over the first available choice with the matching material.
     
     
    -

    job-duplicate

    +

    job-duplicate

    Duplicate the selected job in a workshop:
      @@ -2073,7 +2084,7 @@ instantly duplicates the job.
    -

    workflow

    +

    workflow

    Manage control of repeat jobs.

    Usage:

    @@ -2105,7 +2116,7 @@ this list can be copied to a file, and then reloaded using the
    -

    Function

    +

    Function

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

    @@ -2118,7 +2129,7 @@ the frequency of jobs being toggled.

    in the game UI.

    -

    Constraint format

    +

    Constraint format

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

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

    -

    Constraint examples

    +

    Constraint examples

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

     workflow amount AMMO:ITEM_AMMO_BOLTS/METAL 1000 100
    @@ -2196,15 +2207,15 @@ workflow count CRAFTS///LOCAL,EXCEPTIONAL 100 90
     
    -

    Fortress activity management

    +

    Fortress activity management

    -

    seedwatch

    +

    seedwatch

    Tool for turning cooking of seeds and plants on/off depending on how much you have of them.

    See 'seedwatch help' for detailed description.

    -

    zone

    +

    zone

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

    Options:

    @@ -2303,7 +2314,7 @@ for war/hunt). Negatable.
    -

    Usage with single units

    +

    Usage with single units

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

    -

    Usage with filters

    +

    Usage with filters

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

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

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

    -

    Mass-renaming

    +

    Mass-renaming

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

    -

    Cage zones

    +

    Cage zones

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

    -

    Examples

    +

    Examples

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

    autonestbox

    +

    autonestbox

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

    -

    autobutcher

    +

    autobutcher

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

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

    -

    autolabor

    +

    autolabor

    Automatically manage dwarf labors.

    When enabled, autolabor periodically checks your dwarves and enables or disables labors. It tries to keep as many dwarves as possible busy but @@ -2525,14 +2536,14 @@ while it is enabled.

    -

    Other

    +

    Other

    -

    catsplosion

    +

    catsplosion

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

    -

    dfusion

    +

    dfusion

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

    -

    misery

    +

    misery

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

    Usage:

    @@ -2581,7 +2592,7 @@ twice.

    -

    Scripts

    +

    Scripts

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

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

    Some notable scripts:

    -

    fix/*

    +

    fix/*

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

    • fix/dead-units

      @@ -2616,12 +2627,12 @@ caused by autodump bugs or other hacking mishaps.

    -

    gui/*

    +

    gui/*

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

    -

    binpatch

    +

    binpatch

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

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

    -

    quicksave

    +

    quicksave

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

    -

    setfps

    +

    setfps

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

    -

    siren

    +

    siren

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

    -

    growcrops

    +

    growcrops

    Instantly grow seeds inside farming plots.

    With no argument, this command list the various seed types currently in use in your farming plots. @@ -2661,7 +2672,7 @@ growcrops plump 40

    -

    removebadthoughts

    +

    removebadthoughts

    This script remove negative thoughts from your dwarves. Very useful against tantrum spirals.

    The script can target a single creature, when used with the him argument, @@ -2675,7 +2686,7 @@ but in the short term your dwarves will get much more joyful.

    quickly after you unpause.

    -

    slayrace

    +

    slayrace

    Kills any unit of a given race.

    With no argument, lists the available races.

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

    @@ -2701,7 +2712,7 @@ slayrace elve magma
    -

    magmasource

    +

    magmasource

    Create an infinite magma source on a tile.

    This script registers a map tile as a magma source, and every 12 game ticks that tile receives 1 new unit of flowing magma.

    @@ -2716,7 +2727,7 @@ To remove all placed sources, call magmasource stop

    With no argument, this command shows an help message and list existing sources.

    -

    digfort

    +

    digfort

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

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

    @@ -2734,7 +2745,7 @@ To skip a row in your design, use a single ;.<

    The script takes the plan filename, starting from the root df folder.

    -

    superdwarf

    +

    superdwarf

    Similar to fastdwarf, per-creature.

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

    @@ -2744,16 +2755,16 @@ superdwarf add
     

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

    -

    drainaquifer

    +

    drainaquifer

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

    -

    deathcause

    +

    deathcause

    Focus a body part ingame, and this script will display the cause of death of the creature.

    -

    lua

    +

    lua

    There are the following ways to invoke this command:

    1. lua (without any parameters)

      @@ -2772,12 +2783,44 @@ directory. If the filename is not supplied, it loads "dfhack.lua".

    -

    embark

    +

    embark

    Allows to embark anywhere. Currently windows only.

    +
    +

    lever

    +

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

    +

    Can list levers, including state and links, with:

    +
    +lever list
    +
    +

    To queue a job so that a dwarf will pull the lever 42, use lever pull 42. +This is the same as 'q'uerying the building and queue a 'P'ull request.

    +

    To magically toggle the lever immediately, use:

    +
    +lever pull 42 --now
    +
    +
    +
    +

    stripcaged

    +

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

    +

    With the items argument, only dumps items laying in the cage, excluding +stuff worn by caged creatures. weapons will dump worn weapons, armor +will dump everything worn by caged creatures (including armor and clothing), +and all will dump everything, on a creature or not.

    +

    stripcaged list will display on the dfhack console the list of all cages +and their item content.

    +

    Without further arguments, all commands work on all cages and animal traps on +the map. With the here argument, considers only the in-game selected cage +(or the cage under the game cursor). To target only specific cages, you can +alternatively pass cage IDs as arguments:

    +
    +stripcaged weapons 25321 34228
    +
    +
    -

    In-game interface tools

    +

    In-game interface tools

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

    @@ -2790,7 +2833,7 @@ existing DF screens, they deliberately use red instead of green for the key.

    guideline because it arguably just fixes small usability bugs in the game UI.

    -

    Dwarf Manipulator

    +

    Dwarf Manipulator

    Implemented by the manipulator plugin. To activate, open the unit screen and press 'l'.

    images/manipulator.png @@ -2798,8 +2841,10 @@ press 'l'.

    far left column displays the unit's Happiness (color-coded based on its value), and the right half of the screen displays each dwarf's labor settings and skill levels (0-9 for Dabbling thru Professional, A-E for Great thru Grand -Master, and U-Z for Legendary thru Legendary+5). Cells with red backgrounds -denote skills not controlled by labors.

    +Master, and U-Z for Legendary thru Legendary+5).

    +

    Cells with teal backgrounds denote skills not controlled by labors, e.g. +military and social skills.

    +images/manipulator2.png

    Use the arrow keys or number pad to move the cursor around, holding Shift to move 10 tiles at a time.

    Press the Z-Up (<) and Z-Down (>) keys to move quickly between labor/skill @@ -2827,7 +2872,7 @@ cursor onto that cell instead of toggling it. directly to the main dwarf mode screen.

    -

    AutoMaterial

    +

    AutoMaterial

    The automaterial plugin makes building constructions (walls, floors, fortifications, etc) a little bit easier by saving you from having to trawl through long lists of materials each time you place one.

    @@ -2874,14 +2919,14 @@ materials, it returns you back to this screen. If you use this along with severa enabled materials, you should be able to place complex constructions more conveniently.

    -

    gui/liquids

    +

    gui/liquids

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

    images/liquids.png

    While active, use the suggested keys to switch the usual liquids parameters, and Enter to select the target area and apply changes.

    -

    gui/mechanisms

    +

    gui/mechanisms

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

    images/mechanisms.png

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

    -

    gui/rename

    +

    gui/rename

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

      @@ -2914,7 +2959,7 @@ their species string.

      unit profession change to Ctrl-Shift-T.

    -

    gui/room-list

    +

    gui/room-list

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

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

    list, and allows unassigning them.

    -

    gui/choose-weapons

    +

    gui/choose-weapons

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

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

    and may lead to inappropriate weapons being selected.

    -

    gui/guide-path

    +

    gui/guide-path

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

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

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

    -

    gui/workshop-job

    +

    gui/workshop-job

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

    images/workshop-job.png @@ -2977,7 +3022,7 @@ and then try to change the input item type, now it won't let you select plan you have to unset the material first.

    -

    gui/workflow

    +

    gui/workflow

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

    images/workflow.png @@ -3007,7 +3052,7 @@ suit your need, and set the item count range.

    If you don't need advanced settings, you can just press 'y' to confirm creation.

    -

    gui/assign-rack

    +

    gui/assign-rack

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

    images/assign-rack.png @@ -3032,7 +3077,7 @@ of currently assigned racks for every valid squad.

    -

    Behavior Mods

    +

    Behavior Mods

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

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

    -

    Siege Engine

    +

    Siege Engine

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

    -

    Rationale

    +

    Rationale

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

    -

    Configuration UI

    +

    Configuration UI

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

    @@ -3079,7 +3124,7 @@ menu.

    -

    Power Meter

    +

    Power Meter

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

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

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

    -

    Steam Engine

    +

    Steam Engine

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

    -

    Rationale

    +

    Rationale

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

    -

    Construction

    +

    Construction

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

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

    -

    Operation

    +

    Operation

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

    -

    Explosions

    +

    Explosions

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

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

    -

    Save files

    +

    Save files

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

    -

    Add Spatter

    +

    Add Spatter

    This plugin makes reactions with names starting with SPATTER_ADD_ produce contaminants on the items instead of improvements. The produced contaminants are immune to being washed away by water or destroyed by diff --git a/Readme.rst b/Readme.rst index 3434a240d..b9844debd 100644 --- a/Readme.rst +++ b/Readme.rst @@ -2032,8 +2032,12 @@ This tool implements a Dwarf Therapist-like interface within the game UI. The far left column displays the unit's Happiness (color-coded based on its value), and the right half of the screen displays each dwarf's labor settings and skill levels (0-9 for Dabbling thru Professional, A-E for Great thru Grand -Master, and U-Z for Legendary thru Legendary+5). Cells with red backgrounds -denote skills not controlled by labors. +Master, and U-Z for Legendary thru Legendary+5). + +Cells with teal backgrounds denote skills not controlled by labors, e.g. +military and social skills. + +.. image:: images/manipulator2.png Use the arrow keys or number pad to move the cursor around, holding Shift to move 10 tiles at a time. diff --git a/images/manipulator.png b/images/manipulator.png index 0a546034557fceb446aa0ccb8ddb51883fd71a84..44b603600b36d2954163982c2ad4aa37a36b12e6 100644 GIT binary patch literal 9024 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 diff --git a/images/manipulator2.png b/images/manipulator2.png new file mode 100644 index 0000000000000000000000000000000000000000..250b2f2ab7492a51efaefcac761811b3acef4089 GIT binary patch literal 8840 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 Date: Tue, 27 Nov 2012 11:55:53 -0600 Subject: [PATCH 24/35] Pack manipulator screenshots --- images/manipulator.png | Bin 9024 -> 7724 bytes images/manipulator2.png | Bin 8840 -> 7558 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/images/manipulator.png b/images/manipulator.png index 44b603600b36d2954163982c2ad4aa37a36b12e6..1f452549f9e0abc9998f298eb19a9a3650ee1ed5 100644 GIT binary patch literal 7724 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 POaWs<3w)LSmFWKgF`t0@ literal 8840 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 Date: Wed, 28 Nov 2012 13:33:07 +0100 Subject: [PATCH 25/35] ruby: add DFHack::VERSION --- plugins/ruby/ruby.cpp | 7 +++++++ plugins/ruby/ruby.rb | 2 ++ 2 files changed, 9 insertions(+) diff --git a/plugins/ruby/ruby.cpp b/plugins/ruby/ruby.cpp index 13190f70d..db94ad650 100644 --- a/plugins/ruby/ruby.cpp +++ b/plugins/ruby/ruby.cpp @@ -438,6 +438,12 @@ static VALUE rb_cDFHack; // DFHack module ruby methods, binds specific dfhack methods +// df-dfhack version (eg "0.34.11-r2") +static VALUE rb_dfversion(VALUE self) +{ + return rb_str_new(DFHACK_VERSION, strlen(DFHACK_VERSION)); +} + // enable/disable calls to DFHack.onupdate() static VALUE rb_dfonupdate_active(VALUE self) { @@ -955,6 +961,7 @@ static void ruby_bind_dfhack(void) { rb_define_singleton_method(rb_cDFHack, "malloc", RUBY_METHOD_FUNC(rb_dfmalloc), 1); rb_define_singleton_method(rb_cDFHack, "free", RUBY_METHOD_FUNC(rb_dffree), 1); rb_define_singleton_method(rb_cDFHack, "vmethod_do_call", RUBY_METHOD_FUNC(rb_dfvcall), 8); + rb_define_singleton_method(rb_cDFHack, "version", RUBY_METHOD_FUNC(rb_dfversion), 0); rb_define_singleton_method(rb_cDFHack, "memory_read", RUBY_METHOD_FUNC(rb_dfmemory_read), 2); rb_define_singleton_method(rb_cDFHack, "memory_read_int8", RUBY_METHOD_FUNC(rb_dfmemory_read_int8), 1); diff --git a/plugins/ruby/ruby.rb b/plugins/ruby/ruby.rb index b7f7590e9..27cde675a 100644 --- a/plugins/ruby/ruby.rb +++ b/plugins/ruby/ruby.rb @@ -23,6 +23,8 @@ module Kernel end module DFHack + VERSION = version + class OnupdateCallback attr_accessor :callback, :timelimit, :minyear, :minyeartick, :description def initialize(descr, cb, tl, initdelay=0) From 593dc4f55486b02a258953558db2054cd3607123 Mon Sep 17 00:00:00 2001 From: Anuradha Dissanayake Date: Sun, 25 Nov 2012 19:01:58 +1300 Subject: [PATCH 26/35] Fix handling of manipulator hotkey in unit search screen --- plugins/search.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/search.cpp b/plugins/search.cpp index 742fa9277..a14397fba 100644 --- a/plugins/search.cpp +++ b/plugins/search.cpp @@ -521,7 +521,8 @@ private: virtual bool should_check_input(set *input) { - if (input->count(interface_key::CURSOR_LEFT) || input->count(interface_key::CURSOR_RIGHT) || input->count(interface_key::CUSTOM_L)) + if (input->count(interface_key::CURSOR_LEFT) || input->count(interface_key::CURSOR_RIGHT) || + (!is_entry_mode() && input->count(interface_key::UNITVIEW_PRF_PROF))) { if (!is_entry_mode()) { From bfc11cf94636856a55d0a26ddcd139d41c3d11e1 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Wed, 28 Nov 2012 19:25:01 +0400 Subject: [PATCH 27/35] Add persistent history of per-constraint item counts in workflow. This will be needed for properly merging or integrating the status screen by falconne. The history is maintained as a circular buffer of up to 28 entries, and persists in save files. --- library/include/modules/World.h | 49 ++++++++++++++++ plugins/workflow.cpp | 101 +++++++++++++++++++++++++++++--- 2 files changed, 143 insertions(+), 7 deletions(-) diff --git a/library/include/modules/World.h b/library/include/modules/World.h index a945c4e72..f1fea52a1 100644 --- a/library/include/modules/World.h +++ b/library/include/modules/World.h @@ -81,6 +81,55 @@ namespace DFHack int &ival(int i) { return int_values[i]; } int ival(int i) const { return int_values[i]; } + // Pack binary data into string field. + // Since DF serialization chokes on NUL bytes, + // use bit magic to ensure none of the bytes is 0. + // Choose the lowest bit for padding so that + // sign-extend can be used normally. + + size_t data_size() const { return str_value->size(); } + + bool check_data(size_t off, size_t sz = 1) { + return (str_value->size() >= off+sz); + } + void ensure_data(size_t off, size_t sz = 0) { + if (str_value->size() < off+sz) str_value->resize(off+sz, '\x01'); + } + uint8_t *pdata(size_t off) { return (uint8_t*)&(*str_value)[off]; } + + static const size_t int7_size = 1; + uint8_t get_uint7(size_t off) { + uint8_t *p = pdata(off); + return p[0]>>1; + } + int8_t get_int7(size_t off) { + uint8_t *p = pdata(off); + return int8_t(p[0])>>1; + } + void set_uint7(size_t off, uint8_t val) { + uint8_t *p = pdata(off); + p[0] = uint8_t((val<<1) | 1); + } + void set_int7(size_t off, int8_t val) { set_uint7(off, val); } + + static const size_t int28_size = 4; + uint32_t get_uint28(size_t off) { + uint8_t *p = pdata(off); + return (p[0]>>1) | ((p[1]&~1U)<<6) | ((p[2]&~1U)<<13) | ((p[3]&~1U)<<20); + } + int32_t get_int28(size_t off) { + uint8_t *p = pdata(off); + return (p[0]>>1) | ((p[1]&~1U)<<6) | ((p[2]&~1U)<<13) | ((int8_t(p[3])&~1)<<20); + } + void set_uint28(size_t off, uint32_t val) { + uint8_t *p = pdata(off); + p[0] = uint8_t((val<<1) | 1); + p[1] = uint8_t((val>>6) | 1); + p[2] = uint8_t((val>>13) | 1); + p[3] = uint8_t((val>>20) | 1); + } + void set_int28(size_t off, int32_t val) { set_uint28(off, val); } + PersistentDataItem() : id(0), str_value(0), int_values(0) {} PersistentDataItem(int id, const std::string &key, std::string *sv, int *iv) : id(id), key_value(key), str_value(sv), int_values(iv) {} diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 6e15a4537..813326175 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -293,6 +293,7 @@ typedef std::map, bool> TMaterialCache; struct ItemConstraint { PersistentDataItem config; + PersistentDataItem history; // Fixed key parsed into fields bool is_craft; @@ -308,7 +309,7 @@ struct ItemConstraint { int weight; std::vector jobs; - int item_amount, item_count, item_inuse; + int item_amount, item_count, item_inuse_amount, item_inuse_count; bool request_suspend, request_resume; bool is_active, cant_resume_reported; @@ -318,7 +319,7 @@ struct ItemConstraint { public: ItemConstraint() : is_craft(false), min_quality(item_quality::Ordinary), is_local(false), - weight(0), item_amount(0), item_count(0), item_inuse(0), + weight(0), item_amount(0), item_count(0), item_inuse_amount(0), item_inuse_count(0), is_active(false), cant_resume_reported(false) {} @@ -352,6 +353,44 @@ public: request_resume = (size <= goalCount()-goalGap()); request_suspend = (size >= goalCount()); } + + static const size_t int28_size = PersistentDataItem::int28_size; + static const size_t hist_entry_size = PersistentDataItem::int28_size * 4; + + size_t history_size() { + return history.data_size() / hist_entry_size; + } + size_t history_base(int idx) { + size_t hsize = history_size(); + return ((history.ival(0)+hsize-idx) % hsize) * hist_entry_size; + } + int history_count(int idx) { + return history.get_int28(history_base(idx) + 0*int28_size); + } + int history_amount(int idx) { + return history.get_int28(history_base(idx) + 1*int28_size); + } + int history_inuse_count(int idx) { + return history.get_int28(history_base(idx) + 2*int28_size); + } + int history_inuse_amount(int idx) { + return history.get_int28(history_base(idx) + 3*int28_size); + } + + void updateHistory() + { + size_t buffer_size = history_size(); + if (buffer_size < 28) + history.ensure_data(hist_entry_size*buffer_size++, hist_entry_size); + history.ival(0) = (history.ival(0)+1) % buffer_size; + + size_t base = history.ival(0) * hist_entry_size; + + history.set_int28(base + 0*int28_size, item_count); + history.set_int28(base + 1*int28_size, item_amount); + history.set_int28(base + 2*int28_size, item_inuse_count); + history.set_int28(base + 3*int28_size, item_inuse_amount); + } }; /****************************** @@ -649,6 +688,9 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out) update_job_data(out); process_constraints(out); + + for (size_t i = 0; i < constraints.size(); i++) + constraints[i]->updateHistory(); } } @@ -659,6 +701,10 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out) * ITEM COUNT CONSTRAINT * ******************************/ +static std::string history_key(PersistentDataItem &config) { + return stl_sprintf("workflow/history/%d", config.entry_id()); +} + static ItemConstraint *get_constraint(color_ostream &out, const std::string &str, PersistentDataItem *cfg, bool create) { std::vector tokens; @@ -776,6 +822,8 @@ static ItemConstraint *get_constraint(color_ostream &out, const std::string &str nct->init(str); } + nct->history = World::GetPersistentData(history_key(nct->config), NULL); + constraints.push_back(nct); return nct; } @@ -787,6 +835,7 @@ static void delete_constraint(ItemConstraint *cv) vector_erase_at(constraints, idx); World::DeletePersistentData(cv->config); + World::DeletePersistentData(cv->history); delete cv; } @@ -1064,7 +1113,8 @@ static void map_job_items(color_ostream &out) { constraints[i]->item_amount = 0; constraints[i]->item_count = 0; - constraints[i]->item_inuse = 0; + constraints[i]->item_inuse_amount = 0; + constraints[i]->item_inuse_count = 0; } meltable_count = 0; @@ -1177,7 +1227,8 @@ static void map_job_items(color_ostream &out) isAssignedSquad(item)) { is_invalid = true; - cv->item_inuse++; + cv->item_inuse_count++; + cv->item_inuse_amount += item->getStackSize(); } else { @@ -1367,7 +1418,8 @@ static void push_constraint(lua_State *L, ItemConstraint *cv) Lua::SetField(L, cv->item_amount, ctable, "cur_amount"); Lua::SetField(L, cv->item_count, ctable, "cur_count"); - Lua::SetField(L, cv->item_inuse, ctable, "cur_in_use"); + Lua::SetField(L, cv->item_inuse_amount, ctable, "cur_in_use_amount"); + Lua::SetField(L, cv->item_inuse_count, ctable, "cur_in_use_count"); // Current state value @@ -1463,6 +1515,40 @@ static int setConstraint(lua_State *L) return 1; } +static int getCountHistory(lua_State *L) +{ + auto token = luaL_checkstring(L, 1); + + color_ostream &out = *Lua::GetOutput(L); + update_data_structures(out); + + ItemConstraint *icv = get_constraint(out, token, NULL, false); + + if (icv) + { + size_t hsize = icv->history_size(); + + lua_createtable(L, hsize, 0); + + for (int i = hsize-1; i >= 0; i--) + { + lua_createtable(L, 0, 4); + + Lua::SetField(L, icv->history_amount(i), -1, "cur_amount"); + Lua::SetField(L, icv->history_count(i), -1, "cur_count"); + Lua::SetField(L, icv->history_inuse_amount(i), -1, "cur_in_use_amount"); + Lua::SetField(L, icv->history_inuse_count(i), -1, "cur_in_use_count"); + + lua_rawseti(L, -2, hsize-i); // reverse order + } + } + else + lua_pushnil(L); + + return 1; +} + + DFHACK_PLUGIN_LUA_FUNCTIONS { DFHACK_LUA_FUNCTION(isEnabled), DFHACK_LUA_FUNCTION(setEnabled), @@ -1474,6 +1560,7 @@ DFHACK_PLUGIN_LUA_COMMANDS { DFHACK_LUA_COMMAND(listConstraints), DFHACK_LUA_COMMAND(findConstraint), DFHACK_LUA_COMMAND(setConstraint), + DFHACK_LUA_COMMAND(getCountHistory), DFHACK_LUA_END }; @@ -1521,10 +1608,10 @@ static void print_constraint(color_ostream &out, ItemConstraint *cv, bool no_job << cv->goalCount() << " (gap " << cv->goalGap() << ")" << endl; out.reset_color(); - if (cv->item_count || cv->item_inuse) + if (cv->item_count || cv->item_inuse_count) out << prefix << " items: amount " << cv->item_amount << "; " << cv->item_count << " stacks available, " - << cv->item_inuse << " in use." << endl; + << cv->item_inuse_count << " in use." << endl; if (no_job) return; From 614225cc5f62ea6ccb6743ae38a32cec5e6270f8 Mon Sep 17 00:00:00 2001 From: jj Date: Wed, 28 Nov 2012 19:46:56 +0100 Subject: [PATCH 28/35] follow rename itemst.flags.artifact1 -> artifact --- plugins/autodump.cpp | 4 ++-- plugins/autolabor.cpp | 2 +- plugins/devel/stockcheck.cpp | 2 +- plugins/workflow.cpp | 2 +- scripts/autofarm.rb | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index 5eb25964e..5b4804647 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -161,7 +161,7 @@ static command_result autodump_main(color_ostream &out, vector & parame || itm->flags.bits.in_building || itm->flags.bits.in_chest // || itm->flags.bits.in_inventory - || itm->flags.bits.artifact1 + || itm->flags.bits.artifact ) continue; @@ -271,7 +271,7 @@ command_result df_autodump_destroy_item(color_ostream &out, vector & pa if (item->flags.bits.construction || item->flags.bits.in_building || - item->flags.bits.artifact1) + item->flags.bits.artifact) { out.printerr("Choosing not to destroy buildings, constructions and artifacts.\n"); return CR_FAILURE; diff --git a/plugins/autolabor.cpp b/plugins/autolabor.cpp index 83718bd09..e5047b434 100644 --- a/plugins/autolabor.cpp +++ b/plugins/autolabor.cpp @@ -1556,7 +1556,7 @@ static int stockcheck(color_ostream &out, vector & parameters) #define F(x) bad_flags.bits.x = true; F(dump); F(forbid); F(garbage_collect); F(hostile); F(on_fire); F(rotten); F(trader); - F(in_building); F(construction); F(artifact1); + F(in_building); F(construction); F(artifact); F(spider_web); F(owned); F(in_job); #undef F diff --git a/plugins/devel/stockcheck.cpp b/plugins/devel/stockcheck.cpp index 666db0d79..679411b0e 100644 --- a/plugins/devel/stockcheck.cpp +++ b/plugins/devel/stockcheck.cpp @@ -144,7 +144,7 @@ static command_result stockcheck(color_ostream &out, vector & parameter #define F(x) bad_flags.bits.x = true; F(dump); F(forbid); F(garbage_collect); F(hostile); F(on_fire); F(rotten); F(trader); - F(in_building); F(construction); F(artifact1); + F(in_building); F(construction); F(artifact); F(spider_web); F(owned); F(in_job); #undef F diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 813326175..05fdca55b 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -1126,7 +1126,7 @@ static void map_job_items(color_ostream &out) #define F(x) bad_flags.bits.x = true; F(dump); F(forbid); F(garbage_collect); F(hostile); F(on_fire); F(rotten); F(trader); - F(in_building); F(construction); F(artifact1); + F(in_building); F(construction); F(artifact); #undef F bool dry_buckets = isOptionEnabled(CF_DRYBUCKETS); diff --git a/scripts/autofarm.rb b/scripts/autofarm.rb index c89cb9ff4..cd381089e 100644 --- a/scripts/autofarm.rb +++ b/scripts/autofarm.rb @@ -66,7 +66,7 @@ class AutoFarm if (!i.flags.dump && !i.flags.forbid && !i.flags.garbage_collect && !i.flags.hostile && !i.flags.on_fire && !i.flags.rotten && !i.flags.trader && !i.flags.in_building && !i.flags.construction && - !i.flags.artifact1 && plantable.has_key?(i.mat_index)) + !i.flags.artifact && plantable.has_key?(i.mat_index)) counts[i.mat_index] = counts[i.mat_index] + i.stack_size end } From 771a5ac50bfae154773a4b083277ec81ffa38148 Mon Sep 17 00:00:00 2001 From: jj Date: Wed, 28 Nov 2012 20:08:34 +0100 Subject: [PATCH 29/35] ruby: tweak flagarray#inspect --- plugins/ruby/ruby-autogen-defs.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb index c3203bd52..4148659a6 100644 --- a/plugins/ruby/ruby-autogen-defs.rb +++ b/plugins/ruby/ruby-autogen-defs.rb @@ -138,7 +138,6 @@ module DFHack @@inspecting = {} # avoid infinite recursion on mutually-referenced objects def inspect cn = self.class.name.sub(/^DFHack::/, '') - cn << ' @' << ('0x%X' % _memaddr) if cn != '' out = "#<#{cn}" return out << ' ...>' if @@inspecting[_memaddr] @@inspecting[_memaddr] = true @@ -655,6 +654,13 @@ module DFHack DFHack.memory_bitarray_set(@_memaddr, idx, v) end end + def inspect + out = "#' + end include Enumerable end From 94e669058604b8a129ff431164a987b951f15f0d Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 29 Nov 2012 13:37:16 +0400 Subject: [PATCH 30/35] Don't complain about fake input tokens in simulateInput. --- library/lua/gui.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/lua/gui.lua b/library/lua/gui.lua index cfb058f9d..2145cfad1 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -10,13 +10,19 @@ local to_pen = dfhack.pen.parse CLEAR_PEN = to_pen{ch=32,fg=0,bg=0} +local FAKE_INPUT_KEYS = { + _MOUSE_L = true, + _MOUSE_R = true, + _STRING = true, +} + function simulateInput(screen,...) local keys = {} local function push_key(arg) local kv = arg if type(arg) == 'string' then kv = df.interface_key[arg] - if kv == nil then + if kv == nil and not FAKE_INPUT_KEYS[arg] then error('Invalid keycode: '..arg) end end From 5ea26d9cae7ae43da8afdac905c7b3ab96f9991d Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Thu, 29 Nov 2012 16:27:51 +0400 Subject: [PATCH 31/35] Only show the advanced new constraint dialog on Shift-Enter. Upon reflection it is a bit too scary to be always shown. --- Lua API.html | 6 ++++++ Lua API.rst | 6 ++++++ Readme.html | 4 ++-- Readme.rst | 6 ++---- images/workflow-new1.png | Bin 5662 -> 6674 bytes library/lua/gui/dialogs.lua | 22 +++++++++++++++++++++- library/lua/gui/widgets.lua | 19 +++++++++++++++++++ scripts/gui/workflow.lua | 20 ++++++++++++-------- 8 files changed, 68 insertions(+), 15 deletions(-) diff --git a/Lua API.html b/Lua API.html index 04af5d672..f42905d01 100644 --- a/Lua API.html +++ b/Lua API.html @@ -2853,6 +2853,9 @@ this may be extended with mouse click support.

    + +
    on_submit:Enter key callback; if specified, the list reacts to the key and calls it as on_submit(index,choice).
    on_submit2:Shift-Enter key callback; if specified, the list reacts to the key +and calls it as on_submit2(index,choice).
    row_height:Height of every row in text lines.
    icon_width:If not nil, the specified number of character columns @@ -2908,6 +2911,9 @@ with the following fields:

  • list:submit()

    Call the on_submit callback, as if the Enter key was handled.

  • +
  • list:submit2()

    +

    Call the on_submit2 callback, as if the Shift-Enter key was handled.

    +
  • diff --git a/Lua API.rst b/Lua API.rst index 4087ff0aa..d42a348e4 100644 --- a/Lua API.rst +++ b/Lua API.rst @@ -2777,6 +2777,8 @@ It has the following attributes: :on_select: Selection change callback; called as ``on_select(index,choice)``. :on_submit: Enter key callback; if specified, the list reacts to the key and calls it as ``on_submit(index,choice)``. +:on_submit2: Shift-Enter key callback; if specified, the list reacts to the key + and calls it as ``on_submit2(index,choice)``. :row_height: Height of every row in text lines. :icon_width: If not *nil*, the specified number of character columns are reserved to the left of the list item for the icons. @@ -2826,6 +2828,10 @@ The list supports the following methods: Call the ``on_submit`` callback, as if the Enter key was handled. +* ``list:submit2()`` + + Call the ``on_submit2`` callback, as if the Shift-Enter key was handled. + FilteredList class ------------------ diff --git a/Readme.html b/Readme.html index cdc4dd631..deea72bef 100644 --- a/Readme.html +++ b/Readme.html @@ -3045,11 +3045,11 @@ the job material first using job as described in workflow documentation above. In this manner, this feature can be used for troubleshooting jobs that don't match the right constraints.

    images/workflow-new1.png -

    After selecting one of the presented outputs, the interface proceeds to the +

    If you select one of the outputs with Enter, the matching constraint is simply +added to the list. If you use Shift-Enter, the interface proceeds to the next dialog, which allows you to edit the suggested constraint parameters to suit your need, and set the item count range.

    images/workflow-new2.png -

    If you don't need advanced settings, you can just press 'y' to confirm creation.

    gui/assign-rack

    diff --git a/Readme.rst b/Readme.rst index b9844debd..a214a6ecb 100644 --- a/Readme.rst +++ b/Readme.rst @@ -2309,15 +2309,13 @@ can be used for troubleshooting jobs that don't match the right constraints. .. image:: images/workflow-new1.png -After selecting one of the presented outputs, the interface proceeds to the +If you select one of the outputs with Enter, the matching constraint is simply +added to the list. If you use Shift-Enter, the interface proceeds to the next dialog, which allows you to edit the suggested constraint parameters to suit your need, and set the item count range. .. image:: images/workflow-new2.png -If you don't need advanced settings, you can just press 'y' to confirm creation. - - gui/assign-rack =============== diff --git a/images/workflow-new1.png b/images/workflow-new1.png index 25b498bca23326f9e5ea05471dfcdb275f4e4734..50d0e1f421ac9de1abf87545c8d7ade31bd4cd4a 100644 GIT binary patch literal 6674 zcmZ{Jc{tQx^#5%3ZBl%)jwhT{eX7YqXNK4R8xaL85+2?P=nH!(J_yFI>~-}>N-#^^g1of~Tzep?V2 z_cNX+eNg{#4YaAJ=!08nCNCZCqufCE)X6MPuiHJ6hZdeqUR_*x_BCi_Rv-*>iXti7 zyH{)cn^$5<{@fkCqpo1{G~CH0V(Xh8rN=_ zT+5f^#h~}daJZjDXAKm7sO2WHxPKi|$jz=sx-|Py8$5R0_u%fY!~h9Mf>!&hYu{&@ z?x(QD)bB5RDMPvOmR5m}xlCJ>@F~CE&B6yN6gN&81uf_`?ZA1BYnzvilE%S)=CR2= z34(V6u4A%9Fz(wlC$v*56%O}NGz+cP+N3266tDt8gmaXqk60nrkh$Mp2BID@07+xU zdgD1&W5zKUg%$0zEJ+pn0hc_#5GQ-=MfayDiTphm*qMgw_|pC;b>E={ME+iVfC5r8 zitxb5rbO=rMi-pJ2d5RN{P=L?#N_NPDX)O1re&PAbnG*b89`_is^O zW}k^Di9PWw5qW~WYcum)2c>x0u3&<<=Yv8xE;$1U3o2Q^VrdRsREJwkcGsx^%OQki3X62%o#9ji zz>dxE`R|Y$k3;n-h>Fwju6T@s_SIHuE*`gzcN%e_jeKKB_KN*E`J+8gv?N}R#Wp3J z9PM~kQ@|j(0dmvK^oe@zf($RN9PjL3^4gA`D+71AGA4I9Hao^Dapw~X%mE2I+9<9z zrrRG|-#zWbuOS6qC}7AHlpjf&$B-2~8+aZj9Q1JXgt3IIs{F7K{BN|%((Z?Z$f0*1#PzR-y|DrV&HksW zTF(M}F%y}y_io!~wNMmIgj)C_dM0t#cGNRh{e+spQ?#03(C+Nbz0;tW08V-@inHe{ z^niYOICS$)8MN`wk{M{|kah6^`nDCvrCJ*NRahcv%6S12fu`8u*szK%F!X3>HE*r#xotb4|`W9@_*mtTOSB|S)p z%@pe;CIH8F2v}KJ#o?U+_{du?j>CJ);Yx@K@rMH$*0XV zL(xnaXJwLU>0>#ZOtdB&p&V%$oSG3hDUH1*e3~JfA*UD5ye<>N4nNGs#&&HlS^`Mk z#y*#_J`-nlVoeWI zhnwTR3dvTOME0zNTgmPp{%xKQf2m+bqdJWcDQZ==iuM?nZ#ip|Fm#g5l2_~O$?y3U zmF!%NtARKv<0$Tg99nK)JlUHrT%WC`2d_>JGJNa-)hy0_QzIXK%KsQzI*U4xLB+Nr zS!QTbOTP`u1&#y)JxZ_56_1}^95X}^uxU*>samQblptIy_}Id>#X$qo_+b$49wd=0 z_FHdf`V8E(;`ZJ^1TJgvjQBHF!|8BS7a$vjd%8R;!^Z#LL>S3w52{@QE22Np9D&K7 zD)}>euXgRqukTN{X)}s-b!#QI5QDL?fY1Un2VpKOzg?`AOACn3KlMa(SV^8fAf2$~ zn81MtQ)2Il&Ou;a@3cMZ=Zwq&E;76PDlog#2pELTMwA^DU-jBXT| zFp`JnDGw6*`ZOYE)6oE0nPEowg-ndy9;;Kf|* z$hDzSV-khui|v;qaL)RaVa7DYo}3rO-t+#oBA2XmCiM^TtSR;d8dzw8b<(6b3&B0x{EdXVEWI52WPE(Q#R9BIn7ET z9@c9R<)SP<%=LZHy@IJpq*^k?2#CuUu(8;DN4#5Ax0j^1<(r_zigctB zj3Y)zo`43vM&QDmSBi*CkYfaEcyBJka5p|&11+59)s)X6DUSYk@&TE#2*F2@rhL&4 zFSG0K`ZY)WD9gu7=+4n@FGHqte~+{Bi$YSxIsQusXthI9m6pP0W$g+^4_))1@SOS} zC_S<;sRe0B+mOn5FRf)f-|)b@?5#9d(->K7?8=o68T?kr4HtFF+63y(I9V}IS! zndSutI+wq?L>;|4SHYBN4v*FpKcpqle>iz}@3X)#T^x@JfSg92J2eYpkd8prf@a zve;U!&=8pW+k*BN%Hw9=gO8Tr-b?dK;n++-uWQbDqPUc|G)ba$QFirQ)U#Y=MlrB)=ump6z&JR20UOhsLSr~DX!Eo zwzInv_FUWP3&&vbH>lQX+=x}6W=MI9Zsjfh2P)T)#-h?*3O+zx)Fj&;rAo6!cv4R-{ZDgy>nds0B`x1I6($+(D`NFw>An-TtN$qzbFD~T)ANIH%m@KdRbgV-T}EV2RJK6;GD6ZNk5Pstv+Zlhi8{Tt zls6Wz^wTbY<6?IPG6c;?sq6Q`QCNO=dB5VPd)RvUp(6v?A@1HqM;^ZShiSyx9xr!8 zGwJ9`+Yw1zVMeB4na}GM`>Y_GuGxrYS$YOT7(+{1{ZpW^AKmw}U9+E`985`e^5{h0 z=zt%tXX{7r-g788%{_x^>G|cnq~^;AYD715JD}ZE`0aN|cxwH@-xsb&10???LH=uP zDnU7O+RKz#$W&{QszOO;TAJ(8UKKQK+kOAHks0tZ^d%<%;HtuWR{86YBCv(h_-+MHsB^qYfnO_L*V5z+O%SL(Lvr66>pn;D){a9w{5yUEhj6^-FtJfiZnke~K zx5X`5BI&f!i4U}tcV(j&+m@thvx$41YsaruyPuBFnAjtdBi$*R=f(~DJl;>XN3`@` zTM_y}bIi|Hw4~iAN2(s{lvl8M*J&7fh2~&B&&~biKBGxsKd8*-cI6LL*z2>v4wv}9 zW6a8Dc+4K2=M8F4^09bSmOk&p9SCGWAY4y#pa{2zSX7lm5uO9c^W~aC`_nn0i9*?# z5ybX7U!|*R+P5#=3S(X`|AvGprUm~dg)tB>Cyd^ZFuomijaSss24x1NG48e^bEE@J zvF&B=QW(d=_bIDq@v+}p%)*B?x32x5-4MHozc4cxSKk=Oa(}Xk za<3sv2B*yQ0pBL^aBH8Bs_65ogHH2tM?izLXG?_B!HF18oQctq&Wdex$s3U0CHYn9 ztDR=pgTY-XK=&W7H=p#K&&ulBaT9cSCi197Rq3ultn|tqoz|nN$E3611q+%AGn6U6 zXs@HID@7MJqS45)M3Nn{;G4dHl|BWZ0^kgQ8yjVNsZbM&S{y!&j1N5S&a}lTGB}*A zV)7OC;6)SKg)}NvmUl|9v#FJ7nbWAx2p|k6w@en2jf`MAtH-K}gfItMoE$w~Ab0(O ziMCE@>%5|gE<3RfNpF=&*yODAUjDMmju5Kmj`VOekE06w@Q9TNzxVrty; zk-%c!hcAcc+Z!(1eLtod2TsBG3q{ANi(n^&sZqxmjA3L9IBrdJku@hYTUMc)t0XV> zq~k{UMwv8@6|R(?eR+^WWSJQmK6sUh{1ZJ-eFnL^5^$0(mw`7RM3CTJhC|l2va2frbn*H2+-r8b=m{rfx{ zZ2VT@#rLz__iw%k7loYM(bL$C{j68Qc^1Ey6EHlnCVgm;q=EOG5ZbDQV&ph_B#9fM zWgnhz)R5;yiL0+KKvYD4{lyh#S_6d1BKCn2vi_qxMRoCvt(Z!fM z{NzNW@yzj!gOSlYM}O79Ilb`?=!f{Izok35MDt+=jaaSX!!_n54>Obl5a66+a2uf> zb5d=X6&GZE^YMwYR4&9~^F!i&HiThPHunrVwUBE;^Jsi3VRY?_?IGVAQ|uqb05euY zv4ChLlBgrJ@bexUN6e`Q*68kELnAMMImOcqXpyk_k;;DG-3!5&M22AeP03OY4oj{d#f7WRlTr{Q5oJ;veEvWP7t~bx}K!Gsa20Acc zIC2^X>fVsB7L;t;MM;9XZw-c`M@ASBdZ!CK1Z-eU`CELFo&=hn$G_0yeR=AF=95wT z%E~E-Yt?~X;kD93!>g27_1Rm;&hWlRGc!%zg|ZAOQ+y!5*Q9ySHup@?-=^d2dVTXfhGKmOPmZ(eEX{)MM&U!^yV5Q|{4kyh z3fWKZv@Y?fdLXOb+=1sd6s1P2)m~j@-CVU1o&RK*#n!#1bXqHfD}iz0S840!!;kEW zBwxsYuY^+4~bkfUP^fgA-y+5tw8+s>4US?%M=zh!$=8 z$f9oj7Fn%*hybpC6pimb7i^l}r)*<|j$<1TUFtY-5Cs*|fBQ%o?pYNF>wX+Du%*tc z{i*1LsW!;(nvVk~^%lK%jweQg7{lg+Yg6v5`~c!lGSa()5RZqbH1d725pw}jnyKP< zmyi3cpyd!AQQ+(AGp^$Dh#)4`VLe{1K+p>ub@^uS-hL)195V5 z)g)hzGw-Yr-UDLsroIMGh5LuoW0l@J7R7#s&hCIjJA13^tn&x{aiVyPcN_H?uYU?Y^!c z>FZz##?8gLm#tUX1$gaBlD0g46ViK@5*{2U*a2D=CLn8$(Z@-ntNNw8p?>PvFJ zX+4ZmL30XG&enTdB&&(-E*HvhT)%UAf8(ClVJ$3 zpY_gw@)}z2x;`%qKSa$^?wPXJp0n zKlFAT`auqF6A!|j1}!{#ewE8uZ+}L(SM@(2bi{a;76+wl3gT;7)*&Aj9R@%8dR9cL z%BDcO+dRI7UZO85^Im6zox)dG3?WW^zwsWeTFaMM19wwqB_C@^^pdE4{glU8Pb{IP zFJ+KH%WrxYk46!=fzuloJ);styD%4O;XIhtv{!{u>^Xh$CtHz|eYoOXa#4^(AX?-8 z)HL~!-#+TCgvM6*SpY^V@!?ifWInq8x7(Z(m}Vy|L?wEWX{?0E)J6mVg-9rmedD;h zFk{3|&cO)!DdKPtl_b6~FSDI38Gxf_Lk|HK`uA+-Ac#!6XNn@;C=u_od0)MKL@_C< zCKB9G1}hFtgW)9s>a4sdM^6j!7YrUyZDFV)0e47wfa|$XsLUgsS%!=W@ES0;$>GGX zqK%)nM9JB1(#!$c&&*!Cz#dfk$xztP)pTMBrPqmZ1a%z7&DI-KF~3hhQa8^#+{C-z z^wRPS@?sK@ijuO5g0ixLil&|NS*^3`T1uMoN@ul{l=h15j{dI!0oU<<-eLdufaD`B Q!oMj@&RZH+8M@v5A9!#IKL7v# literal 5662 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 X3+v6wDh=8C=tWR0Y|S5=xySw=1!(tQ diff --git a/library/lua/gui/dialogs.lua b/library/lua/gui/dialogs.lua index 0a79b4c3e..fb9b8fd63 100644 --- a/library/lua/gui/dialogs.lua +++ b/library/lua/gui/dialogs.lua @@ -152,7 +152,9 @@ ListBox.ATTRS{ with_filter = false, cursor_pen = DEFAULT_NIL, select_pen = DEFAULT_NIL, - on_select = DEFAULT_NIL + on_select = DEFAULT_NIL, + on_select2 = DEFAULT_NIL, + select2_hint = DEFAULT_NIL, } function ListBox:preinit(info) @@ -168,6 +170,16 @@ function ListBox:init(info) list_widget = widgets.FilteredList end + local on_submit2 + if self.select2_hint or self.on_select2 then + on_submit2 = function(sel, obj) + self:dismiss() + if self.on_select2 then self.on_select2(sel, obj) end + local cb = obj.on_select2 + if cb then cb(obj, sel) end + end + end + self:addviews{ list_widget{ view_id = 'list', @@ -182,11 +194,19 @@ function ListBox:init(info) local cb = obj.on_select or obj[2] if cb then cb(obj, sel) end end, + on_submit2 = on_submit2, frame = { l = 0, r = 0 }, } } end +function ListBox:onRenderFrame(dc,rect) + ListBox.super.onRenderFrame(self,dc,rect) + if self.select2_hint then + dc:seek(rect.x1+2,rect.y2):key('SEC_SELECT'):string(': '..self.select2_hint,COLOR_DARKGREY) + end +end + function ListBox:getWantedFrameSize() local mw, mh = InputBox.super.getWantedFrameSize(self) local list = self.subviews.list diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 67090e114..145300c59 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -384,6 +384,7 @@ List.ATTRS{ inactive_pen = DEFAULT_NIL, on_select = DEFAULT_NIL, on_submit = DEFAULT_NIL, + on_submit2 = DEFAULT_NIL, row_height = 1, scroll_keys = STANDARDSCROLL, icon_width = DEFAULT_NIL, @@ -542,10 +543,19 @@ function List:submit() end end +function List:submit2() + if self.on_submit2 and #self.choices > 0 then + self.on_submit2(self:getSelected()) + end +end + function List:onInput(keys) if self.on_submit and keys.SELECT then self:submit() return true + elseif self.on_submit2 and keys.SEC_SELECT then + self:submit2() + return true else for k,v in pairs(self.scroll_keys) do if keys[k] then @@ -608,6 +618,11 @@ function FilteredList:init(info) return info.on_submit(self:getSelected()) end end + if info.on_submit2 then + self.list.on_submit2 = function() + return info.on_submit2(self:getSelected()) + end + end self.not_found = Label{ visible = false, text = info.not_found_label or 'No matches', @@ -634,6 +649,10 @@ function FilteredList:submit() return self.list:submit() end +function FilteredList:submit2() + return self.list:submit2() +end + function FilteredList:canSubmit() return not self.not_found.visible end diff --git a/scripts/gui/workflow.lua b/scripts/gui/workflow.lua index 80c05d296..a387e64b9 100644 --- a/scripts/gui/workflow.lua +++ b/scripts/gui/workflow.lua @@ -552,18 +552,22 @@ function JobConstraints:onNewConstraint() table.insert(choices, { text = itemstr..' of '..matstr, obj = cons }) end - dlg.showListPrompt( - 'New limit', - 'Select one of the possible outputs:', - COLOR_WHITE, - choices, - function(idx,item) + dlg.ListBox{ + frame_title = 'New limit', + text = 'Select one of the possible outputs:', + text_pen = COLOR_WHITE, + choices = choices, + on_select = function(idx,item) + self:saveConstraint(item.obj) + end, + select2_hint = 'Advanced', + on_select2 = function(idx,item) NewConstraint{ constraint = item.obj, on_submit = self:callback('saveConstraint') }:show() - end - ) + end, + }:show() end function JobConstraints:onDeleteConstraint() From d7f7538d0148e8a731089034f431dfcd80c3a268 Mon Sep 17 00:00:00 2001 From: jj Date: Thu, 29 Nov 2012 10:33:18 +0100 Subject: [PATCH 32/35] ruby: fix Pointer assignment --- plugins/ruby/ruby-autogen-defs.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb index 4148659a6..a3e810178 100644 --- a/plugins/ruby/ruby-autogen-defs.rb +++ b/plugins/ruby/ruby-autogen-defs.rb @@ -308,7 +308,7 @@ module DFHack DFHack.memory_write_int32(@_memaddr, v) end when nil; DFHack.memory_write_int32(@_memaddr, 0) - else _get._set(v) + else @_tg._at(_getp)._set(v) end end From 184082b379c67989c55d5454cc3a204b40d71360 Mon Sep 17 00:00:00 2001 From: jj Date: Thu, 29 Nov 2012 17:11:16 +0100 Subject: [PATCH 33/35] scripts/lever: fix for links to cage/support --- scripts/lever.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/lever.rb b/scripts/lever.rb index 59196f7d2..43aa29b04 100644 --- a/scripts/lever.rb +++ b/scripts/lever.rb @@ -47,9 +47,12 @@ def lever_descr(bld, idx=nil) }.flatten.each { |r| # linked building description tg = r.building_tg - state = tg.gate_flags.closed ? 'closed' : 'opened' - state << ', closing' if tg.gate_flags.closing - state << ', opening' if tg.gate_flags.opening + state = '' + if tg.respond_to?(:gate_flags) + state << (tg.gate_flags.closed ? 'closed' : 'opened') + state << ", closing (#{tg.timer})" if tg.gate_flags.closing + state << ", opening (#{tg.timer})" if tg.gate_flags.opening + end ret << (descr + " linked to #{tg._rtti_classname} ##{tg.id} @[#{tg.centerx}, #{tg.centery}, #{tg.z}] #{state}") From 2cb594ba8990e062e7f353d38811b218f631866b Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Fri, 30 Nov 2012 14:48:05 +0400 Subject: [PATCH 34/35] Tweak the workflow lua api: include history in output of listConstraints. --- plugins/lua/workflow.lua | 3 +- plugins/workflow.cpp | 98 +++++++++++++++++++++++++--------------- 2 files changed, 63 insertions(+), 38 deletions(-) diff --git a/plugins/lua/workflow.lua b/plugins/lua/workflow.lua index 19ca0a84a..b3bcf3d08 100644 --- a/plugins/lua/workflow.lua +++ b/plugins/lua/workflow.lua @@ -8,10 +8,11 @@ local utils = require 'utils' * isEnabled() * setEnabled(enable) - * listConstraints([job]) -> {...} + * listConstraints([job[,with_history]]) -> {{...},...} * findConstraint(token) -> {...} or nil * setConstraint(token[, by_count, goal, gap]) -> {...} * deleteConstraint(token) -> true/false + * getCountHistory(token) -> {{...},...} or nil --]] diff --git a/plugins/workflow.cpp b/plugins/workflow.cpp index 05fdca55b..12174af5c 100644 --- a/plugins/workflow.cpp +++ b/plugins/workflow.cpp @@ -291,6 +291,15 @@ int ProtectedJob::cur_tick_idx = 0; typedef std::map, bool> TMaterialCache; +static const size_t MAX_HISTORY_SIZE = 28; + +enum HistoryItem { + HIST_COUNT = 0, + HIST_AMOUNT, + HIST_INUSE_COUNT, + HIST_INUSE_AMOUNT +}; + struct ItemConstraint { PersistentDataItem config; PersistentDataItem history; @@ -360,36 +369,29 @@ public: size_t history_size() { return history.data_size() / hist_entry_size; } - size_t history_base(int idx) { + int history_value(int idx, HistoryItem item) { size_t hsize = history_size(); - return ((history.ival(0)+hsize-idx) % hsize) * hist_entry_size; - } - int history_count(int idx) { - return history.get_int28(history_base(idx) + 0*int28_size); - } - int history_amount(int idx) { - return history.get_int28(history_base(idx) + 1*int28_size); - } - int history_inuse_count(int idx) { - return history.get_int28(history_base(idx) + 2*int28_size); - } - int history_inuse_amount(int idx) { - return history.get_int28(history_base(idx) + 3*int28_size); + size_t base = ((history.ival(0)+1+idx) % hsize) * hist_entry_size; + return history.get_int28(base + item*int28_size); } + int history_count(int idx) { return history_value(idx, HIST_COUNT); } + int history_amount(int idx) { return history_value(idx, HIST_AMOUNT); } + int history_inuse_count(int idx) { return history_value(idx, HIST_INUSE_COUNT); } + int history_inuse_amount(int idx) { return history_value(idx, HIST_INUSE_AMOUNT); } void updateHistory() { size_t buffer_size = history_size(); - if (buffer_size < 28) - history.ensure_data(hist_entry_size*buffer_size++, hist_entry_size); + if (buffer_size < MAX_HISTORY_SIZE && size_t(history.ival(0)+1) == buffer_size) + history.ensure_data(hist_entry_size*++buffer_size); history.ival(0) = (history.ival(0)+1) % buffer_size; size_t base = history.ival(0) * hist_entry_size; - history.set_int28(base + 0*int28_size, item_count); - history.set_int28(base + 1*int28_size, item_amount); - history.set_int28(base + 2*int28_size, item_inuse_count); - history.set_int28(base + 3*int28_size, item_inuse_amount); + history.set_int28(base + HIST_COUNT*int28_size, item_count); + history.set_int28(base + HIST_AMOUNT*int28_size, item_amount); + history.set_int28(base + HIST_INUSE_COUNT*int28_size, item_inuse_count); + history.set_int28(base + HIST_INUSE_AMOUNT*int28_size, item_inuse_amount); } }; @@ -1384,6 +1386,25 @@ static void setEnabled(color_ostream &out, bool enable) } } +static void push_count_history(lua_State *L, ItemConstraint *icv) +{ + size_t hsize = icv->history_size(); + + lua_createtable(L, hsize, 0); + + for (size_t i = 0; i < hsize; i++) + { + lua_createtable(L, 0, 4); + + Lua::SetField(L, icv->history_amount(i), -1, "cur_amount"); + Lua::SetField(L, icv->history_count(i), -1, "cur_count"); + Lua::SetField(L, icv->history_inuse_amount(i), -1, "cur_in_use_amount"); + Lua::SetField(L, icv->history_inuse_count(i), -1, "cur_in_use_count"); + + lua_rawseti(L, -2, i+1); + } +} + static void push_constraint(lua_State *L, ItemConstraint *cv) { lua_newtable(L); @@ -1430,19 +1451,31 @@ static void push_constraint(lua_State *L, ItemConstraint *cv) lua_newtable(L); + bool resumed = false, want_resumed = false; + for (size_t i = 0, j = 0; i < cv->jobs.size(); i++) { if (!cv->jobs[i]->isLive()) continue; Lua::PushDFObject(L, cv->jobs[i]->actual_job); lua_rawseti(L, -2, ++j); + + if (cv->jobs[i]->want_resumed) { + want_resumed = true; + resumed = resumed || cv->jobs[i]->isActuallyResumed(); + } } lua_setfield(L, ctable, "jobs"); + + if (want_resumed && !resumed) + Lua::SetField(L, true, ctable, "is_delayed"); } static int listConstraints(lua_State *L) { + lua_settop(L, 2); auto job = Lua::CheckDFObject(L, 1); + bool with_history = lua_toboolean(L, 2); lua_pushnil(L); @@ -1467,6 +1500,13 @@ static int listConstraints(lua_State *L) for (size_t i = 0; i < vec.size(); i++) { push_constraint(L, vec[i]); + + if (with_history) + { + push_count_history(L, vec[i]); + lua_setfield(L, -2, "history"); + } + lua_rawseti(L, -2, i+1); } @@ -1525,23 +1565,7 @@ static int getCountHistory(lua_State *L) ItemConstraint *icv = get_constraint(out, token, NULL, false); if (icv) - { - size_t hsize = icv->history_size(); - - lua_createtable(L, hsize, 0); - - for (int i = hsize-1; i >= 0; i--) - { - lua_createtable(L, 0, 4); - - Lua::SetField(L, icv->history_amount(i), -1, "cur_amount"); - Lua::SetField(L, icv->history_count(i), -1, "cur_count"); - Lua::SetField(L, icv->history_inuse_amount(i), -1, "cur_in_use_amount"); - Lua::SetField(L, icv->history_inuse_count(i), -1, "cur_in_use_count"); - - lua_rawseti(L, -2, hsize-i); // reverse order - } - } + push_count_history(L, icv); else lua_pushnil(L); From 0bfe006016d76206c9a05f4c8c0d5aede3dd748e Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Fri, 30 Nov 2012 19:10:17 +0400 Subject: [PATCH 35/35] Try to reimplement the inventory monitor by falconne in lua. For no other reason than to provide a complete example of lua interface for a native plugin :) TODO: paint the graph in the right pane. --- Lua API.rst | 11 + library/lua/gui.lua | 10 +- library/lua/gui/widgets.lua | 41 +++- scripts/gui/workflow.lua | 410 +++++++++++++++++++++++++++++++++--- 4 files changed, 430 insertions(+), 42 deletions(-) diff --git a/Lua API.rst b/Lua API.rst index d42a348e4..714a41bfb 100644 --- a/Lua API.rst +++ b/Lua API.rst @@ -2710,6 +2710,16 @@ containing newlines, or a table with the following possible fields: Specifies a pen to paint as one tile before the main part of the token. +* ``token.width = ...`` + + If specified either as a value or a callback, the text field is padded + or truncated to the specified number. + +* ``token.pad_char = '?'`` + + If specified together with ``width``, the padding area is filled with + this character instead of just being skipped over. + * ``token.key = '...'`` Specifies the keycode associated with the token. The string description @@ -2842,6 +2852,7 @@ In addition to passing through all attributes supported by List, it supports: :edit_pen: If specified, used instead of ``cursor_pen`` for the edit field. +:edit_below: If true, the edit field is placed below the list instead of above. :not_found_label: Specifies the text of the label shown when no items match the filter. The list choices may include the following attributes: diff --git a/library/lua/gui.lua b/library/lua/gui.lua index 2145cfad1..99bf9263c 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -112,10 +112,14 @@ function inset_frame(rect, inset, gap) return mkdims_xy(rect.x1+l+gap, rect.y1+t+gap, rect.x2-r-gap, rect.y2-b-gap) end -function compute_frame_body(wavail, havail, spec, inset, gap) +function compute_frame_body(wavail, havail, spec, inset, gap, inner_frame) gap = gap or 0 local l,t,r,b = parse_inset(inset) - local rect = compute_frame_rect(wavail, havail, spec, gap*2+l+r, gap*2+t+b) + local xgap,ygap = 0,0 + if inner_frame then + xgap,ygap = gap*2+l+r, gap*2+t+b + end + local rect = compute_frame_rect(wavail, havail, spec, xgap, ygap) local body = mkdims_xy(rect.x1+l+gap, rect.y1+t+gap, rect.x2-r-gap, rect.y2-b-gap) return rect, body end @@ -623,7 +627,7 @@ end function FramedScreen:computeFrame(parent_rect) local sw, sh = parent_rect.width, parent_rect.height local fw, fh = self:getWantedFrameSize(parent_rect) - return compute_frame_body(sw, sh, { w = fw, h = fh }, self.frame_inset, 1) + return compute_frame_body(sw, sh, { w = fw, h = fh }, self.frame_inset, 1, true) end function FramedScreen:onRenderFrame(dc, rect) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 145300c59..ebbffbbbd 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -60,6 +60,7 @@ Panel = defclass(Panel, Widget) Panel.ATTRS { on_render = DEFAULT_NIL, + on_layout = DEFAULT_NIL, } function Panel:init(args) @@ -70,6 +71,10 @@ function Panel:onRenderBody(dc) if self.on_render then self.on_render(dc) end end +function Panel:postComputeFrame(body) + if self.on_layout then self.on_layout(body) end +end + ----------- -- Pages -- ----------- @@ -242,7 +247,7 @@ function render_text(obj,dc,x0,y0,pen,dpen,disabled) end if token.text or token.key then - local text = getval(token.text) or '' + local text = ''..(getval(token.text) or '') local keypen if dc then @@ -256,7 +261,23 @@ function render_text(obj,dc,x0,y0,pen,dpen,disabled) end end - x = x + #text + local width = getval(token.width) + local padstr + if width then + x = x + width + if #text > width then + text = string.sub(text,1,width) + else + if token.pad_char then + padstr = string.rep(token.pad_char,width-#text) + end + if dc and token.rjustify then + if padstr then dc:string(padstr) else dc:advance(width-#text) end + end + end + else + x = x + #text + end if token.key then local keystr = gui.getKeyDisplay(token.key) @@ -281,6 +302,10 @@ function render_text(obj,dc,x0,y0,pen,dpen,disabled) dc:string(text) end end + + if width and dc and not token.rjustify then + if padstr then dc:string(padstr) else dc:advance(width-#text) end + end end token.x2 = x @@ -591,10 +616,14 @@ end FilteredList = defclass(FilteredList, Widget) +FilteredList.ATTRS { + edit_below = false, +} + function FilteredList:init(info) self.edit = EditField{ text_pen = info.edit_pen or info.cursor_pen, - frame = { l = info.icon_width, t = 0 }, + frame = { l = info.icon_width, t = 0, h = 1 }, on_change = self:callback('onFilterChange'), on_char = self:callback('onFilterChar'), } @@ -608,6 +637,10 @@ function FilteredList:init(info) scroll_keys = info.scroll_keys, icon_width = info.icon_width, } + if self.edit_below then + self.edit.frame = { l = info.icon_width, b = 0, h = 1 } + self.list.frame = { t = 0, b = 2 } + end if info.on_select then self.list.on_select = function() return info.on_select(self:getSelected()) @@ -627,7 +660,7 @@ function FilteredList:init(info) visible = false, text = info.not_found_label or 'No matches', text_pen = COLOR_LIGHTRED, - frame = { l = info.icon_width, t = 2 }, + frame = { l = info.icon_width, t = self.list.frame.t }, } self:addviews{ self.edit, self.list, self.not_found } self:setChoices(info.choices, info.selected) diff --git a/scripts/gui/workflow.lua b/scripts/gui/workflow.lua index a387e64b9..9a45f6554 100644 --- a/scripts/gui/workflow.lua +++ b/scripts/gui/workflow.lua @@ -66,20 +66,64 @@ function is_caste_mat(iobj) end function describe_material(iobj) - local matline = 'any material' + local matflags = utils.list_bitfield_flags(iobj.mat_mask) + if #matflags > 0 then + matflags = 'any '..table.concat(matflags, '/') + else + matflags = nil + end + if is_caste_mat(iobj) then - matline = 'no material' + return 'no material' elseif (iobj.mat_type or -1) >= 0 then local info = dfhack.matinfo.decode(iobj.mat_type, iobj.mat_index) + local matline if info then matline = info:toString() else matline = iobj.mat_type..':'..iobj.mat_index end + return matline, matflags + else + return matflags or 'any material' + end +end + +function current_stock(iobj) + if iobj.goal_by_count then + return iobj.cur_count + else + return iobj.cur_amount end - return matline end +function if_by_count(iobj,bc,ba) + if iobj.goal_by_count then + return bc + else + return ba + end +end + +function compute_trend(history,field) + local count = #history + if count == 0 then + return 0 + end + local sumX,sumY,sumXY,sumXX = 0,0,0,0 + for i,v in ipairs(history) do + sumX = sumX + i + sumY = sumY + v[field] + sumXY = sumXY + i*v[field] + sumXX = sumXX + i*i + end + return (count * sumXY - sumX * sumY) / (count * sumXX - sumX * sumX) +end + +------------------------ +-- RANGE EDITOR GROUP -- +------------------------ + local null_cons = { goal_value = 0, goal_gap = 0, goal_by_count = false } RangeEditor = defclass(RangeEditor, widgets.Label) @@ -162,6 +206,10 @@ function RangeEditor:onIncRange(field, delta) self.save_cb(cons) end +--------------------------- +-- NEW CONSTRAINT DIALOG -- +--------------------------- + NewConstraint = defclass(NewConstraint, gui.FramedScreen) NewConstraint.focus_path = 'workflow/new' @@ -177,7 +225,7 @@ NewConstraint.ATTRS { } function NewConstraint:init(args) - self.constraint = args.constraint or {} + self.constraint = args.constraint or { item_type = -1 } rawset_default(self.constraint, { goal_value = 10, goal_gap = 5, goal_by_count = false }) local matlist = {} @@ -202,8 +250,16 @@ function NewConstraint:init(args) frame = { l = 1, t = 2, w = 26 }, text = { 'Type: ', - { pen = COLOR_LIGHTCYAN, - text = function() return describe_item_type(self.constraint) end }, + { pen = function() + if self:isValid() then return COLOR_LIGHTCYAN else return COLOR_LIGHTRED end + end, + text = function() + if self:isValid() then + return describe_item_type(self.constraint) + else + return 'item not set' + end + end }, NEWLINE, ' ', { key = 'CUSTOM_T', text = ': Select, ', on_activate = self:callback('chooseType') }, @@ -277,6 +333,7 @@ function NewConstraint:init(args) { key = 'LEAVESCREEN', text = ': Cancel, ', on_activate = self:callback('dismiss') }, { key = 'MENU_CONFIRM', key_sep = ': ', + enabled = self:callback('isValid'), text = function() if self.is_existing then return 'Update' else return 'Create new' end end, @@ -295,9 +352,17 @@ function NewConstraint:postinit() self:onChange() end +function NewConstraint:isValid() + return self.constraint.item_type >= 0 +end + function NewConstraint:onChange() local token = workflow.constraintToToken(self.constraint) - local out = workflow.findConstraint(token) + local out + + if self:isValid() then + out = workflow.findConstraint(token) + end if out then self.constraint = out @@ -390,6 +455,288 @@ function NewConstraint:onRangeChange() cons.goal_gap = math.max(1, math.min(cons.goal_gap, cons.goal_value-1)) end +------------------------------ +-- GLOBAL CONSTRAINT SCREEN -- +------------------------------ + +ConstraintList = defclass(ConstraintList, gui.FramedScreen) + +ConstraintList.focus_path = 'workflow/list' + +ConstraintList.ATTRS { + frame_title = 'Workflow Status', + frame_inset = 0, + frame_background = COLOR_BLACK, + frame_style = gui.BOUNDARY_FRAME, +} + +function ConstraintList:init(args) + local fwidth_cb = self:cb_getfield('fwidth') + + self.fwidth = 20 + self.sort_by_severity = false + + self:addviews{ + widgets.Panel{ + frame = { w = 31, r = 0, h = 6, t = 0 }, + frame_inset = 1, + subviews = { + widgets.Label{ + frame = { l = 0, t = 0 }, + enabled = self:callback('isAnySelected'), + text = { + { text = function() + local cur = self:getCurConstraint() + if cur then + return string.format( + 'Currently %d (%d in use)', + current_stock(cur), + if_by_count(cur, cur.cur_in_use_count, cur.cur_in_use_amount) + ) + else + return 'No constraint selected' + end + end } + } + }, + RangeEditor{ + frame = { l = 0, t = 2 }, + enabled = self:callback('isAnySelected'), + get_cb = self:callback('getCurConstraint'), + save_cb = self:callback('saveConstraint'), + }, + } + }, + widgets.Widget{ + active = false, + frame = { w = 1, r = 31 }, + frame_background = gui.BOUNDARY_FRAME.frame_pen, + }, + widgets.Widget{ + active = false, + frame = { w = 31, r = 0, h = 1, t = 6 }, + frame_background = gui.BOUNDARY_FRAME.frame_pen, + }, + widgets.Panel{ + frame = { l = 0, r = 32 }, + frame_inset = 1, + on_layout = function(body) + self.fwidth = body.width - (12+1+1+7+1+1+1+7) + end, + subviews = { + widgets.Label{ + frame = { l = 0, t = 0 }, + text_pen = COLOR_CYAN, + text = { + { text = 'Item', width = 12 }, ' ', + { text = 'Material etc', width = fwidth_cb }, ' ', + { text = 'Stock / Limit' }, + } + }, + widgets.FilteredList{ + view_id = 'list', + frame = { t = 2, b = 2 }, + edit_below = true, + not_found_label = 'No matching constraints', + edit_pen = COLOR_LIGHTCYAN, + text_pen = { fg = COLOR_GREY, bg = COLOR_BLACK }, + cursor_pen = { fg = COLOR_WHITE, bg = COLOR_GREEN }, + }, + widgets.Label{ + frame = { b = 0, h = 1 }, + text = { + { key = 'CUSTOM_SHIFT_A', text = ': Add', + on_activate = self:callback('onNewConstraint') }, ', ', + { key = 'CUSTOM_SHIFT_X', text = ': Delete', + on_activate = self:callback('onDeleteConstraint') }, ', ', + { key = 'CUSTOM_SHIFT_O', text = ': Severity Order', + on_activate = self:callback('onSwitchSort'), + pen = function() + if self.sort_by_severity then + return COLOR_LIGHTCYAN + else + return COLOR_WHITE + end + end }, ', ', + { key = 'CUSTOM_SHIFT_S', text = ': Search', + on_activate = function() + self.subviews.list.edit.active = not self.subviews.list.edit.active + end, + pen = function() + if self.subviews.list.edit.active then + return COLOR_LIGHTCYAN + else + return COLOR_WHITE + end + end } + } + } + } + }, + } + + self.subviews.list.edit.active = false + + self:initListChoices() +end + +function stock_trend_color(cons) + local stock = current_stock(cons) + if stock >= cons.goal_value - cons.goal_gap then + return COLOR_LIGHTGREEN, 0 + elseif stock <= cons.goal_gap then + return COLOR_LIGHTRED, 4 + elseif stock >= cons.goal_value - 2*cons.goal_gap then + return COLOR_GREEN, 1 + elseif stock <= 2*cons.goal_gap then + return COLOR_RED, 3 + else + local trend = if_by_count(cons, cons.trend_count, cons.trend_amount) + if trend > 0.3 then + return COLOR_GREEN, 1 + elseif trend < -0.3 then + return COLOR_RED, 3 + else + return COLOR_GREY, 2 + end + end +end + +function ConstraintList:initListChoices(clist, sel_token) + clist = clist or workflow.listConstraints(nil, true) + + local fwidth_cb = self:cb_getfield('fwidth') + local choices = {} + + for i,cons in ipairs(clist) do + cons.trend_count = compute_trend(cons.history, 'cur_count') + cons.trend_amount = compute_trend(cons.history, 'cur_amount') + + local itemstr = describe_item_type(cons) + local matstr,matflagstr = describe_material(cons) + if matflagstr then + matstr = matflagstr .. ' ' .. matstr + end + + if cons.min_quality > 0 or cons.is_local then + local lst = {} + if cons.is_local then + table.insert(lst, 'local') + end + if cons.min_quality > 0 then + table.insert(lst, string.lower(df.item_quality[cons.min_quality])) + end + matstr = matstr .. ' ('..table.concat(lst,',')..')' + end + + local goal_color = COLOR_GREY + if #cons.jobs == 0 then + goal_color = COLOR_RED + elseif cons.is_delayed then + goal_color = COLOR_YELLOW + end + + table.insert(choices, { + text = { + { text = itemstr, width = 12, pad_char = ' ' }, ' ', + { text = matstr, width = fwidth_cb, pad_char = ' ' }, ' ', + { text = curry(current_stock,cons), width = 7, rjustify = true, + pen = function() return { fg = stock_trend_color(cons) } end }, + { text = curry(if_by_count,cons,'S','I'), gap = 1, + pen = { fg = COLOR_GREY } }, + { text = function() return cons.goal_value end, gap = 1, + pen = { fg = goal_color } } + }, + severity = select(2, stock_trend_color(cons)), + search_key = itemstr .. ' | ' .. matstr, + token = cons.token, + obj = cons + }) + end + + self:setChoices(choices, sel_token) +end + +function ConstraintList:isAnySelected() + return self.subviews.list:getSelected() ~= nil +end + +function ConstraintList:getCurConstraint() + local selidx,selobj = self.subviews.list:getSelected() + if selobj then return selobj.obj end +end + +function ConstraintList:onSwitchSort() + self.sort_by_severity = not self.sort_by_severity + self:setChoices(self.subviews.list:getChoices()) +end + +function ConstraintList:setChoices(choices, sel_token) + if self.sort_by_severity then + table.sort(choices, function(a,b) + return a.severity > b.severity + or (a.severity == b.severity and + current_stock(a.obj)/a.obj.goal_value < current_stock(b.obj)/b.obj.goal_value) + end) + else + table.sort(choices, function(a,b) return a.search_key < b.search_key end) + end + + local selidx = nil + if sel_token then + selidx = utils.linear_index(choices, sel_token, 'token') + end + + local list = self.subviews.list + local filter = list:getFilter() + + list:setChoices(choices, selidx) + + if filter ~= '' then + list:setFilter(filter, selidx) + + if selidx and list:getSelected() ~= selidx then + list:setFilter('', selidx) + end + end +end + +function ConstraintList:onInput(keys) + if keys.LEAVESCREEN then + self:dismiss() + else + ConstraintList.super.onInput(self, keys) + end +end + +function ConstraintList:onNewConstraint() + NewConstraint{ + on_submit = self:callback('saveConstraint') + }:show() +end + +function ConstraintList:saveConstraint(cons) + local out = workflow.setConstraint(cons.token, cons.goal_by_count, cons.goal_value, cons.goal_gap) + self:initListChoices(nil, out.token) +end + +function ConstraintList:onDeleteConstraint() + local cons = self:getCurConstraint() + dlg.showYesNoPrompt( + 'Delete Constraint', + 'Really delete the current constraint?', + COLOR_YELLOW, + function() + workflow.deleteConstraint(cons.token) + self:initListChoices() + end + ) +end + +------------------------------- +-- WORKSHOP JOB INFO OVERLAY -- +------------------------------- + JobConstraints = defclass(JobConstraints, guidm.MenuOverlay) JobConstraints.focus_path = 'workflow/job' @@ -480,24 +827,12 @@ function JobConstraints:initListChoices(clist, sel_token) end itemstr = itemstr .. ' ('..table.concat(lst,',')..')' end - local matstr = describe_material(cons) - local matflagstr = '' - local matflags = utils.list_bitfield_flags(cons.mat_mask) - if #matflags > 0 then - matflags[1] = 'any '..matflags[1] - if matstr == 'any material' then - matstr = table.concat(matflags, ', ') - matflags = {} - end - end - if #matflags > 0 then - matflagstr = table.concat(matflags, ', ') - end + local matstr,matflagstr = describe_material(cons) table.insert(choices, { text = { goal, ' ', { text = '(now '..curval..')', pen = order_pen }, NEWLINE, - ' ', itemstr, NEWLINE, ' ', matstr, NEWLINE, ' ', matflagstr + ' ', itemstr, NEWLINE, ' ', matstr, NEWLINE, ' ', (matflagstr or '') }, token = cons.token, obj = cons @@ -593,20 +928,25 @@ function JobConstraints:onInput(keys) end end -if not string.match(dfhack.gui.getCurFocus(), '^dwarfmode/QueryBuilding/Some/Workshop/Job') then - qerror("This script requires a workshop job selected in the 'q' mode") -end +local args = {...} -local job = dfhack.gui.getSelectedJob() +if args[1] == 'list' then + check_enabled(function() ConstraintList{}:show() end) +else + if not string.match(dfhack.gui.getCurFocus(), '^dwarfmode/QueryBuilding/Some/Workshop/Job') then + qerror("This script requires a workshop job selected in the 'q' mode") + end -check_enabled(function() - check_repeat(job, function() - local clist = workflow.listConstraints(job) - if not clist then - dlg.showMessage('Not Supported', 'This type of job is not supported by workflow.', COLOR_LIGHTRED) - return - end - JobConstraints{ job = job, clist = clist }:show() - end) -end) + local job = dfhack.gui.getSelectedJob() + check_enabled(function() + check_repeat(job, function() + local clist = workflow.listConstraints(job) + if not clist then + dlg.showMessage('Not Supported', 'This type of job is not supported by workflow.', COLOR_LIGHTRED) + return + end + JobConstraints{ job = job, clist = clist }:show() + end) + end) +end