Skip to content

Labor Control Overlay #1463

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
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions docs/zSelectLockLabors.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Select Lock Overlay
===================

This is a DFHack overlay plugin for Dwarf Fortress that simulates the selection and locking of multiple units within the **Work Details** screen. It provides a simple UI interface to batch-toggle units' labor assignments, either by selecting, locking, or both.

Features
--------

- **Overlay Interface**: Integrated directly into the `LABOR/WORK_DETAILS` viewscreen.
- **Action Modes**: Choose between `Select only`, `Lock only`, or `Select + Lock`.
- **Batch Processing**: Specify how many entries to affect and apply actions with one click.
- **Non-Intrusive**: Uses DFHack GUI input simulation to trigger existing functionality.

Usage
-----

Once the plugin is loaded and you're in the `Work Details` screen (e.g., `y` -> `Work Details`), the overlay will automatically appear.

1. Use the **Mode** dropdown to select what action(s) to simulate:
- `Select only`: Just toggles unit selection.
- `Lock only`: Just toggles the lock status.
- `Select + Lock`: Toggles both selection and lock.

2. Adjust the number of entries to apply actions to (default is 100).

3. Press the **RUN** button (or the hotkey defined for it) to execute the actions.
98 changes: 98 additions & 0 deletions zSelectLockLabors.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
--@module=true
local gui = require('gui')
local widgets = require('gui.widgets')
local overlay = require('plugins.overlay')

local SelectLockOverlay = defclass(nil, overlay.OverlayWidget)
SelectLockOverlay.ATTRS {
desc = 'Simulate selection and locking of multiple units.',
viewscreens = {'dwarfmode/Info/LABOR/WORK_DETAILS/Default'},
default_enabled = true,
default_pos = {x = -70, y = 10},
frame = {w = 25, h = 6, r = 1, t = 1, transparent = false},
}

local function simulate_actions(self, count)
gui.simulateInput(dfhack.gui.getCurViewscreen(), 'STANDARDSCROLL_RIGHT')

local function step(i)
if i > count then
for _ = 1, count do
gui.simulateInput(dfhack.gui.getCurViewscreen(), 'STANDARDSCROLL_UP')
gui.simulateInput(dfhack.gui.getCurViewscreen(), 'CONTEXT_SCROLL_UP')
end
self.is_running = false
return
end

if self.action_mode ~= 'lock' then
gui.simulateInput(dfhack.gui.getCurViewscreen(), 'SELECT')
end
if self.action_mode ~= 'select' then
gui.simulateInput(dfhack.gui.getCurViewscreen(), 'UNITLIST_SPECIALIZE')
end
--This line is keyboard arrow down
gui.simulateInput(dfhack.gui.getCurViewscreen(), 'STANDARDSCROLL_DOWN')
--CONTEXT_SCROLL_DOWN helps with consistency. Otherwise the program will miss some units. Line below is scroll wheel down
gui.simulateInput(dfhack.gui.getCurViewscreen(), 'CONTEXT_SCROLL_DOWN')

dfhack.timeout(2, 'frames', function() step(i + 1) end)
end

step(1)
end

function SelectLockOverlay:init()
self.action_mode = 'both'
self.entry_count = 100
self.is_running = false
self:addviews{
widgets.Panel{
frame_style = gui.MEDIUM_FRAME,
frame_background = gui.CLEAR_PEN,
subviews = {
widgets.CycleHotkeyLabel{
view_id = 'action_mode',
frame = {l = 1, t = 1},
label = 'Mode',
option_gap = 2,
options = {
{label = 'Select only', value = 'select'},
{label = 'Lock only', value = 'lock'},
{label = 'Select + Lock', value = 'both'},
},
initial_option = 'both',
on_change = function(val) self.action_mode = val end,
},
widgets.EditField{
numeric = true,
frame = {l = 1, t = 2},
key = 'CUSTOM_CTRL_N',
auto_focus = false,
text = '7',
on_change = function(val)
local num = tonumber(val)
self.entry_count = (num and num > 0 and math.floor(num)) or 100
end,
},
widgets.HotkeyLabel{
view_id = 'run_button',
frame = {l = 1, t = 3},
label = 'RUN',
on_activate = function()
if self.is_running then return end
self.is_running = true
simulate_actions(self, self.entry_count)
end,
enabled = function() return not self.is_running end,
},
},
},
}
end

OVERLAY_WIDGETS = {
select_lock_overlay = SelectLockOverlay,
}

return {}