diff --git a/plugins/trackstop.cpp b/plugins/trackstop.cpp index 455b53774..4676a1b52 100644 --- a/plugins/trackstop.cpp +++ b/plugins/trackstop.cpp @@ -6,6 +6,7 @@ #include "uicommon.h" #include "LuaTools.h" +#include "df/building_rollersst.h" #include "df/building_trapst.h" #include "df/viewscreen_dwarfmodest.h" @@ -16,8 +17,10 @@ using namespace std; using df::global::world; using df::global::ui; +using df::building_rollersst; using df::building_trapst; using df::enums::trap_type::trap_type; +using df::enums::screw_pump_direction::screw_pump_direction; DFHACK_PLUGIN("trackstop"); @@ -162,8 +165,106 @@ struct trackstop_hook : public df::viewscreen_dwarfmodest { } }; +struct roller_hook : public df::viewscreen_dwarfmodest { + typedef df::viewscreen_dwarfmodest interpose_base; + + enum Speed { + Lowest = 10000, + Low = 20000, + Medium = 30000, + High = 40000, + Highest = 50000 + }; + + building_rollersst *get_selected_roller() { + if (!Gui::dwarfmode_hotkey(Core::getTopViewscreen()) || ui->main.mode != ui_sidebar_mode::QueryBuilding) { + return nullptr; + } + + building_rollersst *roller = virtual_cast(world->selected_building); + if (roller && roller->construction_stage) { + return roller; + } + + return nullptr; + } + + bool handleInput(set *input) { + building_rollersst *roller = get_selected_roller(); + if (!roller) { + return false; + } + + if (input->count(interface_key::BUILDING_ORIENT_NONE)) { + // Flip roller orientation. + // Long rollers can only be oriented along their length. + // Todo: Only add 1 to 1x1 rollers: x ^= ((x&1)<<1)|1 + // Todo: This could have been elegant without all the casting, + // but as an enum it might be better off listing each case. + roller->direction = (df::enums::screw_pump_direction::screw_pump_direction)(((int8_t)roller->direction) ^ 2); + return true; + } else if (input->count(interface_key::BUILDING_ROLLERS_SPEED_UP)) { + if (roller->speed < Speed::Highest) { + roller->speed += Speed::Lowest; + } + + return true; + } else if (input->count(interface_key::BUILDING_ROLLERS_SPEED_DOWN)) { + if (roller->speed > Speed::Lowest) { + roller->speed -= Speed::Lowest; + } + + return true; + } + + return false; + } + + DEFINE_VMETHOD_INTERPOSE(void, feed, (set *input)) { + if (!handleInput(input)) { + INTERPOSE_NEXT(feed)(input); + } + } + + DEFINE_VMETHOD_INTERPOSE(void, render, ()) { + INTERPOSE_NEXT(render)(); + + building_rollersst *roller = get_selected_roller(); + if (roller) { + auto dims = Gui::getDwarfmodeViewDims(); + int left_margin = dims.menu_x1 + 1; + int x = left_margin; + int y = dims.y1 + 6; + + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(interface_key::BUILDING_ORIENT_NONE)); + OutputString(COLOR_WHITE, x, y, ": Rolls ", false); + OutputString(COLOR_WHITE, x, y, ( + (roller->direction == screw_pump_direction::FromNorth)? "Southward": + (roller->direction == screw_pump_direction::FromEast)? "Westward": + (roller->direction == screw_pump_direction::FromSouth)? "Northward": + (roller->direction == screw_pump_direction::FromWest)? "Eastward": + "" + ), true, left_margin); + + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(interface_key::BUILDING_ROLLERS_SPEED_DOWN)); + OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(interface_key::BUILDING_ROLLERS_SPEED_UP)); + OutputString(COLOR_WHITE, x, y, ": "); + OutputString(COLOR_WHITE, x, y, ( + (roller->speed <= Speed::Lowest)? "Lowest": + (roller->speed <= Speed::Low)? "Low": + (roller->speed <= Speed::Medium)? "Medium": + (roller->speed <= Speed::High)? "High": + "Highest" + )); + OutputString(COLOR_WHITE, x, y, " Speed", true, left_margin); + } + } +}; + IMPLEMENT_VMETHOD_INTERPOSE(trackstop_hook, feed); IMPLEMENT_VMETHOD_INTERPOSE(trackstop_hook, render); +IMPLEMENT_VMETHOD_INTERPOSE(roller_hook, feed); +IMPLEMENT_VMETHOD_INTERPOSE(roller_hook, render); DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) { @@ -178,7 +279,9 @@ DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) { } if (!INTERPOSE_HOOK(trackstop_hook, feed).apply(enable) || - !INTERPOSE_HOOK(trackstop_hook, render).apply(enable)) { + !INTERPOSE_HOOK(trackstop_hook, render).apply(enable) || + !INTERPOSE_HOOK(roller_hook, feed).apply(enable) || + !INTERPOSE_HOOK(roller_hook, render).apply(enable)) { out.printerr("Could not %s trackstop hooks!\n", enable? "insert": "remove"); return CR_FAILURE; }