Skip to content

Commit e1023c4

Browse files
committed
implement import/export/autoload for work details
1 parent 304fc9f commit e1023c4

File tree

4 files changed

+202
-65
lines changed

4 files changed

+202
-65
lines changed

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Template for new versions:
2929
## New Tools
3030

3131
## New Features
32+
- `gui/settings-manager`: add import, export, and autoload for work details
3233

3334
## Fixes
3435

docs/gui/settings-manager.rst

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@ Usage
1616
gui/settings-manager load-difficulty
1717
gui/settings-manager save-standing-orders
1818
gui/settings-manager load-standing-orders
19+
gui/settings-manager save-work-details
20+
gui/settings-manager load-work-details
1921

2022
Difficulty can be saved and loaded on the embark "preparation" screen or in an
21-
active fort. Standing orders can only be saved and loaded in an active fort.
23+
active fort. Standing orders and work details can only be saved and loaded in
24+
an active fort.
2225

2326
If auto-restoring of difficulty settings is turned on, it happens when the
24-
embark "preparation" screen is loaded. If auto-restoring of standing orders
25-
settings is turned on, it happens when the fort is loaded for the first time
26-
(just like all other Autostart commands configured in `gui/control-panel`).
27+
embark "preparation" screen is loaded. If auto-restoring of standing orders or
28+
work details definitions is turned on, it happens when the fort is loaded for
29+
the first time (just like all other Autostart commands configured in
30+
`gui/control-panel`).
2731

2832
Overlays
2933
--------
@@ -39,3 +43,12 @@ You will see a new panel that allows you to save and restore your settings for
3943
standing orders. You can also toggle whether the saved standing orders are
4044
automatically restored when you embark on a new fort. This will toggle the
4145
relevant command in `gui/control-panel` on the Automation -> Autostart page.
46+
47+
There is a similar panel on the Labor -> Work Details page that allows for
48+
saving and restoring of work detail definitons. Be aware that work detail
49+
assignments to units cannot be saved, so you have to assign the work details to
50+
individual units after you restore the definitions. Another caveat is that DF
51+
doesn't evaluate work detail definitions until a change (any change) is made on
52+
the work details screen. Therefore, after importing work detail definitions,
53+
including auto-loading them for new embarks, you have to go to the work details
54+
page and make a change before your imported work details will take effect.

gui/settings-manager.lua

Lines changed: 182 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -227,54 +227,30 @@ function DifficultySettingsOverlay:get_df_struct()
227227
end
228228

229229
------------------------------
230-
-- StandingOrdersOverlay
230+
-- ImportExportAutoOverlay
231231
--
232232

