Skip to content

Commit

Permalink
Merge pull request #948 from myk002/myk_standing_orders
Browse files Browse the repository at this point in the history
[gui/settings-manager] load, save, and autoload standing orders
  • Loading branch information
myk002 authored Jan 15, 2024
2 parents 6c80200 + ff34384 commit 9eb81c9
Show file tree
Hide file tree
Showing 6 changed files with 287 additions and 20 deletions.
2 changes: 1 addition & 1 deletion changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Template for new versions:

## New Features
- `uniform-unstick`: add overlay to the squad equipment screen to show a equipment conflict report and give you a one-click button to fix
- `gui/settings-manager`: save and load (optionally automatically) embark difficulty settings
- `gui/settings-manager`: save and load (optionally automatically) embark difficulty settings and standing orders

## Fixes
- `source`: water and magma sources now persist with fort across saves and loads
Expand Down
38 changes: 25 additions & 13 deletions control-panel.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,30 @@ dfhack.onStateChange[GLOBAL_KEY] = function(sc)
end
end

local function get_command_data(name_or_idx)
if type(name_or_idx) == 'number' then
return registry.COMMANDS_BY_IDX[name_or_idx]
end
return registry.COMMANDS_BY_NAME[name_or_idx]
end

local function get_autostart_internal(data)
local default_value = not not data.default
local current_value = safe_index(common.config.data.commands, data.command, 'autostart')
if current_value == nil then
current_value = default_value
end
return current_value, default_value
end

-- API

-- returns current, default
function get_autostart(command)
local data = get_command_data(command)
if not data then return end
return get_autostart_internal(data)
end

-- CLI

Expand Down Expand Up @@ -85,12 +109,7 @@ local function list_command_group(group, filter_strs, enabled_map)
if #desc > 0 then
print((' %s'):format(desc))
end
local default_value = not not data.default
local current_value = safe_index(common.config.data.commands, data.command, 'autostart')
if current_value == nil then
current_value = default_value
end
print((' autostart enabled: %s (default: %s)'):format(current_value, default_value))
print((' autostart enabled: %s (default: %s)'):format(get_autostart_internal(data)))
if enabled_map[data.command] ~= nil then
print((' currently enabled: %s'):format(enabled_map[data.command]))
end
Expand Down Expand Up @@ -130,13 +149,6 @@ local function do_list(filter_strs)
list_preferences(filter_strs)
end

local function get_command_data(name_or_idx)
if type(name_or_idx) == 'number' then
return registry.COMMANDS_BY_IDX[name_or_idx]
end
return registry.COMMANDS_BY_NAME[name_or_idx]
end

local function do_enable_disable(which, entries)
local enabled_map =common.get_enabled_map()
for _, entry in ipairs(entries) do
Expand Down
9 changes: 9 additions & 0 deletions docs/control-panel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,12 @@ Examples
this will also remove some entries from the ``control-panel list`` output.
Run ``control-panel list`` to see all preference options and their
descriptions.

API
---

Other scripts can query whether a command is set for autostart via the script
API::

local control_panel = reqscript('control-panel')
local enabled, default = control_panel.get_autostart(command)
37 changes: 31 additions & 6 deletions docs/gui/settings-manager.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,40 @@ gui/settings-manager
====================

.. dfhack-tool::
:summary: Save, load, and modify DF settings.
:summary: Import and export DF settings.
:tags: embark interface

This tool provides overlays that allow you to save and load DF settings.
This tool allows you to save and load DF settings.

Usage
-----

::

gui/settings-manager save-difficulty
gui/settings-manager load-difficulty
gui/settings-manager save-standing-orders
gui/settings-manager load-standing-orders

Difficulty can be saved and loaded on the embark "preparation" screen or in an
active fort. Standing orders can only be saved and loaded in an active fort.

If auto-restoring of difficulty settings is turned on, it happens when the
embark "preparation" screen is loaded. If auto-restoring of standing orders
settings is turned on, it happens when the fort is loaded for the first time
(just like all other Autostart commands configured in `gui/control-panel`).

Overlays
--------

