From 0f5802af9f0487452599523b202b34f4617500e5 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sun, 18 May 2014 11:51:49 -0400 Subject: [PATCH 01/36] Add embark-tools A collection of embark-related tools (currently implementations of embark anywhere and nano embark) --- Readme.rst | 13 ++ plugins/CMakeLists.txt | 1 + plugins/embark-tools.cpp | 317 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 331 insertions(+) create mode 100644 plugins/embark-tools.cpp diff --git a/Readme.rst b/Readme.rst index 7491c4a0c..b2d98b599 100644 --- a/Readme.rst +++ b/Readme.rst @@ -2030,6 +2030,19 @@ See the bay12 thread for details: http://www.bay12forums.com/smf/index.php?topic * Some of the DFusion plugins aren't completely ported yet. This can lead to crashes. * The game will be suspended while you're using dfusion. Don't panic when it doesn't respond. +embark-tools +------------ +A collection of tools for embarking. + +Usage:: + + embark-tools enable/disable tool [tool]... + +Tools: + +* ``anywhere``: Allows embarking anywhere (including sites, mountain-only biomes, and oceans). Use with caution. +* ``nano``: An implementation of nano embark - allows resizing below 2x2 when enabled. + misery ------ When enabled, every new negative dwarven thought will be multiplied by a factor (2 by default). diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 650fe1e98..a73651608 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -165,6 +165,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(strangemood strangemood.cpp) DFHACK_PLUGIN(command-prompt command-prompt.cpp) DFHACK_PLUGIN(building-hacks building-hacks.cpp LINK_LIBRARIES lua) + DFHACK_PLUGIN(embark-tools embark-tools.cpp) endif() # this is the skeleton plugin. If you want to make your own, make a copy and then change it diff --git a/plugins/embark-tools.cpp b/plugins/embark-tools.cpp new file mode 100644 index 000000000..1a02e3e65 --- /dev/null +++ b/plugins/embark-tools.cpp @@ -0,0 +1,317 @@ +#include "Console.h" +#include "Core.h" +#include "DataDefs.h" +#include "Export.h" +#include "PluginManager.h" + +#include "modules/Screen.h" +#include "modules/Gui.h" +#include +#include + +#include +#include "ColorText.h" +#include "df/viewscreen_choose_start_sitest.h" +#include "df/interface_key.h" + +using namespace DFHack; + +struct EmbarkTool +{ + std::string id; + std::string name; + std::string desc; + bool enabled; +}; + +EmbarkTool embark_tools[] = { + {"anywhere", "Embark anywhere", "Allows embarking anywhere on the world map", false}, + {"nano", "Nano embark", "Allows the embark size to be decreased below 2x2", false}, +}; +#define NUM_TOOLS sizeof(embark_tools) / sizeof(EmbarkTool) + +command_result embark_tools_cmd (color_ostream &out, std::vector & parameters); + +bool tool_exists (std::string tool_name); +bool tool_enabled (std::string tool_name); +bool tool_enable (std::string tool_name, bool enable_state); + +/* + * Logic + */ + +void resize_embark (df::viewscreen_choose_start_sitest * screen, int dx, int dy) +{ + /* Reproduces DF's embark resizing functionality + * Local area resizes up and to the right, unless it's already touching the edge + */ + int x1 = screen->embark_pos_min.x, + x2 = screen->embark_pos_max.x, + y1 = screen->embark_pos_min.y, + y2 = screen->embark_pos_max.y, + width = x2 - x1 + dx, + height = y2 - y1 + dy; + if (x1 == x2 && dx == -1) + dx = 0; + if (y1 == y2 && dy == -1) + dy = 0; + + x2 += dx; // Resize right + while (x2 > 15) + { + x2--; + x1--; + } + x1 = std::max(0, x1); + + y1 -= dy; // Resize up + while (y1 < 0) + { + y1++; + y2++; + } + y2 = std::min(15, y2); + + screen->embark_pos_min.x = x1; + screen->embark_pos_max.x = x2; + screen->embark_pos_min.y = y1; + screen->embark_pos_max.y = y2; +} + +/* + * Viewscreen hooks + */ + +void OutputString (int8_t color, int &x, int y, const std::string &text) +{ + Screen::paintString(Screen::Pen(' ', color, 0), x, y, text); + x += text.length(); +} + +struct choose_start_site_hook : df::viewscreen_choose_start_sitest +{ + typedef df::viewscreen_choose_start_sitest interpose_base; + + DEFINE_VMETHOD_INTERPOSE(void, feed, (std::set *input)) + { + bool prevent_default = false; + df::viewscreen * top = Gui::getCurViewscreen(); + VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, top); + if (tool_enabled("anywhere")) + { + for (auto iter = input->begin(); iter != input->end(); iter++) + { + df::interface_key key = *iter; + if (key == df::interface_key::SETUP_EMBARK) + { + prevent_default = true; + screen->in_embark_normal = 1; + } + } + } + if (tool_enabled("nano")) + { + for (auto iter = input->begin(); iter != input->end(); iter++) + { + df::interface_key key = *iter; + bool is_resize = true; + int dx = 0, dy = 0; + switch (key) + { + case df::interface_key::SETUP_LOCAL_Y_UP: + dy = 1; + break; + case df::interface_key::SETUP_LOCAL_Y_DOWN: + dy = -1; + break; + case df::interface_key::SETUP_LOCAL_X_UP: + dx = 1; + break; + case df::interface_key::SETUP_LOCAL_X_DOWN: + dx = -1; + break; + default: + is_resize = false; + } + if (is_resize) { + prevent_default = true; + resize_embark(screen, dx, dy); + } + } + } + if (!prevent_default) + INTERPOSE_NEXT(feed)(input); + } + + DEFINE_VMETHOD_INTERPOSE(void, render, ()) + { + INTERPOSE_NEXT(render)(); + + df::viewscreen * top = Gui::getCurViewscreen(); + VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, top); + + auto dim = Screen::getWindowSize(); + int x = 1, + y = dim.y - 5; + OutputString(COLOR_LIGHTMAGENTA, x, y, "Enabled: "); + std::list tools; + for (int i = 0; i < NUM_TOOLS; i++) + { + if (embark_tools[i].enabled) + { + tools.push_back(embark_tools[i].name); + tools.push_back(", "); + } + } + if (tools.size()) + { + tools.pop_back(); // Remove last , + for (auto iter = tools.begin(); iter != tools.end(); iter++) + { + OutputString(COLOR_LIGHTMAGENTA, x, y, *iter); + } + } + else + { + OutputString(COLOR_LIGHTMAGENTA, x, y, "(none)"); + } + + if (tool_enabled("anywhere")) + { + x = 20; y = dim.y - 2; + if (screen->page == 0) + { + // Only display on main page (not site finder, notes, etc.) + OutputString(COLOR_WHITE, x, y, ": Embark!"); + } + } + } +}; + +IMPLEMENT_VMETHOD_INTERPOSE(choose_start_site_hook, feed); +IMPLEMENT_VMETHOD_INTERPOSE(choose_start_site_hook, render); + +/* + * Tool management + */ + +bool tool_exists (std::string tool_name) +{ + for (int i = 0; i < NUM_TOOLS; i++) + { + if (embark_tools[i].id == tool_name) + return true; + } + return false; +} + +bool tool_enabled (std::string tool_name) +{ + for (int i = 0; i < NUM_TOOLS; i++) + { + if (embark_tools[i].id == tool_name) + return embark_tools[i].enabled; + } + return false; +} + +bool tool_enable (std::string tool_name, bool enable_state) +{ + for (int i = 0; i < NUM_TOOLS; i++) + { + if (embark_tools[i].id == tool_name) + { + embark_tools[i].enabled = enable_state; + return true; + } + } + return false; +} + +/* + * Plugin management + */ + +DFHACK_PLUGIN("embark-tools"); +DFHACK_PLUGIN_IS_ENABLED(is_enabled); + +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) +{ + std::string help = ""; + help += "embark-tools (enable/disable) tool [tool...]\n" + "Tools:\n"; + for (int i = 0; i < NUM_TOOLS; i++) + { + help += (" " + embark_tools[i].id + ": " + embark_tools[i].desc + "\n"); + } + commands.push_back(PluginCommand( + "embark-tools", + "A collection of embark tools", + embark_tools_cmd, + false, + help.c_str() + )); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown (color_ostream &out) +{ + INTERPOSE_HOOK(choose_start_site_hook, feed).remove(); + INTERPOSE_HOOK(choose_start_site_hook, render).remove(); + return CR_OK; +} + +DFhackCExport command_result plugin_enable (color_ostream &out, bool enable) +{ + if (is_enabled != enable) + { + if (!INTERPOSE_HOOK(choose_start_site_hook, feed).apply(enable) || + !INTERPOSE_HOOK(choose_start_site_hook, render).apply(enable)) + return CR_FAILURE; + is_enabled = enable; + } + return CR_OK; +} + +command_result embark_tools_cmd (color_ostream &out, std::vector & parameters) +{ + CoreSuspender suspend; + if (parameters.size()) + { + // Set by "enable"/"disable" - allows for multiple commands, e.g. "enable nano disable anywhere" + bool enable_state = true; + for (size_t i = 0; i < parameters.size(); i++) + { + if (parameters[i] == "enable") + { + enable_state = true; + plugin_enable(out, true); // Enable plugin + } + else if (parameters[i] == "disable") + enable_state = false; + else if (tool_exists(parameters[i])) + { + tool_enable(parameters[i], enable_state); + } + else + return CR_WRONG_USAGE; + } + } + else + { + if (is_enabled) + { + out << "Tool status:" << std::endl; + for (int i = 0; i < NUM_TOOLS; i++) + { + EmbarkTool t = embark_tools[i]; + out << t.name << " (" << t.id << "): " << (t.enabled ? "Enabled" : "Disabled") << std::endl; + } + } + else + { + out << "Plugin not enabled" << std::endl; + } + } + return CR_OK; +} From 27bc40ed219d774cbaadb25243b5333f8cecb4a0 Mon Sep 17 00:00:00 2001 From: Lethosor Date: Sun, 18 May 2014 18:53:28 -0400 Subject: [PATCH 02/36] Update Readme.rst --- Readme.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.rst b/Readme.rst index b2d98b599..3451eaff0 100644 --- a/Readme.rst +++ b/Readme.rst @@ -2032,7 +2032,7 @@ See the bay12 thread for details: http://www.bay12forums.com/smf/index.php?topic embark-tools ------------ -A collection of tools for embarking. +A collection of embark-related tools. Usage:: From 6519ac1bf887b61ea613b91012f9fad331166ef3 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sun, 18 May 2014 20:03:31 -0400 Subject: [PATCH 03/36] Add sand indicator and allow enabling/disabling all tools --- plugins/embark-tools.cpp | 61 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/plugins/embark-tools.cpp b/plugins/embark-tools.cpp index 1a02e3e65..12b00bb0b 100644 --- a/plugins/embark-tools.cpp +++ b/plugins/embark-tools.cpp @@ -27,6 +27,7 @@ struct EmbarkTool EmbarkTool embark_tools[] = { {"anywhere", "Embark anywhere", "Allows embarking anywhere on the world map", false}, {"nano", "Nano embark", "Allows the embark size to be decreased below 2x2", false}, + {"sand", "Sand indicator", "Displays an indicator when sand is present on the given embark site", false}, }; #define NUM_TOOLS sizeof(embark_tools) / sizeof(EmbarkTool) @@ -35,6 +36,7 @@ command_result embark_tools_cmd (color_ostream &out, std::vector & bool tool_exists (std::string tool_name); bool tool_enabled (std::string tool_name); bool tool_enable (std::string tool_name, bool enable_state); +void tool_update (std::string tool_name); /* * Logic @@ -78,6 +80,30 @@ void resize_embark (df::viewscreen_choose_start_sitest * screen, int dx, int dy) screen->embark_pos_max.y = y2; } +std::string sand_indicator = ""; +bool sand_dirty = true; // Flag set when update is needed +void sand_update () +{ + CoreSuspendClaimer suspend; + df::viewscreen * top = Gui::getCurViewscreen(); + VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, top); + buffered_color_ostream out; + Core::getInstance().runCommand(out, "prospect"); + auto fragments = out.fragments(); + sand_indicator = ""; + for (auto iter = fragments.begin(); iter != fragments.end(); iter++) + { + std::string fragment = iter->second; + if (fragment.find("SAND_") != std::string::npos || + fragment.find("SAND :") != std::string::npos) + { + sand_indicator = "Sand"; + break; + } + } + sand_dirty = false; +} + /* * Viewscreen hooks */ @@ -139,6 +165,10 @@ struct choose_start_site_hook : df::viewscreen_choose_start_sitest } } } + if (tool_enabled("sand")) + { + sand_dirty = true; + } if (!prevent_default) INTERPOSE_NEXT(feed)(input); } @@ -185,6 +215,18 @@ struct choose_start_site_hook : df::viewscreen_choose_start_sitest OutputString(COLOR_WHITE, x, y, ": Embark!"); } } + if (tool_enabled("sand")) + { + if (sand_dirty) + { + sand_update(); + } + x = dim.x - 28; y = 13; + if (screen->page == 0) + { + OutputString(COLOR_YELLOW, x, y, sand_indicator); + } + } } }; @@ -217,15 +259,26 @@ bool tool_enabled (std::string tool_name) bool tool_enable (std::string tool_name, bool enable_state) { + int n = 0; for (int i = 0; i < NUM_TOOLS; i++) { - if (embark_tools[i].id == tool_name) + if (embark_tools[i].id == tool_name || tool_name == "all") { embark_tools[i].enabled = enable_state; - return true; + tool_update(tool_name); + n++; } } - return false; + return (bool)n; +} + +void tool_update (std::string tool_name) +{ + // Called whenever a tool is enabled/disabled + if (tool_name == "sand") + { + sand_dirty = true; + } } /* @@ -289,7 +342,7 @@ command_result embark_tools_cmd (color_ostream &out, std::vector & } else if (parameters[i] == "disable") enable_state = false; - else if (tool_exists(parameters[i])) + else if (tool_exists(parameters[i]) || parameters[i] == "all") { tool_enable(parameters[i], enable_state); } From 96b70a93bc0a1d92992d5c66b85dede85f857fcf Mon Sep 17 00:00:00 2001 From: lethosor Date: Sun, 18 May 2014 21:21:17 -0400 Subject: [PATCH 04/36] Update readme --- Readme.rst | 1 + plugins/embark-tools.cpp | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Readme.rst b/Readme.rst index 3451eaff0..006f06ae8 100644 --- a/Readme.rst +++ b/Readme.rst @@ -2042,6 +2042,7 @@ Tools: * ``anywhere``: Allows embarking anywhere (including sites, mountain-only biomes, and oceans). Use with caution. * ``nano``: An implementation of nano embark - allows resizing below 2x2 when enabled. +* ``sand``: Displays an indicator when sand is present in the currently-selected area, similar to the default clay/stone indicators. misery ------ diff --git a/plugins/embark-tools.cpp b/plugins/embark-tools.cpp index 12b00bb0b..23354abcc 100644 --- a/plugins/embark-tools.cpp +++ b/plugins/embark-tools.cpp @@ -94,8 +94,7 @@ void sand_update () for (auto iter = fragments.begin(); iter != fragments.end(); iter++) { std::string fragment = iter->second; - if (fragment.find("SAND_") != std::string::npos || - fragment.find("SAND :") != std::string::npos) + if (fragment.find("SAND_") != std::string::npos) { sand_indicator = "Sand"; break; From 02811c773c6623b6084d18f940f9f7fbc7bb4470 Mon Sep 17 00:00:00 2001 From: lethosor Date: Mon, 19 May 2014 15:53:29 -0400 Subject: [PATCH 05/36] Fix crash with child screens (e.g. saving a macro) --- plugins/embark-tools.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/embark-tools.cpp b/plugins/embark-tools.cpp index 23354abcc..265b1cea3 100644 --- a/plugins/embark-tools.cpp +++ b/plugins/embark-tools.cpp @@ -178,6 +178,8 @@ struct choose_start_site_hook : df::viewscreen_choose_start_sitest df::viewscreen * top = Gui::getCurViewscreen(); VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, top); + if (!screen) + return; auto dim = Screen::getWindowSize(); int x = 1, From bb5f7b475d792b029fe47da06e13517afdddb641 Mon Sep 17 00:00:00 2001 From: lethosor Date: Mon, 19 May 2014 16:11:42 -0400 Subject: [PATCH 06/36] Add sticky (equivalent of tweak stable-cursor) --- Readme.rst | 1 + plugins/embark-tools.cpp | 76 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/Readme.rst b/Readme.rst index 006f06ae8..e8a04de78 100644 --- a/Readme.rst +++ b/Readme.rst @@ -2043,6 +2043,7 @@ Tools: * ``anywhere``: Allows embarking anywhere (including sites, mountain-only biomes, and oceans). Use with caution. * ``nano``: An implementation of nano embark - allows resizing below 2x2 when enabled. * ``sand``: Displays an indicator when sand is present in the currently-selected area, similar to the default clay/stone indicators. +* ``sticky``: Maintains the selected local area while navigating the world map misery ------ diff --git a/plugins/embark-tools.cpp b/plugins/embark-tools.cpp index 265b1cea3..4d1a4afbe 100644 --- a/plugins/embark-tools.cpp +++ b/plugins/embark-tools.cpp @@ -28,6 +28,7 @@ EmbarkTool embark_tools[] = { {"anywhere", "Embark anywhere", "Allows embarking anywhere on the world map", false}, {"nano", "Nano embark", "Allows the embark size to be decreased below 2x2", false}, {"sand", "Sand indicator", "Displays an indicator when sand is present on the given embark site", false}, + {"sticky", "Stable position", "Maintains the selected local area while navigating the world map", false}, }; #define NUM_TOOLS sizeof(embark_tools) / sizeof(EmbarkTool) @@ -103,6 +104,26 @@ void sand_update () sand_dirty = false; } +int sticky_pos[] = {0, 0, 3, 3}; +bool sticky_moved = false; +void sticky_save (df::viewscreen_choose_start_sitest * screen) +{ + sticky_pos = { + screen->embark_pos_min.x, + screen->embark_pos_max.x, + screen->embark_pos_min.y, + screen->embark_pos_max.y, + }; +} + +void sticky_apply (df::viewscreen_choose_start_sitest * screen) +{ + screen->embark_pos_min.x = sticky_pos[0]; + screen->embark_pos_max.x = sticky_pos[1]; + screen->embark_pos_min.y = sticky_pos[2]; + screen->embark_pos_max.y = sticky_pos[3]; +} + /* * Viewscreen hooks */ @@ -134,6 +155,7 @@ struct choose_start_site_hook : df::viewscreen_choose_start_sitest } } } + if (tool_enabled("nano")) { for (auto iter = input->begin(); iter != input->end(); iter++) @@ -158,12 +180,52 @@ struct choose_start_site_hook : df::viewscreen_choose_start_sitest default: is_resize = false; } - if (is_resize) { + if (is_resize) + { prevent_default = true; resize_embark(screen, dx, dy); } } } + + if (tool_enabled("sticky")) + { + for (auto iter = input->begin(); iter != input->end(); iter++) + { + df::interface_key key = *iter; + bool is_motion = false; + int dx = 0, dy = 0; + switch (key) + { + case df::interface_key::CURSOR_UP: + case df::interface_key::CURSOR_DOWN: + case df::interface_key::CURSOR_LEFT: + case df::interface_key::CURSOR_RIGHT: + case df::interface_key::CURSOR_UPLEFT: + case df::interface_key::CURSOR_UPRIGHT: + case df::interface_key::CURSOR_DOWNLEFT: + case df::interface_key::CURSOR_DOWNRIGHT: + case df::interface_key::CURSOR_UP_FAST: + case df::interface_key::CURSOR_DOWN_FAST: + case df::interface_key::CURSOR_LEFT_FAST: + case df::interface_key::CURSOR_RIGHT_FAST: + case df::interface_key::CURSOR_UPLEFT_FAST: + case df::interface_key::CURSOR_UPRIGHT_FAST: + case df::interface_key::CURSOR_DOWNLEFT_FAST: + case df::interface_key::CURSOR_DOWNRIGHT_FAST: + is_motion = true; + break; + default: + is_motion = false; + } + if (is_motion) + { + sticky_save(screen); + sticky_moved = true; + } + } + } + if (tool_enabled("sand")) { sand_dirty = true; @@ -174,13 +236,19 @@ struct choose_start_site_hook : df::viewscreen_choose_start_sitest DEFINE_VMETHOD_INTERPOSE(void, render, ()) { - INTERPOSE_NEXT(render)(); - df::viewscreen * top = Gui::getCurViewscreen(); VIRTUAL_CAST_VAR(screen, df::viewscreen_choose_start_sitest, top); if (!screen) return; + if (tool_enabled("sticky") && sticky_moved) + { + sticky_apply(screen); + sticky_moved = false; + } + + INTERPOSE_NEXT(render)(); + auto dim = Screen::getWindowSize(); int x = 1, y = dim.y - 5; @@ -321,7 +389,7 @@ DFhackCExport command_result plugin_enable (color_ostream &out, bool enable) { if (!INTERPOSE_HOOK(choose_start_site_hook, feed).apply(enable) || !INTERPOSE_HOOK(choose_start_site_hook, render).apply(enable)) - return CR_FAILURE; + return CR_FAILURE; is_enabled = enable; } return CR_OK; From da31bab4199d17f46c5b4d72cb079d2d479f9f28 Mon Sep 17 00:00:00 2001 From: lethosor Date: Mon, 19 May 2014 16:33:17 -0400 Subject: [PATCH 07/36] Display embark label on all 5 map pages --- plugins/embark-tools.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/embark-tools.cpp b/plugins/embark-tools.cpp index 4d1a4afbe..0c2781d05 100644 --- a/plugins/embark-tools.cpp +++ b/plugins/embark-tools.cpp @@ -278,9 +278,9 @@ struct choose_start_site_hook : df::viewscreen_choose_start_sitest if (tool_enabled("anywhere")) { x = 20; y = dim.y - 2; - if (screen->page == 0) + if (screen->page >= 0 && screen->page <= 4) { - // Only display on main page (not site finder, notes, etc.) + // Only display on five map pages, not on site finder or notes OutputString(COLOR_WHITE, x, y, ": Embark!"); } } From fcb62ac7dd37fba5c9437d2a96a8fa3f27ae0efc Mon Sep 17 00:00:00 2001 From: lethosor Date: Mon, 19 May 2014 17:43:30 -0400 Subject: [PATCH 08/36] sticky: Fix handling of rapid input --- plugins/embark-tools.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/embark-tools.cpp b/plugins/embark-tools.cpp index 0c2781d05..1eb7f0198 100644 --- a/plugins/embark-tools.cpp +++ b/plugins/embark-tools.cpp @@ -218,7 +218,7 @@ struct choose_start_site_hook : df::viewscreen_choose_start_sitest default: is_motion = false; } - if (is_motion) + if (is_motion && !sticky_moved) { sticky_save(screen); sticky_moved = true; From 2d778be95662269cb8d9a757d240d06f330207ba Mon Sep 17 00:00:00 2001 From: lethosor Date: Tue, 20 May 2014 15:51:26 -0400 Subject: [PATCH 09/36] Fix embark sidebar updating --- plugins/embark-tools.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/plugins/embark-tools.cpp b/plugins/embark-tools.cpp index 1eb7f0198..f049841c5 100644 --- a/plugins/embark-tools.cpp +++ b/plugins/embark-tools.cpp @@ -43,6 +43,21 @@ void tool_update (std::string tool_name); * Logic */ +void update_embark_sidebar (df::viewscreen_choose_start_sitest * screen) +{ + bool is_top = false; + if (screen->embark_pos_min.y == 0) + is_top = true; + std::set keys; + keys.insert(df::interface_key::SETUP_LOCAL_Y_MUP); + screen->feed(&keys); + if (!is_top) + { + keys.insert(df::interface_key::SETUP_LOCAL_Y_MDOWN); + screen->feed(&keys); + } +} + void resize_embark (df::viewscreen_choose_start_sitest * screen, int dx, int dy) { /* Reproduces DF's embark resizing functionality @@ -79,6 +94,8 @@ void resize_embark (df::viewscreen_choose_start_sitest * screen, int dx, int dy) screen->embark_pos_max.x = x2; screen->embark_pos_min.y = y1; screen->embark_pos_max.y = y2; + + update_embark_sidebar(screen); } std::string sand_indicator = ""; @@ -122,6 +139,7 @@ void sticky_apply (df::viewscreen_choose_start_sitest * screen) screen->embark_pos_max.x = sticky_pos[1]; screen->embark_pos_min.y = sticky_pos[2]; screen->embark_pos_max.y = sticky_pos[3]; + update_embark_sidebar(screen); } /* From a7fd6c478350abef246df4a9579d898085b4c605 Mon Sep 17 00:00:00 2001 From: lethosor Date: Mon, 2 Jun 2014 17:55:27 -0400 Subject: [PATCH 10/36] Add embark-tools settings interface --- plugins/embark-tools.cpp | 89 +++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 11 deletions(-) diff --git a/plugins/embark-tools.cpp b/plugins/embark-tools.cpp index f049841c5..c9bbdf27e 100644 --- a/plugins/embark-tools.cpp +++ b/plugins/embark-tools.cpp @@ -22,23 +22,83 @@ struct EmbarkTool std::string name; std::string desc; bool enabled; + df::interface_key toggle_key; }; EmbarkTool embark_tools[] = { - {"anywhere", "Embark anywhere", "Allows embarking anywhere on the world map", false}, - {"nano", "Nano embark", "Allows the embark size to be decreased below 2x2", false}, - {"sand", "Sand indicator", "Displays an indicator when sand is present on the given embark site", false}, - {"sticky", "Stable position", "Maintains the selected local area while navigating the world map", false}, + {"anywhere", "Embark anywhere", "Allows embarking anywhere on the world map", + false, df::interface_key::CUSTOM_A}, + {"nano", "Nano embark", "Allows the embark size to be decreased below 2x2", + false, df::interface_key::CUSTOM_N}, + {"sand", "Sand indicator", "Displays an indicator when sand is present on the given embark site", + false, df::interface_key::CUSTOM_S}, + {"sticky", "Stable position", "Maintains the selected local area while navigating the world map", + false, df::interface_key::CUSTOM_P}, }; #define NUM_TOOLS sizeof(embark_tools) / sizeof(EmbarkTool) command_result embark_tools_cmd (color_ostream &out, std::vector & parameters); +void OutputString (int8_t color, int &x, int y, const std::string &text); + bool tool_exists (std::string tool_name); bool tool_enabled (std::string tool_name); bool tool_enable (std::string tool_name, bool enable_state); void tool_update (std::string tool_name); +class embark_tools_settings : public dfhack_viewscreen +{ +public: + embark_tools_settings () { }; + ~embark_tools_settings () { }; + void help () { }; + std::string getFocusString () { return "embark-tools/options"; }; + void render () + { + int x; + auto dim = Screen::getWindowSize(); + int width = 50, + height = 4 + 1 + NUM_TOOLS, // Padding + lower row + min_x = (dim.x - width) / 2, + max_x = (dim.x + width) / 2, + min_y = (dim.y - height) / 2, + max_y = min_y + height; + Screen::fillRect(Screen::Pen(' ', COLOR_BLACK, COLOR_DARKGREY), min_x, min_y, max_x, max_y); + Screen::fillRect(Screen::Pen(' ', COLOR_BLACK, COLOR_BLACK), min_x + 1, min_y + 1, max_x - 1, max_y - 1); + x = min_x + 2; + OutputString(COLOR_LIGHTRED, x, max_y - 2, Screen::getKeyDisplay(df::interface_key::SELECT)); + OutputString(COLOR_WHITE, x, max_y - 2, "/"); + OutputString(COLOR_LIGHTRED, x, max_y - 2, Screen::getKeyDisplay(df::interface_key::LEAVESCREEN)); + OutputString(COLOR_WHITE, x, max_y - 2, ": Done"); + for (int i = 0, y = min_y + 2; i < NUM_TOOLS; i++, y++) + { + EmbarkTool t = embark_tools[i]; + x = min_x + 2; + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(t.toggle_key)); + OutputString(COLOR_WHITE, x, y, ": " + t.name + (t.enabled ? ": Enabled" : ": Disabled")); + } + }; + void feed (std::set * input) + { + if (input->count(df::interface_key::SELECT) || input->count(df::interface_key::LEAVESCREEN)) + { + Screen::dismiss(this); + return; + } + for (auto iter = input->begin(); iter != input->end(); iter++) + { + df::interface_key key = *iter; + for (int i = 0; i < NUM_TOOLS; i++) + { + if (embark_tools[i].toggle_key == key) + { + embark_tools[i].enabled = !embark_tools[i].enabled; + } + } + } + }; +}; + /* * Logic */ @@ -174,6 +234,12 @@ struct choose_start_site_hook : df::viewscreen_choose_start_sitest } } + if (input->count(df::interface_key::CUSTOM_S)) + { + Screen::show(new embark_tools_settings); + return; + } + if (tool_enabled("nano")) { for (auto iter = input->begin(); iter != input->end(); iter++) @@ -270,20 +336,21 @@ struct choose_start_site_hook : df::viewscreen_choose_start_sitest auto dim = Screen::getWindowSize(); int x = 1, y = dim.y - 5; - OutputString(COLOR_LIGHTMAGENTA, x, y, "Enabled: "); - std::list tools; + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(df::interface_key::CUSTOM_S)); + OutputString(COLOR_WHITE, x, y, ": Enabled: "); + std::list parts; for (int i = 0; i < NUM_TOOLS; i++) { if (embark_tools[i].enabled) { - tools.push_back(embark_tools[i].name); - tools.push_back(", "); + parts.push_back(embark_tools[i].name); + parts.push_back(", "); } } - if (tools.size()) + if (parts.size()) { - tools.pop_back(); // Remove last , - for (auto iter = tools.begin(); iter != tools.end(); iter++) + parts.pop_back(); // Remove trailing comma + for (auto iter = parts.begin(); iter != parts.end(); iter++) { OutputString(COLOR_LIGHTMAGENTA, x, y, *iter); } From 6ec0fd6589042356e75dee3267097221bbb69054 Mon Sep 17 00:00:00 2001 From: lethosor Date: Tue, 3 Jun 2014 18:29:13 -0400 Subject: [PATCH 11/36] New tweak: confirm-embark Adds a confirmation when selecting [e]mbark on the "prepare carefully" screen. Suggested in multiple threads on forums. --- plugins/tweak.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/plugins/tweak.cpp b/plugins/tweak.cpp index d74ef0767..2136fff58 100644 --- a/plugins/tweak.cpp +++ b/plugins/tweak.cpp @@ -52,6 +52,7 @@ #include "df/reaction.h" #include "df/reaction_reagent_itemst.h" #include "df/reaction_reagent_flags.h" +#include "df/viewscreen_setupdwarfgamest.h" #include "df/viewscreen_layer_assigntradest.h" #include "df/viewscreen_tradegoodsst.h" #include "df/viewscreen_layer_militaryst.h" @@ -120,6 +121,8 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector \n" @@ -331,6 +334,83 @@ struct readable_build_plate_hook : df::viewscreen_dwarfmodest IMPLEMENT_VMETHOD_INTERPOSE(readable_build_plate_hook, render); +enum confirm_embark_states +{ + ECS_INACTIVE = 0, + ECS_CONFIRM, + ECS_ACCEPTED +}; +static confirm_embark_states confirm_embark_state = ECS_INACTIVE; + +struct confirm_embark_hook : df::viewscreen_setupdwarfgamest +{ + typedef df::viewscreen_setupdwarfgamest interpose_base; + + DEFINE_VMETHOD_INTERPOSE(void, feed, (set *input)) + { + bool intercept = false; + df::viewscreen * top = Gui::getCurViewscreen(); + VIRTUAL_CAST_VAR(screen, df::viewscreen_setupdwarfgamest, top); + if (screen) + { + if (screen->anon_14 == 0) // Advanced embark screen + { + if (confirm_embark_state == ECS_INACTIVE) + { + if (input->count(df::interface_key::SETUP_EMBARK)) + { + confirm_embark_state = ECS_CONFIRM; + intercept = true; + } + } + else if (confirm_embark_state == ECS_CONFIRM) + { + intercept = true; + if (input->count(df::interface_key::MENU_CONFIRM)) + confirm_embark_state = ECS_ACCEPTED; + else if (input->size()) + confirm_embark_state = ECS_INACTIVE; + } + } + } + + if (!intercept) + INTERPOSE_NEXT(feed)(input); + } + + DEFINE_VMETHOD_INTERPOSE(void, render, ()) + { + INTERPOSE_NEXT(render)(); + df::viewscreen * top = Gui::getCurViewscreen(); + VIRTUAL_CAST_VAR(screen, df::viewscreen_setupdwarfgamest, top); + auto dim = Screen::getWindowSize(); + Screen::Pen pen(' ', COLOR_WHITE, COLOR_BLACK); + if (confirm_embark_state != ECS_INACTIVE) + { + Screen::fillRect(Screen::Pen(' ', COLOR_BLACK, COLOR_BLACK), 0, 0, dim.x - 1, dim.y - 1); + } + if (confirm_embark_state == ECS_CONFIRM) + { + Screen::paintString(pen, 2, 2, "Really embark?"); + Screen::paintString(Screen::Pen(' ', COLOR_LIGHTGREEN), + 2, 4, Screen::getKeyDisplay(df::interface_key::MENU_CONFIRM)); + Screen::paintString(pen, 3, 4, ": Confirm, Other: Cancel"); + Screen::paintString(pen, dim.x - 10, dim.y - 1, "DFHack"); + } + else if (confirm_embark_state == ECS_ACCEPTED) + { + Screen::paintString(pen, 2, 2, "Embarking..."); + std::set input; + input.insert(df::interface_key::SETUP_EMBARK); + screen->feed(&input); + confirm_embark_state = ECS_INACTIVE; + } + } +}; + +IMPLEMENT_VMETHOD_INTERPOSE(confirm_embark_hook, feed); +IMPLEMENT_VMETHOD_INTERPOSE(confirm_embark_hook, render); + struct stable_temp_hook : df::item_actual { typedef df::item_actual interpose_base; @@ -1150,7 +1230,7 @@ static command_result tweak(color_ostream &out, vector ¶meters) df::unit *unit = getSelectedUnit(out, true); if (!unit) return CR_FAILURE; - + if(unit->race != df::global::ui->race_id) { out << "Selected unit does not belong to your race!" << endl; @@ -1161,15 +1241,15 @@ static command_result tweak(color_ostream &out, vector ¶meters) // see http://dffd.wimbli.com/file.php?id=6139 for a save if (unit->flags2.bits.resident) unit->flags2.bits.resident = 0; - + // case #2: migrants who have the merchant flag // happens on almost all maps after a few migrant waves if(unit->flags1.bits.merchant) unit->flags1.bits.merchant = 0; - // this one is a cheat, but bugged migrants usually have the same civ_id + // this one is a cheat, but bugged migrants usually have the same civ_id // so it should not be triggered in most cases - // if it happens that the player has 'foreign' units of the same race + // if it happens that the player has 'foreign' units of the same race // (vanilla df: dwarves not from mountainhome) on his map, just grab them if(unit->civ_id != df::global::ui->civ_id) unit->civ_id = df::global::ui->civ_id; @@ -1216,6 +1296,11 @@ static command_result tweak(color_ostream &out, vector ¶meters) enable_hook(out, INTERPOSE_HOOK(readable_build_plate_hook, render), parameters); } + else if (cmd == "confirm-embark") + { + enable_hook(out, INTERPOSE_HOOK(confirm_embark_hook, feed), parameters); + enable_hook(out, INTERPOSE_HOOK(confirm_embark_hook, render), parameters); + } else if (cmd == "stable-temp") { enable_hook(out, INTERPOSE_HOOK(stable_temp_hook, adjustTemperature), parameters); @@ -1280,7 +1365,7 @@ static command_result tweak(color_ostream &out, vector ¶meters) enable_hook(out, INTERPOSE_HOOK(adamantine_cloth_wear_shoes_hook, incWearTimer), parameters); enable_hook(out, INTERPOSE_HOOK(adamantine_cloth_wear_pants_hook, incWearTimer), parameters); } - else + else return CR_WRONG_USAGE; return CR_OK; From f29d1886ff2164932a3773d7929f745005cc64a9 Mon Sep 17 00:00:00 2001 From: lethosor Date: Wed, 4 Jun 2014 14:41:35 -0400 Subject: [PATCH 12/36] tweak confirm-embark fixes * Added a display of the total embark points remaining, for convenience * Made 'esc' work by interposing key_conflict as well * Rearranged to look more like DF's confirmations --- plugins/tweak.cpp | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/plugins/tweak.cpp b/plugins/tweak.cpp index 2136fff58..58ff6f929 100644 --- a/plugins/tweak.cpp +++ b/plugins/tweak.cpp @@ -346,6 +346,12 @@ struct confirm_embark_hook : df::viewscreen_setupdwarfgamest { typedef df::viewscreen_setupdwarfgamest interpose_base; + void OutputString(int8_t fg, int &x, int y, std::string text) + { + Screen::paintString(Screen::Pen(' ', fg, COLOR_BLACK), x, y, text); + x += text.length(); + } + DEFINE_VMETHOD_INTERPOSE(void, feed, (set *input)) { bool intercept = false; @@ -378,28 +384,39 @@ struct confirm_embark_hook : df::viewscreen_setupdwarfgamest INTERPOSE_NEXT(feed)(input); } + DEFINE_VMETHOD_INTERPOSE(bool, key_conflict, (df::interface_key key)) + { + if (key == df::interface_key::OPTIONS) + return true; + return false; + } + DEFINE_VMETHOD_INTERPOSE(void, render, ()) { INTERPOSE_NEXT(render)(); df::viewscreen * top = Gui::getCurViewscreen(); VIRTUAL_CAST_VAR(screen, df::viewscreen_setupdwarfgamest, top); auto dim = Screen::getWindowSize(); - Screen::Pen pen(' ', COLOR_WHITE, COLOR_BLACK); + int x = 0, y = 0; if (confirm_embark_state != ECS_INACTIVE) { Screen::fillRect(Screen::Pen(' ', COLOR_BLACK, COLOR_BLACK), 0, 0, dim.x - 1, dim.y - 1); } if (confirm_embark_state == ECS_CONFIRM) { - Screen::paintString(pen, 2, 2, "Really embark?"); - Screen::paintString(Screen::Pen(' ', COLOR_LIGHTGREEN), - 2, 4, Screen::getKeyDisplay(df::interface_key::MENU_CONFIRM)); - Screen::paintString(pen, 3, 4, ": Confirm, Other: Cancel"); - Screen::paintString(pen, dim.x - 10, dim.y - 1, "DFHack"); + x = 2, y = 2; + OutputString(COLOR_WHITE, x, y, "Really embark? ("); + OutputString(COLOR_LIGHTGREEN, x, y, Screen::getKeyDisplay(df::interface_key::MENU_CONFIRM)); + OutputString(COLOR_WHITE, x, y, " = yes, other = no)"); + x = 2, y = 4; + int32_t points = screen->anon_37; + OutputString(COLOR_WHITE, x, y, "Points left: "); + OutputString((points ? COLOR_YELLOW : COLOR_LIGHTGREEN), x, y, std::to_string(points)); + x = dim.x - 10, y = dim.y - 1; + OutputString(COLOR_WHITE, x, y, "DFHack"); } else if (confirm_embark_state == ECS_ACCEPTED) { - Screen::paintString(pen, 2, 2, "Embarking..."); std::set input; input.insert(df::interface_key::SETUP_EMBARK); screen->feed(&input); @@ -409,6 +426,7 @@ struct confirm_embark_hook : df::viewscreen_setupdwarfgamest }; IMPLEMENT_VMETHOD_INTERPOSE(confirm_embark_hook, feed); +IMPLEMENT_VMETHOD_INTERPOSE(confirm_embark_hook, key_conflict); IMPLEMENT_VMETHOD_INTERPOSE(confirm_embark_hook, render); struct stable_temp_hook : df::item_actual { @@ -1299,6 +1317,7 @@ static command_result tweak(color_ostream &out, vector ¶meters) else if (cmd == "confirm-embark") { enable_hook(out, INTERPOSE_HOOK(confirm_embark_hook, feed), parameters); + enable_hook(out, INTERPOSE_HOOK(confirm_embark_hook, key_conflict), parameters); enable_hook(out, INTERPOSE_HOOK(confirm_embark_hook, render), parameters); } else if (cmd == "stable-temp") From 0a1d87c09f418c8c9075083bb207d91c6185628d Mon Sep 17 00:00:00 2001 From: lethosor Date: Wed, 4 Jun 2014 23:18:19 -0400 Subject: [PATCH 13/36] confirm-embark: Make esc work again --- plugins/tweak.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/tweak.cpp b/plugins/tweak.cpp index 58ff6f929..c7cec6246 100644 --- a/plugins/tweak.cpp +++ b/plugins/tweak.cpp @@ -386,8 +386,11 @@ struct confirm_embark_hook : df::viewscreen_setupdwarfgamest DEFINE_VMETHOD_INTERPOSE(bool, key_conflict, (df::interface_key key)) { - if (key == df::interface_key::OPTIONS) - return true; + if (confirm_embark_state == ECS_CONFIRM) + { + if (key == df::interface_key::OPTIONS) + return true; + } return false; } From c29d61dca23feb42b16c2a04e54a66f2406c35d6 Mon Sep 17 00:00:00 2001 From: Lethosor Date: Fri, 6 Jun 2014 14:59:23 -0400 Subject: [PATCH 14/36] Use INTERPOSE_NEXT in key_conflict See comment on 0a1d87c09f418c8c9075083bb207d91c6185628d --- plugins/tweak.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tweak.cpp b/plugins/tweak.cpp index c7cec6246..8e301ae5c 100644 --- a/plugins/tweak.cpp +++ b/plugins/tweak.cpp @@ -391,7 +391,7 @@ struct confirm_embark_hook : df::viewscreen_setupdwarfgamest if (key == df::interface_key::OPTIONS) return true; } - return false; + return INTERPOSE_NEXT(key_conflict)(key); } DEFINE_VMETHOD_INTERPOSE(void, render, ()) From 2242d42c9c896d754037d88a5a5a94f0a0fb16c6 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 7 Jun 2014 20:15:49 -0400 Subject: [PATCH 15/36] Implement runCommand in Lua API --- library/LuaApi.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 3a374445f..91baf5fbb 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2227,6 +2227,31 @@ static int internal_getDir(lua_State *L) } return 1; } + +static int internal_runCommand(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TSTRING); + std::string command = lua_tostring(L, 1); + buffered_color_ostream out; + Core::getInstance().runCommand(out, command); + auto fragments = out.fragments(); + lua_newtable(L); + int i = 1; + for (auto iter = fragments.begin(); iter != fragments.end(); iter++, i++) + { + int color = iter->first; + std::string output = iter->second; + lua_createtable(L, 2, 0); + lua_pushinteger(L, color); + lua_rawseti(L, -2, 1); + lua_pushstring(L, output.c_str()); + lua_rawseti(L, -2, 2); + lua_rawseti(L, -2, i); + } + lua_pushvalue(L, -1); + return 1; +} + static const luaL_Reg dfhack_internal_funcs[] = { { "getAddress", internal_getAddress }, { "setAddress", internal_setAddress }, @@ -2240,6 +2265,7 @@ static const luaL_Reg dfhack_internal_funcs[] = { { "memscan", internal_memscan }, { "diffscan", internal_diffscan }, { "getDir", internal_getDir }, + { "runCommand", internal_runCommand }, { NULL, NULL } }; From 91a93a00d2222039397d910aa346beddb9b2f5e6 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 7 Jun 2014 20:31:14 -0400 Subject: [PATCH 16/36] Add dfhack.run_command (Lua) Simplified version of runCommand --- library/lua/dfhack.lua | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua index 77c62311a..10af8b43e 100644 --- a/library/lua/dfhack.lua +++ b/library/lua/dfhack.lua @@ -256,7 +256,8 @@ function dfhack.interpreter(prompt,hfile,env) print("Shortcuts:\n".. " '= foo' => '_1,_2,... = foo'\n".. " '! foo' => 'print(foo)'\n".. - "Both save the first result as '_'.") + " '~ foo' => 'printall(foo)'\n".. + "All of these save the first result as '_'.") print_banner = false end @@ -357,6 +358,16 @@ function dfhack.run_script(name,...) return f(...) end +function dfhack.run_command(command, ...) + command = command .. ' ' .. table.concat({...}, ' ') + fragments = internal.runCommand(command) + output = "" + for i, f in pairs(fragments) do + output = output .. f[2] + end + return output +end + -- Per-save init file function dfhack.getSavePath() From bdcc00f6f768159a260f4caa04ae8b470f6b887a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-David=20Be=CC=81langer?= Date: Mon, 9 Jun 2014 21:51:52 -0400 Subject: [PATCH 17/36] Util method (in the Units class) to get a unit squad name (the translated name, or alias if set) --- library/include/modules/Units.h | 2 ++ library/modules/Units.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/library/include/modules/Units.h b/library/include/modules/Units.h index b51183d6b..5380d82aa 100644 --- a/library/include/modules/Units.h +++ b/library/include/modules/Units.h @@ -256,6 +256,8 @@ DFHACK_EXPORT std::string getCasteProfessionName(int race, int caste, df::profes DFHACK_EXPORT int8_t getProfessionColor(df::unit *unit, bool ignore_noble = false); DFHACK_EXPORT int8_t getCasteProfessionColor(int race, int caste, df::profession pid); + +DFHACK_EXPORT std::string getSquadName(df::unit *unit); } } #endif diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 20c536cd1..588292301 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -69,6 +69,7 @@ using namespace std; #include "df/unit_misc_trait.h" #include "df/unit_skill.h" #include "df/curse_attr_change.h" +#include "df/squad.h" using namespace DFHack; using namespace df::enums; @@ -1552,3 +1553,13 @@ int8_t DFHack::Units::getCasteProfessionColor(int race, int casteid, df::profess // default to dwarven peasant color return 3; } + +std::string DFHack::Units::getSquadName(df::unit *unit) +{ + if (unit->military.squad_id == -1) + return ""; + df::squad *squad = world->squads.all[unit->military.squad_id]; + if (squad->alias.size() > 0) + return squad->alias; + return Translation::TranslateName(&squad->name, true); +} From 044f958551c592047bb9f75e4dba47a44919b877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-David=20Be=CC=81langer?= Date: Mon, 9 Jun 2014 21:58:16 -0400 Subject: [PATCH 18/36] Squad column and squad info in Dwarf Manipulator (manipulator plugin) --- plugins/manipulator.cpp | 86 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 5 deletions(-) diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index 57f134447..ecba97b6d 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -248,11 +248,14 @@ struct UnitInfo string profession; int8_t color; int active_index; + string squad_effective_name; + string squad_info; }; enum altsort_mode { ALTSORT_NAME, ALTSORT_PROFESSION, + ALTSORT_SQUAD, ALTSORT_HAPPINESS, ALTSORT_ARRIVAL, ALTSORT_MAX @@ -278,6 +281,22 @@ bool sortByProfession (const UnitInfo *d1, const UnitInfo *d2) return (d1->profession < d2->profession); } +bool sortBySquad (const UnitInfo *d1, const UnitInfo *d2) +{ + bool gt = false; + if (d1->unit->military.squad_id == -1 && d2->unit->military.squad_id == -1) + gt = d1->name > d2->name; + else if (d1->unit->military.squad_id == -1) + gt = true; + else if (d2->unit->military.squad_id == -1) + gt = false; + else if (d1->unit->military.squad_id != d2->unit->military.squad_id) + gt = d1->squad_effective_name > d2->squad_effective_name; + else + gt = d1->unit->military.squad_position > d2->unit->military.squad_position; + return descending ? gt : !gt; +} + bool sortByHappiness (const UnitInfo *d1, const UnitInfo *d2) { if (descending) @@ -337,6 +356,7 @@ enum display_columns { DISP_COLUMN_HAPPINESS, DISP_COLUMN_NAME, DISP_COLUMN_PROFESSION, + DISP_COLUMN_SQUAD, DISP_COLUMN_LABORS, DISP_COLUMN_MAX, }; @@ -450,6 +470,13 @@ void viewscreen_unitlaborsst::refreshNames() cur->name = Translation::TranslateName(Units::getVisibleName(unit), false); cur->transname = Translation::TranslateName(Units::getVisibleName(unit), true); cur->profession = Units::getProfessionName(unit); + if (unit->military.squad_id > -1) { + cur->squad_effective_name = Units::getSquadName(unit); + cur->squad_info = stl_sprintf("%i", unit->military.squad_position + 1) + "." + cur->squad_effective_name; + } else { + cur->squad_effective_name = ""; + cur->squad_info = ""; + } } calcSize(); } @@ -458,7 +485,7 @@ void viewscreen_unitlaborsst::calcSize() { auto dim = Screen::getWindowSize(); - num_rows = dim.y - 10; + num_rows = dim.y - 11; if (num_rows > units.size()) num_rows = units.size(); @@ -469,11 +496,13 @@ 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] = 16; - col_maxwidth[DISP_COLUMN_NAME] = 16; // adjusted in the loop below + col_minwidth[DISP_COLUMN_NAME] = 12; + col_maxwidth[DISP_COLUMN_NAME] = 12; // 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_minwidth[DISP_COLUMN_SQUAD] = 10; + col_maxwidth[DISP_COLUMN_SQUAD] = 10; // adjusted in the loop below + col_minwidth[DISP_COLUMN_LABORS] = num_columns / 2; // 50% col_maxwidth[DISP_COLUMN_LABORS] = NUM_COLUMNS; // get max_name/max_prof from strings length @@ -483,6 +512,8 @@ void viewscreen_unitlaborsst::calcSize() col_maxwidth[DISP_COLUMN_NAME] = units[i]->name.size(); if (col_maxwidth[DISP_COLUMN_PROFESSION] < units[i]->profession.size()) col_maxwidth[DISP_COLUMN_PROFESSION] = units[i]->profession.size(); + if (col_maxwidth[DISP_COLUMN_SQUAD] < units[i]->squad_info.size()) + col_maxwidth[DISP_COLUMN_SQUAD] = units[i]->squad_info.size(); } // check how much room we have @@ -764,6 +795,17 @@ void viewscreen_unitlaborsst::feed(set *events) } break; + case DISP_COLUMN_SQUAD: + if (enabler->mouse_lbut || enabler->mouse_rbut) + { + input_sort = ALTSORT_SQUAD; + if (enabler->mouse_lbut) + events->insert(interface_key::SECONDSCROLL_PAGEDOWN); + if (enabler->mouse_rbut) + events->insert(interface_key::SECONDSCROLL_PAGEUP); + } + break; + case DISP_COLUMN_LABORS: if (enabler->mouse_lbut || enabler->mouse_rbut) { @@ -784,6 +826,7 @@ void viewscreen_unitlaborsst::feed(set *events) case DISP_COLUMN_NAME: case DISP_COLUMN_PROFESSION: + case DISP_COLUMN_SQUAD: // left-click to view, right-click to zoom if (enabler->mouse_lbut) { @@ -882,6 +925,9 @@ void viewscreen_unitlaborsst::feed(set *events) case ALTSORT_PROFESSION: std::sort(units.begin(), units.end(), sortByProfession); break; + case ALTSORT_SQUAD: + std::sort(units.begin(), units.end(), sortBySquad); + break; case ALTSORT_HAPPINESS: std::sort(units.begin(), units.end(), sortByHappiness); break; @@ -898,6 +944,9 @@ void viewscreen_unitlaborsst::feed(set *events) altsort = ALTSORT_PROFESSION; break; case ALTSORT_PROFESSION: + altsort = ALTSORT_SQUAD; + break; + case ALTSORT_SQUAD: altsort = ALTSORT_HAPPINESS; break; case ALTSORT_HAPPINESS: @@ -950,6 +999,7 @@ void viewscreen_unitlaborsst::render() 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"); + Screen::paintString(Screen::Pen(' ', 7, 0), col_offsets[DISP_COLUMN_SQUAD], 2, "Squad"); for (int col = 0; col < col_widths[DISP_COLUMN_LABORS]; col++) { @@ -1025,6 +1075,11 @@ void viewscreen_unitlaborsst::render() bg = 0; Screen::paintString(Screen::Pen(' ', fg, bg), col_offsets[DISP_COLUMN_PROFESSION], 4 + row, profession); + + fg = 15; + string squad = cur->squad_info; + squad.resize(col_widths[DISP_COLUMN_SQUAD]); + Screen::paintString(Screen::Pen(' ', fg, bg), col_offsets[DISP_COLUMN_SQUAD], 4 + row, squad); // Print unit's skills and labor assignments for (int col = 0; col < col_widths[DISP_COLUMN_LABORS]; col++) @@ -1114,7 +1169,25 @@ void viewscreen_unitlaborsst::render() else str = stl_sprintf("Not %s (0/500)", ENUM_ATTR_STR(job_skill, caption_noun, columns[sel_column].skill)); } - Screen::paintString(Screen::Pen(' ', 9, 0), x, 3 + num_rows + 2, str); + Screen::paintString(Screen::Pen(' ', 9, 0), x, y, str); + + if (cur->unit->military.squad_id > -1) { + + x = 1; + y++; + + string squadLabel = "Squad: "; + Screen::paintString(white_pen, x, y, squadLabel); + x += squadLabel.size(); + + string squad = cur->squad_effective_name; + Screen::paintString(Screen::Pen(' ', 11, 0), x, y, squad); + x += squad.size(); + + string pos = stl_sprintf(" Pos %i", cur->unit->military.squad_position + 1); + Screen::paintString(Screen::Pen(' ', 9, 0), x, y, pos); + + } canToggle = (cur->allowEdit) && (columns[sel_column].labor != unit_labor::NONE); } @@ -1153,6 +1226,9 @@ void viewscreen_unitlaborsst::render() case ALTSORT_PROFESSION: OutputString(15, x, y, "Profession"); break; + case ALTSORT_SQUAD: + OutputString(15, x, y, "Squad"); + break; case ALTSORT_HAPPINESS: OutputString(15, x, y, "Happiness"); break; From 8ba1307944b01ae15a824617d27248980d5dae57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-David=20Be=CC=81langer?= Date: Mon, 9 Jun 2014 22:00:23 -0400 Subject: [PATCH 19/36] Update documentation related to Dwarf Manipulator's squad column --- Readme.html | 18 +++++++++--------- Readme.rst | 16 ++++++++-------- images/manipulator.png | Bin 7724 -> 30435 bytes images/manipulator2.png | Bin 7558 -> 32738 bytes 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Readme.html b/Readme.html index f03522734..d35f2d890 100644 --- a/Readme.html +++ b/Readme.html @@ -3,7 +3,7 @@ - + DFHack Readme