233-
StandingOrdersOverlay = defclass(StandingOrdersOverlay, overlay.OverlayWidget)
234-
StandingOrdersOverlay.ATTRS {
235-
desc='Adds buttons to the standing orders screen for saving and restoring settings.',
236-
default_pos={x=6, y=-5},
237-
viewscreens='dwarfmode/Info/LABOR/STANDING_ORDERS/AUTOMATED_WORKSHOPS',
233+
ImportExportAutoOverlay = defclass(ImportExportAutoOverlay, overlay.OverlayWidget)
234+
ImportExportAutoOverlay.ATTRS {
238235
default_enabled=true,
239-
frame={w=78, h=5},
240236
frame_style=gui.MEDIUM_FRAME,
241237
frame_background=gui.CLEAR_PEN,
238+
save_label=DEFAULT_NIL,
239+
load_label=DEFAULT_NIL,
240+
auto_label=DEFAULT_NIL,
241+
save_fn=DEFAULT_NIL,
242+
load_fn=DEFAULT_NIL,
243+
has_data_fn=DEFAULT_NIL,
244+
autostart_command=DEFAULT_NIL,
242245
}
243246

244-
local li = df.global.plotinfo.labor_info
245-
246-
local function save_standing_orders()
247-
local standing_orders = {}
248-
for name, val in pairs(df.global) do
249-
if name:startswith('standing_orders_') then
250-
standing_orders[name] = val
251-
end
252-
end
253-
config.data.standing_orders = standing_orders
254-
local chores = {}
255-
chores.enabled = li.flags.children_do_chores
256-
chores.labors = utils.clone(li.chores)
257-
config.data.chores = chores
258-
config:write()
259-
end
260-
261-
local function load_standing_orders()
262-
for name, val in pairs(config.data.standing_orders or {}) do
263-
df.global[name] = val
264-
end
265-
li.flags.children_do_chores = not not safe_index(config.data.chores, 'enabled')
266-
for i, val in ipairs(safe_index(config.data.chores, 'labors') or {}) do
267-
li.chores[i-1] = val
268-
end
269-
end
270-
271-
function StandingOrdersOverlay:init()
247+
function ImportExportAutoOverlay:init()
272248
self:addviews{
273249
widgets.HotkeyLabel{
274250
view_id='save',
275251
frame={l=0, t=0, w=39},
276252
key='CUSTOM_CTRL_E',
277-
label='Save standing orders (all tabs)',
253+
label=self.save_label,
278254
on_activate=self:callback('do_save'),
279255
},
280256
widgets.Label{
@@ -288,9 +264,9 @@ function StandingOrdersOverlay:init()
288264
view_id='load',
289265
frame={l=42, t=0, w=34},
290266
key='CUSTOM_CTRL_I',
291-
label='Load saved standing orders',
267+
label=self.load_label,
292268
on_activate=self:callback('do_load'),
293-
enabled=function() return next(config.data.standing_orders or {}) end,
269+
enabled=self.has_data_fn,
294270
},
295271
widgets.Label{
296272
view_id='load_flash',
@@ -303,38 +279,37 @@ function StandingOrdersOverlay:init()
303279
view_id='auto',
304280
frame={l=0, t=2},
305281
key='CUSTOM_CTRL_A',
306-
label='Apply saved settings for new embarks:',
282+
label=self.auto_label,
307283
on_change=self:callback('do_auto'),
308-
enabled=function() return next(config.data.standing_orders or {}) end,
284+
enabled=self.has_data_fn,
309285
},
310286
}
311287
end
312288

313-
function StandingOrdersOverlay:do_save()
289+
function ImportExportAutoOverlay:do_save()
314290
flash(self, 'save')
315-
save_standing_orders()
291+
self.save_fn()
316292
end
317293

318-
function StandingOrdersOverlay:do_load()
294+
function ImportExportAutoOverlay:do_load()
319295
flash(self, 'load')
320-
load_standing_orders()
296+
self.load_fn()
321297
end
322298

323-
local autostart_command = 'gui/settings-manager load-standing-orders'
324-
325-
SOMessage = defclass(SOMessage, widgets.Window)
326-
SOMessage.ATTRS {
299+
AutoMessage = defclass(AutoMessage, widgets.Window)
300+
AutoMessage.ATTRS {
327301
frame={w=61, h=9},
302+
autostart_command=DEFAULT_NIL,
328303
enabled=DEFAULT_NIL,
329304
}
330305

331-
function SOMessage:init()
306+
function AutoMessage:init()
332307
self:addviews{
333308
widgets.Label{
334309
view_id='label',
335310
frame={t=0, l=0},
336311
text={
337-
'The "', autostart_command, '" command', NEWLINE,
312+
'The "', self.autostart_command, '" command', NEWLINE,
338313
'has been ',
339314
{text=self.enabled and 'enabled' or 'disabled', pen=self.enabled and COLOR_GREEN or COLOR_LIGHTRED},
340315
' in the ',
@@ -363,37 +338,173 @@ function SOMessage:init()
363338
}
364339
end
365340

366-
SOMessageScreen = defclass(SOMessageScreen, gui.ZScreenModal)
367-
SOMessageScreen.ATTRS {
341+
AutoMessageScreen = defclass(AutoMessageScreen, gui.ZScreenModal)
342+
AutoMessageScreen.ATTRS {
368343
focus_path='settings-manager/prompt',
344+
autostart_command=DEFAULT_NIL,
369345
enabled=DEFAULT_NIL,
370346
}
371347

372-
function SOMessageScreen:init()
348+
function AutoMessageScreen:init()
373349
self:addviews{
374-
SOMessage{
350+
AutoMessage{
375351
frame_title=(self.enabled and 'Enabled' or 'Disabled')..' auto-restore',
376-
enabled=self.enabled
352+
autostart_command=self.autostart_command,
353+
enabled=self.enabled,
377354
},
378355
}
379356
end
380357

381-
function StandingOrdersOverlay:do_auto(val)
382-
dfhack.run_script('control-panel', (val and '' or 'no') .. 'autostart', autostart_command)
383-
SOMessageScreen{enabled=val}:show()
358+
function ImportExportAutoOverlay:do_auto(val)
359+
dfhack.run_script('control-panel', (val and '' or 'no') .. 'autostart', self.autostart_command)
360+
AutoMessageScreen{autostart_command=self.autostart_command, enabled=val}:show()
384361
end
385362

386-
function StandingOrdersOverlay:onRenderFrame(dc, rect)
387-
StandingOrdersOverlay.super.onRenderFrame(self, dc, rect)
388-
local enabled = control_panel.get_autostart(autostart_command)
363+
function ImportExportAutoOverlay:onRenderFrame(dc, rect)
364+
ImportExportAutoOverlay.super.onRenderFrame(self, dc, rect)
365+
local enabled = control_panel.get_autostart(self.autostart_command)
389366
self.subviews.auto:setOption(enabled)
390367
end
391368

369+
------------------------------
370+
-- StandingOrdersOverlay
371+
--
372+
373+
local li = df.global.plotinfo.labor_info
374+
375+
local function save_standing_orders()
376+
local standing_orders = {}
377+
for name, val in pairs(df.global) do
378+
if name:startswith('standing_orders_') then
379+
standing_orders[name] = val
380+
end
381+
end
382+
config.data.standing_orders = standing_orders
383+
local chores = {}
384+
chores.enabled = li.flags.children_do_chores
385+
chores.labors = utils.clone(li.chores)
386+
config.data.chores = chores
387+
config:write()
388+
end
389+
390+
local function load_standing_orders()
391+
for name, val in pairs(config.data.standing_orders or {}) do
392+
df.global[name] = val
393+
end
394+
li.flags.children_do_chores = not not safe_index(config.data.chores, 'enabled')
395+
for i, val in ipairs(safe_index(config.data.chores, 'labors') or {}) do
396+
li.chores[i-1] = val
397+
end
398+
end
399+
400+
local function has_saved_standing_orders()
401+
return next(config.data.standing_orders or {})
402+
end
403+
404+
StandingOrdersOverlay = defclass(StandingOrdersOverlay, ImportExportAutoOverlay)
405+
StandingOrdersOverlay.ATTRS {
406+
desc='Adds buttons to the standing orders screen for saving and restoring settings.',
407+
default_pos={x=6, y=-5},
408+
viewscreens='dwarfmode/Info/LABOR/STANDING_ORDERS/AUTOMATED_WORKSHOPS',
409+
frame={w=78, h=5},
410+
save_label='Save standing orders (all tabs)',
411+
load_label='Load saved standing orders',
412+
auto_label='Apply saved settings for new embarks:',
413+
save_fn=save_standing_orders,
414+
load_fn=load_standing_orders,
415+
has_data_fn=has_saved_standing_orders,
416+
autostart_command='gui/settings-manager load-standing-orders',
417+
}
418+
419+
------------------------------
420+
-- WorkDetailsOverlay
421+
--
422+
423+
local function clone_wd_flags(flags)
424+
return {
425+
cannot_be_everybody=flags.cannot_be_everybody,
426+
no_modify=flags.no_modify,
427+
mode=flags.mode,
428+
}
429+
end
430+
431+
local function save_work_details()
432+
local details = {}
433+
for idx, wd in ipairs(li.work_details) do
434+
local detail = {
435+
name=wd.name,
436+
icon=wd.icon,
437+
work_detail_flags=clone_wd_flags(wd.work_detail_flags),
438+
allowed_labors=utils.clone(wd.allowed_labors),
439+
}
440+
details[idx+1] = detail
441+
end
442+
config.data.work_details = details
443+
config:write()
444+
end
445+
446+
local function load_work_details()
447+
if not config.data.work_details or #config.data.work_details < 10 then
448+
-- not enough data to cover built-in work details
449+
return
450+
end
451+
li.work_details:resize(#config.data.work_details)
452+
-- keep unit assignments for overwritten indices
453+
for idx, wd in ipairs(config.data.work_details) do
454+
local detail = {
455+
new=df.work_detail,
456+
name=wd.name,
457+
icon=wd.icon,
458+
work_detail_flags=wd.work_detail_flags,
459+
}
460+
li.work_details[idx-1] = detail
461+
local al = li.work_details[idx-1].allowed_labors
462+
for i,v in ipairs(wd.allowed_labors) do
463+
al[i-1] = v
464+
end
465+
end
466+
local scr = dfhack.gui.getDFViewscreen(true)
467+
if dfhack.gui.matchFocusString('dwarfmode/Info/LABOR/WORK_DETAILS', scr) then
468+
gui.simulateInput(scr, 'LEAVESCREEN')
469+
gui.simulateInput(scr, 'D_LABOR')
470+
end
471+
end
472+
473+
local function has_saved_work_details()
474+
return next(config.data.work_details or {})
475+
end
476+
477+
WorkDetailsOverlay = defclass(WorkDetailsOverlay, ImportExportAutoOverlay)
478+
WorkDetailsOverlay.ATTRS {
479+
desc='Adds buttons to the work details screen for saving and restoring settings.',
480+
default_pos={x=80, y=-5},
481+
viewscreens='dwarfmode/Info/LABOR/WORK_DETAILS',
482+
frame={w=35, h=5},
483+
save_label='Save work details',
484+
load_label='Load work details',
485+
auto_label='Load for new embarks:',
486+
save_fn=save_work_details,
487+
load_fn=load_work_details,
488+
has_data_fn=has_saved_work_details,
489+
autostart_command='gui/settings-manager load-work-details',
490+
}
491+
492+
function WorkDetailsOverlay:init()
493+
self.subviews.save.frame.w = 25
494+
self.subviews.save_flash.frame.l = 10
495+
self.subviews.load.frame.t = 1
496+
self.subviews.load.frame.l = 0
497+
self.subviews.load.frame.w = 25
498+
self.subviews.load_flash.frame.t = 1
499+
self.subviews.load_flash.frame.l = 10
500+
end
501+
392502
OVERLAY_WIDGETS = {
393503
embark_difficulty=DifficultyEmbarkOverlay,
394504
embark_notification=DifficultyEmbarkNotificationOverlay,
395505
settings_difficulty=DifficultySettingsOverlay,
396506
standing_orders=StandingOrdersOverlay,
507+
work_details=WorkDetailsOverlay,
397508
}
398509

399510
if dfhack_flags.module then
@@ -447,6 +558,16 @@ elseif command == 'load-standing-orders' then
447558
else
448559
qerror('must be in a loaded fort')
449560
end
561+
elseif command == 'save-work-details' then
562+
if is_fort then save_work_details()
563+
else
564+
qerror('must be in a loaded fort')
565+
end
566+
elseif command == 'load-work-details' then
567+
if is_fort then load_work_details()
568+
else
569+
qerror('must be in a loaded fort')
570+
end
450571
else
451572
print(dfhack.script_help())
452573
end

internal/control-panel/registry.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ COMMANDS_BY_IDX = {
4040
params={'--time', '1', '--timeUnits', 'months', '--command', '[', 'cleanowned', 'X', ']'}},
4141
{command='gui/settings-manager load-standing-orders', group='automation', mode='run',
4242
desc='Go to the Standing Orders tab in the Labor screen to save your current settings.'},
43+
{command='gui/settings-manager load-work-details', group='automation', mode='run',
44+
desc='Go to the Work Details tab in the Labor screen to save your current definitions.'},
4345
{command='nestboxes', group='automation', mode='enable'},
4446
{command='orders-sort', help_command='orders', group='automation', mode='repeat',
4547
desc='Sort manager orders by repeat frequency so one-time orders can be completed.',

0 commit comments

Comments
 (0)