When embarking, if you click on the ``Custom settings`` button for game
difficulty, you will see a new panel at the top. You can save the current
difficulty settings and load the saved settings back. You can also toggle an
option to automatically load the saved settings for new embarks.
When embarking or when a fort is loaded, if you click on the
``Custom settings`` button for game difficulty, you will see a new panel at the
top. You can save the current difficulty settings and load the saved settings
back. You can also toggle an option to automatically load the saved settings
for new embarks.

When a fort is loaded, you can also go to the Labor -> Standing Orders page.
You will see a new panel that allows you to save and restore your settings for
standing orders. You can also toggle whether the saved standing orders are
automatically restored when you embark on a new fort. This will toggle the
relevant command in `gui/control-panel` on the Automation -> Autostart page.
219 changes: 219 additions & 0 deletions gui/settings-manager.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
--@ module = true

local argparse = require('argparse')
local control_panel = reqscript('control-panel')
local gui = require('gui')
local json = require('json')
local overlay = require('plugins.overlay')
Expand Down Expand Up @@ -224,16 +226,233 @@ function DifficultySettingsOverlay:get_df_struct()
return df.global.game.main_interface.settings
end

------------------------------
-- StandingOrdersOverlay
--

StandingOrdersOverlay = defclass(StandingOrdersOverlay, overlay.OverlayWidget)
StandingOrdersOverlay.ATTRS {
desc='Adds buttons to the standing orders screen for saving and restoring settings.',
default_pos={x=6, y=-5},
viewscreens='dwarfmode/Info/LABOR/STANDING_ORDERS/AUTOMATED_WORKSHOPS',
default_enabled=true,
frame={w=78, h=5},
frame_style=gui.MEDIUM_FRAME,
frame_background=gui.CLEAR_PEN,
}

local li = df.global.plotinfo.labor_info

local function save_standing_orders()
local standing_orders = {}
for name, val in pairs(df.global) do
if name:startswith('standing_orders_') then
standing_orders[name] = val
end
end
config.data.standing_orders = standing_orders
local chores = {}
chores.enabled = li.flags.children_do_chores
chores.labors = utils.clone(li.chores)
config.data.chores = chores
config:write()
end

local function load_standing_orders()
for name, val in pairs(config.data.standing_orders or {}) do
df.global[name] = val
end
li.flags.children_do_chores = not not safe_index(config.data.chores, 'enabled')
for i, val in ipairs(safe_index(config.data.chores, 'labors') or {}) do
li.chores[i-1] = val
end
end

function StandingOrdersOverlay:init()
self:addviews{
widgets.HotkeyLabel{
view_id='save',
frame={l=0, t=0, w=39},
key='CUSTOM_CTRL_E',
label='Save standing orders (all tabs)',
on_activate=self:callback('do_save'),
},
widgets.Label{
view_id='save_flash',
frame={l=18, t=0},
text='Saved',
text_pen=COLOR_GREEN,
visible=false,
},
widgets.HotkeyLabel{
view_id='load',
frame={l=42, t=0, w=34},
key='CUSTOM_CTRL_I',
label='Load saved standing orders',
on_activate=self:callback('do_load'),
enabled=function() return next(config.data.standing_orders or {}) end,
},
widgets.Label{
view_id='load_flash',
frame={l=51, t=0},
text='Loaded',
text_pen=COLOR_GREEN,
visible=false,
},
widgets.ToggleHotkeyLabel{
view_id='auto',
frame={l=0, t=2},
key='CUSTOM_CTRL_A',
label='Apply saved settings for new embarks:',
on_change=self:callback('do_auto'),
enabled=function() return next(config.data.standing_orders or {}) end,
},
}
end

function StandingOrdersOverlay:do_save()
flash(self, 'save')
save_standing_orders()
end

function StandingOrdersOverlay:do_load()
flash(self, 'load')
load_standing_orders()
end

local autostart_command = 'gui/settings-manager load-standing-orders'

SOMessage = defclass(SOMessage, widgets.Window)
SOMessage.ATTRS {
frame={w=61, h=9},
enabled=DEFAULT_NIL,
}

