Skip to content
6 changes: 6 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ Template for new versions:
- `deathcause`: added functionality to this script to fetch cause of death programatically

## Fixes
- `confirm`: only show pause option for pausable confirmations
- `confirm`: when editing a uniform, confirm discard of changes when exiting with Escape
- `confirm`: when removing a manager order, show correct order description when using non-100% interface setting
- `confirm`: when removing a manager order, show correct order description after prior order removal or window resize (when scrolled to bottom of order list)
- `confirm`: when removing a manager order, show specific item/job type for ammo, shield, helm, gloves, shoes, trap component, and meal orders
- `confirm`: the pause option now pauses individual confirmation types, allowing multiple different confirmations to be paused independently
- `immortal-cravings`: prioritize high-value meals, properly split of portions, and don't go eating or drinking on a full stomach

## Misc Improvements
Expand Down
22 changes: 15 additions & 7 deletions confirm.lua
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ function ConfirmOverlay:init()
}
end
end
self.paused_confs = {}
end

function ConfirmOverlay:preUpdateLayout()
Expand All @@ -77,11 +78,14 @@ function ConfirmOverlay:preUpdateLayout()
end

function ConfirmOverlay:overlay_onupdate()
if self.paused_conf and
not dfhack.gui.matchFocusString(self.paused_conf.context,
for conf in pairs(self.paused_confs) do
if not dfhack.gui.matchFocusString(conf.context,
dfhack.gui.getDFViewscreen(true))
then
self.paused_conf = nil
then
self.paused_confs[conf] = nil
end
end
if not next(self.paused_confs) then
self.overlay_onupdate_max_freq_seconds = 300
end
end
Expand All @@ -108,19 +112,22 @@ function ConfirmOverlay:matches_conf(conf, keys, scr)
end

function ConfirmOverlay:onInput(keys)
if self.paused_conf or self.simulating then
if self.simulating then
return false
end
local scr = dfhack.gui.getDFViewscreen(true)
for id, conf in pairs(specs.REGISTRY) do
if specs.config.data[id].enabled and self:matches_conf(conf, keys, scr) then
if self.paused_confs[conf] then
return false
end
local mouse_pos = xy2pos(dfhack.screen.getMousePos())
local propagate_fn = function(pause)
if conf.on_propagate then
conf.on_propagate()
end
if pause then
self.paused_conf = conf
self.paused_confs[conf] = true
self.overlay_onupdate_max_freq_seconds = 0
end
if keys._MOUSE_L then
Expand All @@ -131,8 +138,9 @@ function ConfirmOverlay:onInput(keys)
gui.simulateInput(scr, keys)
self.simulating = false
end
local pause_fn = conf.pausable and curry(propagate_fn, true) or nil
dialogs.showYesNoPrompt(conf.title, utils.getval(conf.message):wrap(45), COLOR_YELLOW,
propagate_fn, nil, curry(propagate_fn, true), curry(dfhack.run_script, 'gui/confirm', tostring(conf.id)))
propagate_fn, nil, pause_fn, curry(dfhack.run_script, 'gui/confirm', tostring(conf.id)))
return true
end
end
Expand Down
93 changes: 70 additions & 23 deletions internal/confirm/specs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

local json = require('json')
local trade_internal = reqscript('internal/caravan/trade')
local gui = require('gui')

local CONFIG_FILE = 'dfhack-config/confirm.json'

