Merge pull request #3781 from Halifay/work_orders_manager_enhancement

Work orders manager enhancement
develop
Myk 2023-09-29 09:58:44 -07:00 committed by GitHub
commit 183ff83f69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 153 additions and 2 deletions

@ -10,6 +10,13 @@ work (e.g. links from the `changelog`).
:local:
:depth: 1
.. _workorder-recheck:
workorder-recheck
=================
Tool to set 'Checking' status of the selected work order, allowing conditions to be
reevaluated. Merged into `orders`.
.. _autohauler:
autohauler

@ -17,6 +17,13 @@ Usage
manager orders. It will not clear the orders that already exist.
``orders clear``
Deletes all manager orders in the current embark.
``orders recheck [this]``
Sets the status to ``Checking`` (from ``Active``) for all work orders. if the
"this" option is passed, only sets the status for the workorder whose condition
details page is open. This makes the manager reevaluate its conditions.
This is especially useful for an order that had its conditions met when it
was started, but the requisite items have since disappeared and the workorder
is now generating job cancellation spam.
``orders sort``
Sorts current manager orders by repeat frequency so repeating orders don't
prevent one-time orders from ever being completed. The sorting order is:

@ -62,12 +62,16 @@ local function do_export()
}:show()
end
local function do_recheck()
dfhack.run_command('orders', 'recheck')
end
OrdersOverlay = defclass(OrdersOverlay, overlay.OverlayWidget)
OrdersOverlay.ATTRS{
default_pos={x=53,y=-6},
default_enabled=true,
viewscreens='dwarfmode/Info/WORK_ORDERS/Default',
frame={w=30, h=4},
frame={w=46, h=4},
}
function OrdersOverlay:init()
@ -95,13 +99,20 @@ function OrdersOverlay:init()
},
widgets.HotkeyLabel{
frame={t=0, l=15},
label='recheck',
key='CUSTOM_CTRL_R',
auto_width=true,
on_activate=do_recheck,
},
widgets.HotkeyLabel{
frame={t=1, l=15},
label='sort',
key='CUSTOM_CTRL_O',
auto_width=true,
on_activate=do_sort,
},
widgets.HotkeyLabel{
frame={t=1, l=15},
frame={t=0, l=31},
label='clear',
key='CUSTOM_CTRL_C',
auto_width=true,
@ -157,7 +168,91 @@ function OrdersOverlay:render(dc)
OrdersOverlay.super.render(self, dc)
end
-- Resets the selected work order to the `Checking` state
local function set_current_inactive()
local scrConditions = df.global.game.main_interface.info.work_orders.conditions
if scrConditions.open then
dfhack.run_command('orders', 'recheck', 'this')
else
qerror("Order conditions is not open")
end
end
local function is_current_active()
local scrConditions = df.global.game.main_interface.info.work_orders.conditions
local order = scrConditions.wq
return order.status.active
end
-- -------------------
-- RecheckOverlay
--
local focusString = 'dwarfmode/Info/WORK_ORDERS/Conditions'
RecheckOverlay = defclass(RecheckOverlay, overlay.OverlayWidget)
RecheckOverlay.ATTRS{
default_pos={x=6,y=8},
default_enabled=true,
viewscreens=focusString,
-- width is the sum of lengths of `[` + `Ctrl+A` + `: ` + button.label + `]`
frame={w=1 + 6 + 2 + 16 + 1, h=3},
}
local function areTabsInTwoRows()
-- get the tile above the order status icon
local pen = dfhack.screen.readTile(7, 7, false)
-- in graphics mode, `0` when one row, something else when two (`67` aka 'C' from "Creatures")
-- in ASCII mode, `32` aka ' ' when one row, something else when two (`196` aka '-' from tab frame's top)
return (pen.ch ~= 0 and pen.ch ~= 32)
end
function RecheckOverlay:updateTextButtonFrame()
local twoRows = areTabsInTwoRows()
if (self._twoRows == twoRows) then return false end
self._twoRows = twoRows
local frame = twoRows
and {b=0, l=0, r=0, h=1}
or {t=0, l=0, r=0, h=1}
self.subviews.button.frame = frame
return true
end
function RecheckOverlay:init()
self:addviews{
widgets.TextButton{
view_id = 'button',
-- frame={t=0, l=0, r=0, h=1}, -- is set in `updateTextButtonFrame()`
label='request re-check',
key='CUSTOM_CTRL_A',
on_activate=set_current_inactive,
enabled=is_current_active,
},
}
self:updateTextButtonFrame()
end
function RecheckOverlay:onRenderBody(dc)
if (self.frame_rect.y1 == 7) then
-- only apply this logic if the overlay is on the same row as
-- originally thought: just above the order status icon
if self:updateTextButtonFrame() then
self:updateLayout()
end
end
RecheckOverlay.super.onRenderBody(self, dc)
end
-- -------------------
OVERLAY_WIDGETS = {
recheck=RecheckOverlay,
overlay=OrdersOverlay,
}

@ -10,6 +10,7 @@
#include "json/json.h"
#include "df/building.h"
#include "df/gamest.h"
#include "df/historical_figure.h"
#include "df/itemdef_ammost.h"
#include "df/itemdef_armorst.h"
@ -36,6 +37,8 @@
using namespace DFHack;
using namespace df::enums;
using df::global::game;
DFHACK_PLUGIN("orders");
REQUIRE_GLOBAL(world);
@ -64,6 +67,8 @@ static command_result orders_export_command(color_ostream & out, const std::stri
static command_result orders_import_command(color_ostream & out, const std::string & name);
static command_result orders_clear_command(color_ostream & out);
static command_result orders_sort_command(color_ostream & out);
static command_result orders_recheck_command(color_ostream & out);
static command_result orders_recheck_current_command(color_ostream & out);
static command_result orders_command(color_ostream & out, std::vector<std::string> & parameters)
{
@ -111,6 +116,19 @@ static command_result orders_command(color_ostream & out, std::vector<std::strin
return orders_sort_command(out);
}
if (parameters[0] == "recheck" && parameters.size() == 1)
{
return orders_recheck_command(out);
}
if (parameters[0] == "recheck" && parameters.size() == 2)
{
if (parameters[1] == "this")
{
return orders_recheck_current_command(out);
}
}
return CR_WRONG_USAGE;
}
@ -1015,3 +1033,27 @@ static command_result orders_sort_command(color_ostream & out)
return CR_OK;
}
static command_result orders_recheck_command(color_ostream & out)
{
for (auto it : world->manager_orders)
{
it->status.bits.active = false;
it->status.bits.validated = false;
}
return CR_OK;
}
static command_result orders_recheck_current_command(color_ostream & out)
{
if (game->main_interface.info.work_orders.conditions.open)
{
game->main_interface.info.work_orders.conditions.wq->status.bits.active = false;
}
else
{
out << COLOR_LIGHTRED << "Order conditions is not open" << std::endl;
return CR_FAILURE;
}
return CR_OK;
}