function SOMessage:init()
self:addviews{
widgets.Label{
view_id='label',
frame={t=0, l=0},
text={
'The "', autostart_command, '" command', NEWLINE,
'has been ',
{text=self.enabled and 'enabled' or 'disabled', pen=self.enabled and COLOR_GREEN or COLOR_LIGHTRED},
' in the ',
{text='Automation', pen=COLOR_YELLOW}, ' -> ',
{text='Autostart', pen=COLOR_YELLOW}, ' tab of ', NEWLINE,
{text='.', gap=25},
},
},
widgets.HotkeyLabel{
frame={t=2, l=0},
label='gui/control-panel',
key='CUSTOM_CTRL_G',
auto_width=true,
on_activate=function()
self.parent_view:dismiss()
dfhack.run_script('gui/control-panel')
end,
},
widgets.HotkeyLabel{
frame={b=0, l=0, r=0},
label='Ok',
key='SELECT',
auto_width=true,
on_activate=function() self.parent_view:dismiss() end,
},
}
end

SOMessageScreen = defclass(SOMessageScreen, gui.ZScreenModal)
SOMessageScreen.ATTRS {
focus_path='settings-manager/prompt',
enabled=DEFAULT_NIL,
}

function SOMessageScreen:init()
self:addviews{
SOMessage{
frame_title=(self.enabled and 'Enabled' or 'Disabled')..' auto-restore',
enabled=self.enabled
},
}
end

function StandingOrdersOverlay:do_auto(val)
dfhack.run_script('control-panel', (val and '' or 'no') .. 'autostart', autostart_command)
SOMessageScreen{enabled=val}:show()
end

function StandingOrdersOverlay:onRenderFrame(dc, rect)
StandingOrdersOverlay.super.onRenderFrame(self, dc, rect)
local enabled = control_panel.get_autostart(autostart_command)
self.subviews.auto:setOption(enabled)
end

OVERLAY_WIDGETS = {
embark_difficulty=DifficultyEmbarkOverlay,
embark_notification=DifficultyEmbarkNotificationOverlay,
settings_difficulty=DifficultySettingsOverlay,
standing_orders=StandingOrdersOverlay,
}

if dfhack_flags.module then
return
end

------------------------------
-- CLI processing
--

local help = false

local positionals = argparse.processArgsGetopt({...}, {
{'h', 'help', handler=function() help = true end},
})

local command = (positionals or {})[1]

if help then
print(dfhack.script_help())
return
end

local scr = dfhack.gui.getDFViewscreen(true)
local is_embark = df.viewscreen_setupdwarfgamest:is_instance(scr)
local is_fort = df.viewscreen_dwarfmodest:is_instance(scr)

if command == 'save-difficulty' then
if is_embark then save_difficulty(scr.difficulty)
elseif is_fort then
save_difficulty(df.global.game.main_interface.settings.difficulty)
else
qerror('must be on the embark preparation screen or in a loaded fort')
end
elseif command == 'load-difficulty' then
if is_embark then
load_difficulty(scr.difficulty)
show_notification = true
elseif is_fort then
load_difficulty(df.global.game.main_interface.settings.difficulty)
else
qerror('must be on the embark preparation screen or in a loaded fort')
end
elseif command == 'save-standing-orders' then
if is_fort then save_standing_orders()
else
qerror('must be in a loaded fort')
end
elseif command == 'load-standing-orders' then
if is_fort then load_standing_orders()
else
qerror('must be in a loaded fort')
end
else
print(dfhack.script_help())
end

return

--[[
TODO: reinstate color editor
Expand Down
2 changes: 2 additions & 0 deletions internal/control-panel/registry.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ COMMANDS_BY_IDX = {
{command='cleanowned', group='automation', mode='repeat',
desc='Encourage dwarves to drop tattered clothing and grab new ones.',
params={'--time', '1', '--timeUnits', 'months', '--command', '[', 'cleanowned', 'X', ']'}},
{command='gui/settings-manager load-standing-orders', group='automation', mode='run',
desc='Go to the Standing Orders tab in the Labor screen to save your current settings.'},
{command='nestboxes', group='automation', mode='enable'},
{command='orders-sort', help_command='orders', group='automation', mode='repeat',
desc='Sort manager orders by repeat frequency so one-time orders can be completed.',
Expand Down

0 comments on commit 9eb81c9

Please sign in to comment.