|
|
|
@ -45,6 +45,7 @@
|
|
|
|
|
#include "df/reaction_reagent_flags.h"
|
|
|
|
|
#include "df/viewscreen_layer_assigntradest.h"
|
|
|
|
|
#include "df/viewscreen_tradegoodsst.h"
|
|
|
|
|
#include "df/viewscreen_layer_militaryst.h"
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
@ -61,6 +62,7 @@ using df::global::ui_menu_width;
|
|
|
|
|
using df::global::ui_area_map_width;
|
|
|
|
|
|
|
|
|
|
using namespace DFHack::Gui;
|
|
|
|
|
using Screen::Pen;
|
|
|
|
|
|
|
|
|
|
static command_result tweak(color_ostream &out, vector <string> & parameters);
|
|
|
|
|
|
|
|
|
@ -114,6 +116,13 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
|
|
|
|
|
" tweak fast-trade [disable]\n"
|
|
|
|
|
" Makes Shift-Enter in the Move Goods to Depot and Trade screens select\n"
|
|
|
|
|
" the current item (fully, in case of a stack), and scroll down one line.\n"
|
|
|
|
|
" tweak military-stable-assign [disable]\n"
|
|
|
|
|
" Preserve list order and cursor position when assigning to squad,\n"
|
|
|
|
|
" i.e. stop the rightmost list of the Positions page of the military\n"
|
|
|
|
|
" screen from constantly jumping to the top.\n"
|
|
|
|
|
" tweak military-color-assigned [disable]\n"
|
|
|
|
|
" Color squad candidates already assigned to other squads in brown/green\n"
|
|
|
|
|
" to make them stand out more in the list.\n"
|
|
|
|
|
));
|
|
|
|
|
return CR_OK;
|
|
|
|
|
}
|
|
|
|
@ -540,6 +549,101 @@ struct fast_trade_select_hook : df::viewscreen_tradegoodsst {
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(fast_trade_select_hook, feed);
|
|
|
|
|
|
|
|
|
|
struct military_assign_hook : df::viewscreen_layer_militaryst {
|
|
|
|
|
typedef df::viewscreen_layer_militaryst interpose_base;
|
|
|
|
|
|
|
|
|
|
inline bool inPositionsMode() {
|
|
|
|
|
return page == Positions && !(in_create_squad || in_new_squad);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input))
|
|
|
|
|
{
|
|
|
|
|
if (inPositionsMode() && !layer_objects[0]->active)
|
|
|
|
|
{
|
|
|
|
|
auto pos_list = layer_objects[1];
|
|
|
|
|
auto plist = layer_objects[2];
|
|
|
|
|
auto &cand = positions.candidates;
|
|
|
|
|
|
|
|
|
|
// Save the candidate list and cursors
|
|
|
|
|
std::vector<df::unit*> copy = cand;
|
|
|
|
|
int cursor = plist->getListCursor();
|
|
|
|
|
int pos_cursor = pos_list->getListCursor();
|
|
|
|
|
|
|
|
|
|
INTERPOSE_NEXT(feed)(input);
|
|
|
|
|
|
|
|
|
|
if (inPositionsMode() && !layer_objects[0]->active)
|
|
|
|
|
{
|
|
|
|
|
bool is_select = input->count(interface_key::SELECT);
|
|
|
|
|
|
|
|
|
|
// Resort the candidate list and restore cursor
|
|
|
|
|
// on add to squad OR scroll in the position list.
|
|
|
|
|
if (!plist->active || is_select)
|
|
|
|
|
{
|
|
|
|
|
// Since we don't know the actual sorting order, preserve
|
|
|
|
|
// the ordering of the items in the list before keypress.
|
|
|
|
|
// This does the right thing even if the list was sorted
|
|
|
|
|
// with sort-units.
|
|
|
|
|
std::set<df::unit*> prev, next;
|
|
|
|
|
prev.insert(copy.begin(), copy.end());
|
|
|
|
|
next.insert(cand.begin(), cand.end());
|
|
|
|
|
std::vector<df::unit*> out;
|
|
|
|
|
|
|
|
|
|
// (old-before-cursor) (new) |cursor| (old-after-cursor)
|
|
|
|
|
for (int i = 0; i < cursor && i < (int)copy.size(); i++)
|
|
|
|
|
if (next.count(copy[i])) out.push_back(copy[i]);
|
|
|
|
|
for (size_t i = 0; i < cand.size(); i++)
|
|
|
|
|
if (!prev.count(cand[i])) out.push_back(cand[i]);
|
|
|
|
|
int new_cursor = out.size();
|
|
|
|
|
for (int i = cursor; i < (int)copy.size(); i++)
|
|
|
|
|
if (next.count(copy[i])) out.push_back(copy[i]);
|
|
|
|
|
|
|
|
|
|
cand.swap(out);
|
|
|
|
|
plist->setListLength(cand.size());
|
|
|
|
|
if (new_cursor < (int)cand.size())
|
|
|
|
|
plist->setListCursor(new_cursor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Preserve the position list index on remove from squad
|
|
|
|
|
if (pos_list->active && is_select)
|
|
|
|
|
pos_list->setListCursor(pos_cursor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
INTERPOSE_NEXT(feed)(input);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(void, render, ())
|
|
|
|
|
{
|
|
|
|
|
INTERPOSE_NEXT(render)();
|
|
|
|
|
|
|
|
|
|
if (inPositionsMode())
|
|
|
|
|
{
|
|
|
|
|
auto plist = layer_objects[2];
|
|
|
|
|
int x1 = plist->getX1(), y1 = plist->getY1();
|
|
|
|
|
int x2 = plist->getX2(), y2 = plist->getY2();
|
|
|
|
|
int i1 = plist->getFirstVisible(), i2 = plist->getLastVisible();
|
|
|
|
|
|
|
|
|
|
for (int y = y1, i = i1; i <= i2; i++, y++)
|
|
|
|
|
{
|
|
|
|
|
auto unit = vector_get(positions.candidates, i);
|
|
|
|
|
if (!unit || unit->military.squad_index < 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
for (int x = x1; x <= x2; x++)
|
|
|
|
|
{
|
|
|
|
|
Pen cur_tile = Screen::readTile(x, y);
|
|
|
|
|
if (!cur_tile.valid()) continue;
|
|
|
|
|
cur_tile.fg = (cur_tile.fg == COLOR_GREY ? COLOR_BROWN : COLOR_GREEN);
|
|
|
|
|
Screen::paintTile(cur_tile, x, y);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(military_assign_hook, feed);
|
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(military_assign_hook, render);
|
|
|
|
|
|
|
|
|
|
static void enable_hook(color_ostream &out, VMethodInterposeLinkBase &hook, vector <string> ¶meters)
|
|
|
|
|
{
|
|
|
|
|
if (vector_get(parameters, 1) == "disable")
|
|
|
|
@ -704,6 +808,14 @@ static command_result tweak(color_ostream &out, vector <string> ¶meters)
|
|
|
|
|
enable_hook(out, INTERPOSE_HOOK(fast_trade_assign_hook, feed), parameters);
|
|
|
|
|
enable_hook(out, INTERPOSE_HOOK(fast_trade_select_hook, feed), parameters);
|
|
|
|
|
}
|
|
|
|
|
else if (cmd == "military-stable-assign")
|
|
|
|
|
{
|
|
|
|
|
enable_hook(out, INTERPOSE_HOOK(military_assign_hook, feed), parameters);
|
|
|
|
|
}
|
|
|
|
|
else if (cmd == "military-color-assigned")
|
|
|
|
|
{
|
|
|
|
|
enable_hook(out, INTERPOSE_HOOK(military_assign_hook, render), parameters);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return CR_WRONG_USAGE;
|
|
|
|
|
|
|
|
|
|