Skip to content

confirm fixes: pausing, Escape from uniform, order-remove descriptions #1446

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
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:
## Fixes
- `starvingdead`: properly restore to correct enabled state when loading a new game that is different from the first game loaded in this session
- `starvingdead`: ensure undead decay does not happen faster than the declared decay rate when saving and loading the game
- `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

## 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