|
|
|
@ -11,98 +11,13 @@
|
|
|
|
|
|
|
|
|
|
#include <VTableInterpose.h>
|
|
|
|
|
#include "ColorText.h"
|
|
|
|
|
#include "uicommon.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;
|
|
|
|
|
df::interface_key toggle_key;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
EmbarkTool embark_tools[] = {
|
|
|
|
|
{"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 int(sizeof(embark_tools) / sizeof(EmbarkTool))
|
|
|
|
|
|
|
|
|
|
command_result embark_tools_cmd (color_ostream &out, std::vector <std::string> & 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 ()
|
|
|
|
|
{
|
|
|
|
|
parent->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<df::interface_key> * 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
|
|
|
|
|
*/
|
|
|
|
|
#define FOR_ITER_TOOLS(iter) for(auto iter = tools.begin(); iter != tools.end(); iter++)
|
|
|
|
|
|
|
|
|
|
void update_embark_sidebar (df::viewscreen_choose_start_sitest * screen)
|
|
|
|
|
{
|
|
|
|
@ -159,238 +74,317 @@ void resize_embark (df::viewscreen_choose_start_sitest * screen, int dx, int dy)
|
|
|
|
|
update_embark_sidebar(screen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string sand_indicator = "";
|
|
|
|
|
bool sand_dirty = true; // Flag set when update is needed
|
|
|
|
|
void sand_update (df::viewscreen_choose_start_sitest * screen)
|
|
|
|
|
{
|
|
|
|
|
CoreSuspendClaimer suspend;
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
sand_indicator = "Sand";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sand_dirty = false;
|
|
|
|
|
}
|
|
|
|
|
typedef df::viewscreen_choose_start_sitest start_sitest;
|
|
|
|
|
typedef std::set<df::interface_key> ikey_set;
|
|
|
|
|
|
|
|
|
|
int sticky_pos[] = {0, 0, 3, 3};
|
|
|
|
|
bool sticky_moved = false;
|
|
|
|
|
void sticky_save (df::viewscreen_choose_start_sitest * screen)
|
|
|
|
|
class EmbarkTool
|
|
|
|
|
{
|
|
|
|
|
sticky_pos[0] = screen->location.embark_pos_min.x;
|
|
|
|
|
sticky_pos[1] = screen->location.embark_pos_max.x;
|
|
|
|
|
sticky_pos[2] = screen->location.embark_pos_min.y;
|
|
|
|
|
sticky_pos[3] = screen->location.embark_pos_max.y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sticky_apply (df::viewscreen_choose_start_sitest * screen)
|
|
|
|
|
{
|
|
|
|
|
if (screen->finder.finder_state != -1)
|
|
|
|
|
{
|
|
|
|
|
// Site finder is active - don't override default local position
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
screen->location.embark_pos_min.x = sticky_pos[0];
|
|
|
|
|
screen->location.embark_pos_max.x = sticky_pos[1];
|
|
|
|
|
screen->location.embark_pos_min.y = sticky_pos[2];
|
|
|
|
|
screen->location.embark_pos_max.y = sticky_pos[3];
|
|
|
|
|
update_embark_sidebar(screen);
|
|
|
|
|
}
|
|
|
|
|
protected:
|
|
|
|
|
bool enabled;
|
|
|
|
|
public:
|
|
|
|
|
EmbarkTool()
|
|
|
|
|
:enabled(false)
|
|
|
|
|
{ }
|
|
|
|
|
virtual bool getEnabled() { return enabled; }
|
|
|
|
|
virtual void setEnabled(bool state) { enabled = state; }
|
|
|
|
|
virtual void toggleEnabled() { setEnabled(!enabled); }
|
|
|
|
|
virtual std::string getId() = 0;
|
|
|
|
|
virtual std::string getName() = 0;
|
|
|
|
|
virtual std::string getDesc() = 0;
|
|
|
|
|
virtual df::interface_key getToggleKey() = 0;
|
|
|
|
|
virtual void before_render(start_sitest* screen) { };
|
|
|
|
|
virtual void after_render(start_sitest* screen) { };
|
|
|
|
|
virtual void before_feed(start_sitest* screen, ikey_set* input, bool &cancel) { };
|
|
|
|
|
virtual void after_feed(start_sitest* screen, ikey_set* input) { };
|
|
|
|
|
};
|
|
|
|
|
std::vector<EmbarkTool*> tools;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Viewscreen hooks
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void OutputString (int8_t color, int &x, int y, const std::string &text)
|
|
|
|
|
class SampleTool : public EmbarkTool
|
|
|
|
|
{
|
|
|
|
|
Screen::paintString(Screen::Pen(' ', color, 0), x, y, text);
|
|
|
|
|
x += text.length();
|
|
|
|
|
}
|
|
|
|
|
virtual std::string getId() { return "id"; }
|
|
|
|
|
virtual std::string getName() { return "Name"; }
|
|
|
|
|
virtual std::string getDesc() { return "Description"; }
|
|
|
|
|
virtual df::interface_key getToggleKey() { return df::interface_key::KEY; }
|
|
|
|
|
virtual void before_render(start_sitest* screen) { }
|
|
|
|
|
virtual void after_render(start_sitest* screen) { }
|
|
|
|
|
virtual void before_feed(start_sitest* screen, ikey_set* input, bool &cancel) { };
|
|
|
|
|
virtual void after_feed(start_sitest* screen, ikey_set* input) { };
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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<df::interface_key> *input))
|
|
|
|
|
class EmbarkAnywhere : public EmbarkTool
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
virtual std::string getId() { return "anywhere"; }
|
|
|
|
|
virtual std::string getName() { return "Embark anywhere"; }
|
|
|
|
|
virtual std::string getDesc() { return "Allows embarking anywhere on the world map"; }
|
|
|
|
|
virtual df::interface_key getToggleKey() { return df::interface_key::CUSTOM_A; }
|
|
|
|
|
virtual void after_render(start_sitest* screen)
|
|
|
|
|
{
|
|
|
|
|
bool prevent_default = false;
|
|
|
|
|
if (tool_enabled("anywhere"))
|
|
|
|
|
auto dim = Screen::getWindowSize();
|
|
|
|
|
int x = 20, y = dim.y - 2;
|
|
|
|
|
if (screen->page >= 0 && screen->page <= 4)
|
|
|
|
|
{
|
|
|
|
|
for (auto iter = input->begin(); iter != input->end(); iter++)
|
|
|
|
|
{
|
|
|
|
|
df::interface_key key = *iter;
|
|
|
|
|
if (key == df::interface_key::SETUP_EMBARK)
|
|
|
|
|
{
|
|
|
|
|
prevent_default = true;
|
|
|
|
|
this->in_embark_normal = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
OutputString(COLOR_WHITE, x, y, ": Embark!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (input->count(df::interface_key::CUSTOM_S))
|
|
|
|
|
}
|
|
|
|
|
virtual void before_feed(start_sitest* screen, ikey_set *input, bool &cancel)
|
|
|
|
|
{
|
|
|
|
|
if (input->count(df::interface_key::SETUP_EMBARK))
|
|
|
|
|
{
|
|
|
|
|
Screen::show(new embark_tools_settings);
|
|
|
|
|
return;
|
|
|
|
|
cancel = true;
|
|
|
|
|
screen->in_embark_normal = 1;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (tool_enabled("nano"))
|
|
|
|
|
class NanoEmbark : public EmbarkTool
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
virtual std::string getId() { return "nano"; }
|
|
|
|
|
virtual std::string getName() { return "Nano embark"; }
|
|
|
|
|
virtual std::string getDesc() { return "Allows the embark size to be decreased below 2x2"; }
|
|
|
|
|
virtual df::interface_key getToggleKey() { return df::interface_key::CUSTOM_N; }
|
|
|
|
|
virtual void before_feed(start_sitest* screen, ikey_set* input, bool &cancel)
|
|
|
|
|
{
|
|
|
|
|
for (auto iter = input->begin(); iter != input->end(); iter++)
|
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
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(this, dx, dy);
|
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
cancel = true;
|
|
|
|
|
resize_embark(screen, dx, dy);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (tool_enabled("sticky"))
|
|
|
|
|
class SandIndicator : public EmbarkTool
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
bool dirty;
|
|
|
|
|
std::string indicator;
|
|
|
|
|
void update_indicator()
|
|
|
|
|
{
|
|
|
|
|
CoreSuspendClaimer suspend;
|
|
|
|
|
buffered_color_ostream out;
|
|
|
|
|
Core::getInstance().runCommand(out, "prospect");
|
|
|
|
|
auto fragments = out.fragments();
|
|
|
|
|
indicator = "";
|
|
|
|
|
for (auto iter = fragments.begin(); iter != fragments.end(); iter++)
|
|
|
|
|
{
|
|
|
|
|
for (auto iter = input->begin(); iter != input->end(); iter++)
|
|
|
|
|
std::string fragment = iter->second;
|
|
|
|
|
if (fragment.find("SAND_") != std::string::npos)
|
|
|
|
|
{
|
|
|
|
|
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_moved)
|
|
|
|
|
{
|
|
|
|
|
sticky_save(this);
|
|
|
|
|
sticky_moved = true;
|
|
|
|
|
}
|
|
|
|
|
indicator = "Sand";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tool_enabled("sand"))
|
|
|
|
|
dirty = false;
|
|
|
|
|
}
|
|
|
|
|
public:
|
|
|
|
|
SandIndicator()
|
|
|
|
|
:EmbarkTool(),
|
|
|
|
|
dirty(true),
|
|
|
|
|
indicator("")
|
|
|
|
|
{ }
|
|
|
|
|
virtual void setEnabled(bool state)
|
|
|
|
|
{
|
|
|
|
|
EmbarkTool::setEnabled(state);
|
|
|
|
|
dirty = true;
|
|
|
|
|
}
|
|
|
|
|
virtual std::string getId() { return "sand"; }
|
|
|
|
|
virtual std::string getName() { return "Sand indicator"; }
|
|
|
|
|
virtual std::string getDesc() { return "Displays an indicator when sand is present on the given embark site"; }
|
|
|
|
|
virtual df::interface_key getToggleKey() { return df::interface_key::CUSTOM_S; }
|
|
|
|
|
virtual void after_render(start_sitest* screen)
|
|
|
|
|
{
|
|
|
|
|
if (dirty)
|
|
|
|
|
update_indicator();
|
|
|
|
|
auto dim = Screen::getWindowSize();
|
|
|
|
|
int x = dim.x - 28,
|
|
|
|
|
y = 13;
|
|
|
|
|
if (screen->page == 0)
|
|
|
|
|
{
|
|
|
|
|
sand_dirty = true;
|
|
|
|
|
OutputString(COLOR_YELLOW, x, y, indicator);
|
|
|
|
|
}
|
|
|
|
|
if (!prevent_default)
|
|
|
|
|
INTERPOSE_NEXT(feed)(input);
|
|
|
|
|
}
|
|
|
|
|
virtual void after_feed(start_sitest* screen, ikey_set* input)
|
|
|
|
|
{
|
|
|
|
|
dirty = true;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(void, render, ())
|
|
|
|
|
class StablePosition : public EmbarkTool
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
int prev_position[4];
|
|
|
|
|
bool moved_position;
|
|
|
|
|
void save_position(start_sitest* screen)
|
|
|
|
|
{
|
|
|
|
|
prev_position[0] = screen->location.embark_pos_min.x;
|
|
|
|
|
prev_position[1] = screen->location.embark_pos_max.x;
|
|
|
|
|
prev_position[2] = screen->location.embark_pos_min.y;
|
|
|
|
|
prev_position[3] = screen->location.embark_pos_max.y;
|
|
|
|
|
}
|
|
|
|
|
void restore_position(start_sitest* screen)
|
|
|
|
|
{
|
|
|
|
|
if (tool_enabled("sticky") && sticky_moved)
|
|
|
|
|
if (screen->finder.finder_state != -1)
|
|
|
|
|
{
|
|
|
|
|
sticky_apply(this);
|
|
|
|
|
sticky_moved = false;
|
|
|
|
|
// Site finder is active - don't override default local position
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
INTERPOSE_NEXT(render)();
|
|
|
|
|
|
|
|
|
|
auto dim = Screen::getWindowSize();
|
|
|
|
|
int x = 1,
|
|
|
|
|
y = dim.y - 5;
|
|
|
|
|
OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(df::interface_key::CUSTOM_S));
|
|
|
|
|
OutputString(COLOR_WHITE, x, y, ": Enabled: ");
|
|
|
|
|
std::list<std::string> parts;
|
|
|
|
|
for (int i = 0; i < NUM_TOOLS; i++)
|
|
|
|
|
screen->location.embark_pos_min.x = prev_position[0];
|
|
|
|
|
screen->location.embark_pos_max.x = prev_position[1];
|
|
|
|
|
screen->location.embark_pos_min.y = prev_position[2];
|
|
|
|
|
screen->location.embark_pos_max.y = prev_position[3];
|
|
|
|
|
update_embark_sidebar(screen);
|
|
|
|
|
}
|
|
|
|
|
public:
|
|
|
|
|
StablePosition()
|
|
|
|
|
:EmbarkTool(),
|
|
|
|
|
moved_position(false)
|
|
|
|
|
{
|
|
|
|
|
prev_position[0] = 0;
|
|
|
|
|
prev_position[1] = 0;
|
|
|
|
|
prev_position[2] = 3;
|
|
|
|
|
prev_position[3] = 3;
|
|
|
|
|
}
|
|
|
|
|
virtual std::string getId() { return "sticky"; }
|
|
|
|
|
virtual std::string getName() { return "Stable position"; }
|
|
|
|
|
virtual std::string getDesc() { return "Maintains the selected local area while navigating the world map"; }
|
|
|
|
|
virtual df::interface_key getToggleKey() { return df::interface_key::CUSTOM_P; }
|
|
|
|
|
virtual void before_render(start_sitest* screen) {
|
|
|
|
|
if (moved_position)
|
|
|
|
|
{
|
|
|
|
|
if (embark_tools[i].enabled)
|
|
|
|
|
{
|
|
|
|
|
parts.push_back(embark_tools[i].name);
|
|
|
|
|
parts.push_back(", ");
|
|
|
|
|
}
|
|
|
|
|
restore_position(screen);
|
|
|
|
|
moved_position = false;
|
|
|
|
|
}
|
|
|
|
|
if (parts.size())
|
|
|
|
|
}
|
|
|
|
|
virtual void before_feed(start_sitest* screen, ikey_set* input, bool &cancel) {
|
|
|
|
|
for (auto iter = input->begin(); iter != input->end(); iter++)
|
|
|
|
|
{
|
|
|
|
|
parts.pop_back(); // Remove trailing comma
|
|
|
|
|
for (auto iter = parts.begin(); iter != parts.end(); iter++)
|
|
|
|
|
df::interface_key key = *iter;
|
|
|
|
|
bool is_motion = false;
|
|
|
|
|
int dx = 0, dy = 0;
|
|
|
|
|
switch (key)
|
|
|
|
|
{
|
|
|
|
|
OutputString(COLOR_LIGHTMAGENTA, x, y, *iter);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
if (is_motion && !moved_position)
|
|
|
|
|
{
|
|
|
|
|
save_position(screen);
|
|
|
|
|
moved_position = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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 ()
|
|
|
|
|
{
|
|
|
|
|
parent->render();
|
|
|
|
|
int x, y;
|
|
|
|
|
auto dim = Screen::getWindowSize();
|
|
|
|
|
int width = 50,
|
|
|
|
|
height = 4 + 1 + tools.size(), // 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;
|
|
|
|
|
y = max_y - 2;
|
|
|
|
|
OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(df::interface_key::SELECT));
|
|
|
|
|
OutputString(COLOR_WHITE, x, y, "/");
|
|
|
|
|
OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(df::interface_key::LEAVESCREEN));
|
|
|
|
|
OutputString(COLOR_WHITE, x, y, ": Done");
|
|
|
|
|
y = min_y + 2;
|
|
|
|
|
FOR_ITER_TOOLS(iter)
|
|
|
|
|
{
|
|
|
|
|
OutputString(COLOR_LIGHTMAGENTA, x, y, "(none)");
|
|
|
|
|
EmbarkTool* t = *iter;
|
|
|
|
|
x = min_x + 2;
|
|
|
|
|
OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(t->getToggleKey()));
|
|
|
|
|
OutputString(COLOR_WHITE, x, y, ": " + t->getName() +
|
|
|
|
|
(t->getEnabled() ? ": Enabled" : ": Disabled"));
|
|
|
|
|
y++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tool_enabled("anywhere"))
|
|
|
|
|
};
|
|
|
|
|
void feed (std::set<df::interface_key> * input)
|
|
|
|
|
{
|
|
|
|
|
if (input->count(df::interface_key::SELECT) || input->count(df::interface_key::LEAVESCREEN))
|
|
|
|
|
{
|
|
|
|
|
x = 20; y = dim.y - 2;
|
|
|
|
|
if (this->page >= 0 && this->page <= 4)
|
|
|
|
|
{
|
|
|
|
|
// Only display on five map pages, not on site finder or notes
|
|
|
|
|
OutputString(COLOR_WHITE, x, y, ": Embark!");
|
|
|
|
|
}
|
|
|
|
|
Screen::dismiss(this);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (tool_enabled("sand"))
|
|
|
|
|
for (auto iter = input->begin(); iter != input->end(); iter++)
|
|
|
|
|
{
|
|
|
|
|
if (sand_dirty)
|
|
|
|
|
{
|
|
|
|
|
sand_update(this);
|
|
|
|
|
}
|
|
|
|
|
x = dim.x - 28; y = 13;
|
|
|
|
|
if (this->page == 0)
|
|
|
|
|
df::interface_key key = *iter;
|
|
|
|
|
FOR_ITER_TOOLS(iter)
|
|
|
|
|
{
|
|
|
|
|
OutputString(COLOR_YELLOW, x, y, sand_indicator);
|
|
|
|
|
EmbarkTool* t = *iter;
|
|
|
|
|
if (t->getToggleKey() == key)
|
|
|
|
|
{
|
|
|
|
|
t->toggleEnabled();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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++)
|
|
|
|
|
FOR_ITER_TOOLS(iter)
|
|
|
|
|
{
|
|
|
|
|
if (embark_tools[i].id == tool_name)
|
|
|
|
|
EmbarkTool* tool = *iter;
|
|
|
|
|
if (tool->getId() == tool_name)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
@ -398,10 +392,11 @@ bool tool_exists (std::string tool_name)
|
|
|
|
|
|
|
|
|
|
bool tool_enabled (std::string tool_name)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < NUM_TOOLS; i++)
|
|
|
|
|
FOR_ITER_TOOLS(iter)
|
|
|
|
|
{
|
|
|
|
|
if (embark_tools[i].id == tool_name)
|
|
|
|
|
return embark_tools[i].enabled;
|
|
|
|
|
EmbarkTool* tool = *iter;
|
|
|
|
|
if (tool->getId() == tool_name)
|
|
|
|
|
return tool->getEnabled();
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -409,42 +404,122 @@ 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++)
|
|
|
|
|
FOR_ITER_TOOLS(iter)
|
|
|
|
|
{
|
|
|
|
|
if (embark_tools[i].id == tool_name || tool_name == "all")
|
|
|
|
|
EmbarkTool* tool = *iter;
|
|
|
|
|
if (tool->getId() == tool_name || tool_name == "all")
|
|
|
|
|
{
|
|
|
|
|
embark_tools[i].enabled = enable_state;
|
|
|
|
|
tool_update(tool_name);
|
|
|
|
|
tool->setEnabled(enable_state);
|
|
|
|
|
n++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (bool)n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void tool_update (std::string tool_name)
|
|
|
|
|
struct choose_start_site_hook : df::viewscreen_choose_start_sitest
|
|
|
|
|
{
|
|
|
|
|
// Called whenever a tool is enabled/disabled
|
|
|
|
|
if (tool_name == "sand")
|
|
|
|
|
typedef df::viewscreen_choose_start_sitest interpose_base;
|
|
|
|
|
|
|
|
|
|
void display_tool_status()
|
|
|
|
|
{
|
|
|
|
|
auto dim = Screen::getWindowSize();
|
|
|
|
|
int x = 1,
|
|
|
|
|
y = dim.y - 5;
|
|
|
|
|
OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(df::interface_key::CUSTOM_S));
|
|
|
|
|
OutputString(COLOR_WHITE, x, y, ": Enabled: ");
|
|
|
|
|
std::list<std::string> parts;
|
|
|
|
|
FOR_ITER_TOOLS(iter)
|
|
|
|
|
{
|
|
|
|
|
EmbarkTool* tool = *iter;
|
|
|
|
|
if (tool->getEnabled())
|
|
|
|
|
{
|
|
|
|
|
parts.push_back(tool->getName());
|
|
|
|
|
parts.push_back(", ");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (parts.size())
|
|
|
|
|
{
|
|
|
|
|
parts.pop_back(); // Remove trailing comma
|
|
|
|
|
for (auto iter = parts.begin(); iter != parts.end(); iter++)
|
|
|
|
|
{
|
|
|
|
|
OutputString(COLOR_LIGHTMAGENTA, x, y, *iter);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
OutputString(COLOR_LIGHTMAGENTA, x, y, "(none)");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void display_settings()
|
|
|
|
|
{
|
|
|
|
|
sand_dirty = true;
|
|
|
|
|
Screen::show(new embark_tools_settings);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Plugin management
|
|
|
|
|
*/
|
|
|
|
|
inline bool is_valid_page()
|
|
|
|
|
{
|
|
|
|
|
return (page >= 0 && page <= 4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(void, feed, (std::set<df::interface_key> *input))
|
|
|
|
|
{
|
|
|
|
|
bool cancel = false;
|
|
|
|
|
FOR_ITER_TOOLS(iter)
|
|
|
|
|
{
|
|
|
|
|
EmbarkTool* tool = *iter;
|
|
|
|
|
if (tool->getEnabled())
|
|
|
|
|
tool->before_feed(this, input, cancel);
|
|
|
|
|
}
|
|
|
|
|
if (cancel)
|
|
|
|
|
return;
|
|
|
|
|
INTERPOSE_NEXT(feed)(input);
|
|
|
|
|
if (input->count(df::interface_key::CUSTOM_S) && is_valid_page())
|
|
|
|
|
display_settings();
|
|
|
|
|
FOR_ITER_TOOLS(iter)
|
|
|
|
|
{
|
|
|
|
|
EmbarkTool* tool = *iter;
|
|
|
|
|
if (tool->getEnabled())
|
|
|
|
|
tool->after_feed(this, input);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(void, render, ())
|
|
|
|
|
{
|
|
|
|
|
FOR_ITER_TOOLS(iter)
|
|
|
|
|
{
|
|
|
|
|
EmbarkTool* tool = *iter;
|
|
|
|
|
if (tool->getEnabled())
|
|
|
|
|
tool->before_render(this);
|
|
|
|
|
}
|
|
|
|
|
INTERPOSE_NEXT(render)();
|
|
|
|
|
display_tool_status();
|
|
|
|
|
FOR_ITER_TOOLS(iter)
|
|
|
|
|
{
|
|
|
|
|
EmbarkTool* tool = *iter;
|
|
|
|
|
if (tool->getEnabled())
|
|
|
|
|
tool->after_render(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(choose_start_site_hook, feed);
|
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(choose_start_site_hook, render);
|
|
|
|
|
|
|
|
|
|
DFHACK_PLUGIN("embark-tools");
|
|
|
|
|
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
|
|
|
|
|
|
|
|
|
|
command_result embark_tools_cmd (color_ostream &out, std::vector <std::string> & parameters);
|
|
|
|
|
|
|
|
|
|
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
|
|
|
|
|
{
|
|
|
|
|
tools.push_back(new EmbarkAnywhere);
|
|
|
|
|
tools.push_back(new NanoEmbark);
|
|
|
|
|
tools.push_back(new SandIndicator);
|
|
|
|
|
tools.push_back(new StablePosition);
|
|
|
|
|
std::string help = "";
|
|
|
|
|
help += "embark-tools (enable/disable) tool [tool...]\n"
|
|
|
|
|
"Tools:\n";
|
|
|
|
|
for (int i = 0; i < NUM_TOOLS; i++)
|
|
|
|
|
FOR_ITER_TOOLS(iter)
|
|
|
|
|
{
|
|
|
|
|
help += (" " + embark_tools[i].id + ": " + embark_tools[i].desc + "\n");
|
|
|
|
|
help += (" " + (*iter)->getId() + ": " + (*iter)->getDesc() + "\n");
|
|
|
|
|
}
|
|
|
|
|
commands.push_back(PluginCommand(
|
|
|
|
|
"embark-tools",
|
|
|
|
@ -504,10 +579,11 @@ command_result embark_tools_cmd (color_ostream &out, std::vector <std::string> &
|
|
|
|
|
if (is_enabled)
|
|
|
|
|
{
|
|
|
|
|
out << "Tool status:" << std::endl;
|
|
|
|
|
for (int i = 0; i < NUM_TOOLS; i++)
|
|
|
|
|
FOR_ITER_TOOLS(iter)
|
|
|
|
|
{
|
|
|
|
|
EmbarkTool t = embark_tools[i];
|
|
|
|
|
out << t.name << " (" << t.id << "): " << (t.enabled ? "Enabled" : "Disabled") << std::endl;
|
|
|
|
|
EmbarkTool* t = *iter;
|
|
|
|
|
out << t->getName() << " (" << t->getId() << "): "
|
|
|
|
|
<< (t->getEnabled() ? "Enabled" : "Disabled") << std::endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|