Expand Down Expand Up @@ -325,13 +326,13 @@ ConfirmSpec{
id='uniform-discard-changes',
title='Discard uniform changes',
message='Are you sure you want to discard changes to this uniform?',
intercept_keys={'_MOUSE_L', '_MOUSE_R'},
intercept_keys={'LEAVESCREEN', '_MOUSE_L', '_MOUSE_R'},
-- sticks out the left side so it can move with the panel
-- when the screen is resized too narrow
intercept_frame={r=32, t=19, w=101, b=3},
context='dwarfmode/Squads/Equipment/Customizing/Default',
predicate=function(keys, mouse_offset)
if keys._MOUSE_R then
if keys.LEAVESCREEN or keys._MOUSE_R then
return uniform_has_changes()
end
if clicked_on_confirm_button(mouse_offset) then
Expand Down Expand Up @@ -430,7 +431,7 @@ ConfirmSpec{
end,
}

local function make_order_desc(order, noun)
local function make_order_material_desc(order, noun)
local desc = ''
if order.mat_type >= 0 then
local matinfo = dfhack.matinfo.decode(order.mat_type, order.mat_index)
Expand All @@ -451,35 +452,81 @@ end
local orders = df.global.world.manager_orders.all
local itemdefs = df.global.world.raws.itemdefs
local reactions = df.global.world.raws.reactions.reactions

local meal_type_by_ingredient_count = {
[2] = 'easy',
[3] = 'fine',
[4] = 'lavish',
}

local function make_order_desc(order)
if order.job_type == df.job_type.CustomReaction then
for _, reaction in ipairs(reactions) do
if reaction.code == order.reaction_name then
return reaction.name
end
end
return ''
elseif order.job_type == df.job_type.PrepareMeal then
-- DF uses mat_type as ingredient count?
local meal_type = meal_type_by_ingredient_count[order.mat_type]
if meal_type then
return 'prepare ' .. meal_type .. ' meal'
end
return 'prepare meal'
end
local noun
if order.job_type == df.job_type.MakeArmor then
noun = itemdefs.armor[order.item_subtype].name
elseif order.job_type == df.job_type.MakeWeapon then
noun = itemdefs.weapons[order.item_subtype].name
elseif order.job_type == df.job_type.MakeShield then
noun = itemdefs.shields[order.item_subtype].name
elseif order.job_type == df.job_type.MakeAmmo then
noun = itemdefs.ammo[order.item_subtype].name
elseif order.job_type == df.job_type.MakeHelm then
noun = itemdefs.helms[order.item_subtype].name
elseif order.job_type == df.job_type.MakeGloves then
noun = itemdefs.gloves[order.item_subtype].name
elseif order.job_type == df.job_type.MakePants then
noun = itemdefs.pants[order.item_subtype].name
elseif order.job_type == df.job_type.MakeShoes then
noun = itemdefs.shoes[order.item_subtype].name
elseif order.job_type == df.job_type.MakeTool then
noun = itemdefs.tools[order.item_subtype].name
elseif order.job_type == df.job_type.MakeTrapComponent then
noun = itemdefs.trapcomps[order.item_subtype].name
elseif order.job_type == df.job_type.SmeltOre then
noun = 'ore'
else
-- caption is usually "verb noun(-phrase)"
noun = df.job_type.attrs[order.job_type].caption
end
return make_order_material_desc(order, noun)
end

ConfirmSpec{
id='order-remove',
title='Remove manger order',
message=function()
local order_desc = ''
local scroll_pos = mi.info.work_orders.scroll_position_work_orders
local y_offset = dfhack.screen.getWindowSize() > 154 and 8 or 10
local ir = gui.get_interface_rect()
local y_offset = ir.width > 154 and 8 or 10
local order_rows = (ir.height - y_offset - 9) // 3
local max_scroll_pos = math.max(0, #orders - order_rows) -- DF keeps list view "full" (no empty rows at bottom), if possible
if scroll_pos > max_scroll_pos then
-- sometimes, DF does not adjust scroll_position_work_orders (when
-- scrolled to bottom: order removed, or list view height grew);
-- compensate to keep order_idx in sync (and in bounds)
scroll_pos = max_scroll_pos
end
local _, y = dfhack.screen.getMousePos()
if y then
local order_idx = scroll_pos + (y - y_offset) // 3
local order = orders[order_idx]
if order.job_type == df.job_type.CustomReaction then
for _, reaction in ipairs(reactions) do
if reaction.code == order.reaction_name then
order_desc = reaction.name
end
end
elseif order.job_type == df.job_type.MakeArmor then
order_desc = make_order_desc(order, itemdefs.armor[order.item_subtype].name)
elseif order.job_type == df.job_type.MakeWeapon then
order_desc = make_order_desc(order, itemdefs.weapons[order.item_subtype].name)
elseif order.job_type == df.job_type.MakePants then
order_desc = make_order_desc(order, itemdefs.pants[order.item_subtype].name)
elseif order.job_type == df.job_type.SmeltOre then
order_desc = make_order_desc(order, 'ore')
elseif order.job_type == df.job_type.MakeTool then
order_desc = make_order_desc(order, itemdefs.tools[order.item_subtype].name)
else
order_desc = make_order_desc(order, df.job_type.attrs[order.job_type].caption)
local order = safe_index(orders, order_idx)
if order then
order_desc = make_order_desc(order)
end
end
return ('Are you sure you want to remove this manager order?\n\n%s'):format(dfhack.capitalizeStringWords(order_desc))
Expand Down
Loading