Skip to content

Commit f279f5d

Browse files
authored
Merge pull request #5824 from gwilymtv/gwilym-buildingplan-pull
buildingplan: add Pull button for linked levers
2 parents 0ac1aad + db6e8fa commit f279f5d

3 files changed

Lines changed: 109 additions & 1 deletion

File tree

docs/changelog.txt

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

5959
## New Features
60+
- `buildingplan`: add a ``Pull`` button next to linked levers on a building's "Show linked buildings" tab so you can queue a high-priority pull-lever job (or cancel a queued one) without navigating to the lever
6061

6162
## Fixes
6263
- `autoclothing`: correct defect in validating material specification on command line

docs/plugins/buildingplan.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,3 +249,8 @@ usual) unless freed via the ``Free`` buttons on the ``Show items`` tab on both
249249
buildings. This will remove the mechanism from the building and drop it onto the
250250
ground, allowing it to be reused elsewhere. There is an option to auto-free
251251
mechanisms when unlinking to perform this step automatically.
252+
253+
For any linked building that is a lever, a ``Pull`` button also appears next to it
254+
on the ``Show linked buildings`` tab, with a glyph showing the lever's current
255+
position. Clicking it queues a high-priority ("do now") pull-lever job without
256+
having to navigate to the lever itself; click it again to cancel the job.

plugins/lua/buildingplan/unlink_mechanisms.lua

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ local dialogs = require('gui.dialogs')
44
local overlay = require("plugins.overlay")
55
local utils = require("utils")
66
local widgets = require("gui.widgets")
7+
local lever = reqscript("lever")
78

89
local function mech_iter(b) --iterate mechanisms backwards
910
local t = b.contained_items
@@ -35,6 +36,40 @@ local function get_mech_target(m) --mechanism target building if exists
3536
return i and df.building.find(m.general_refs[i].building_id) or nil
3637
end
3738

39+
local function is_lever(b) --building is a lever
40+
return b and b._type == df.building_trapst and b.trap_type == df.trap_type.Lever
41+
end
42+
43+
local function get_pull_job(b) --pending pull job on lever, or nil
44+
for _, j in ipairs(b.jobs) do
45+
if j.job_type == df.job_type.PullLever then
46+
return j
47+
end
48+
end
49+
end
50+
51+
local ASCII_LEVER_OFF = string.char(0x95) --ò
52+
local ASCII_LEVER_ON = string.char(0xA2) --ó
53+
54+
local function get_lever_state_char(lever) --lever position glyph for the current tileset
55+
-- match the current mode because ASCII and premium lever glyphs differ in directions
56+
if dfhack.screen.inGraphicsMode() then
57+
return lever.state == 0 and "/" or "\\"
58+
end
59+
return lever.state == 0 and ASCII_LEVER_OFF or ASCII_LEVER_ON
60+
end
61+
62+
local function get_pull_label(lever) --button label and pen for the lever's pull state
63+
local state_char = get_lever_state_char(lever) --current lever position
64+
local job = get_pull_job(lever)
65+
if not job then
66+
return "Pull "..state_char, COLOR_WHITE
67+
elseif dfhack.job.getWorker(job) then
68+
return "Pulling "..state_char, COLOR_GREEN --a citizen has taken the job
69+
end
70+
return "Queued "..state_char, COLOR_YELLOW --queued, not yet taken
71+
end
72+
3873
local function has_link_tab(b) --linked building tab exists
3974
if not b then
4075
return
@@ -148,7 +183,7 @@ local valid_build = {
148183
MechLinkOverlay = defclass(MechLinkOverlay, overlay.OverlayWidget)
149184
MechLinkOverlay.ATTRS
150185
{
151-
desc = "Allows unlinking mechanisms from buildings.",
186+
desc = "Allows unlinking mechanisms and pulling linked levers from buildings.",
152187
default_enabled = true,
153188
default_pos = {x=-41, y=-4},
154189
frame = {w=56, h=27},
@@ -303,6 +338,55 @@ function MechLinkOverlay:activate_button(n)
303338
end
304339
end
305340

341+
function MechLinkOverlay:get_pull_button(n, ensure)
342+
local button = self.subviews["pull_"..n]
343+
if not button and ensure then
344+
self:addviews
345+
{
346+
widgets.TextButton
347+
{
348+
view_id = "pull_"..n,
349+
frame = {t=0, r=17, w=11, h=1},
350+
label = "", --set per-frame in update_buttons
351+
on_activate = function() self:activate_pull(n) end,
352+
visible = false,
353+
},
354+
}
355+
button = self.subviews["pull_"..n]
356+
button:updateLayout(self.frame_body)
357+
end
358+
359+
return button
360+
end
361+
362+
function MechLinkOverlay:pull_target(n) --linked lever for button n, or nil
363+
local button = self:get_pull_button(n)
364+
if not button then
365+
return
366+
end
367+
368+
local idx = self:idx_from_offset(button.frame.t)
369+
if idx > 0 and idx < #self.building.contained_items then
370+
local target = get_mech_target(self.building.contained_items[idx].item)
371+
if is_lever(target) then
372+
return target
373+
end
374+
end
375+
end
376+
377+
function MechLinkOverlay:activate_pull(n)
378+
local target = self:pull_target(n)
379+
if not target then
380+
return
381+
end
382+
local job = get_pull_job(target)
383+
if job then
384+
dfhack.job.removeJob(job) --cancel queued pull
385+
else
386+
lever.leverPullJob(target, true) --do now
387+
end
388+
end
389+
306390
function MechLinkOverlay:ask_unlink_all()
307391
local saved_mode = self.subviews.unlink_mode:getOptionValue()
308392
local message = {
@@ -356,6 +440,20 @@ function MechLinkOverlay:update_buttons()
356440
button.visible = true
357441
end
358442
button:updateLayout()
443+
444+
local pbutton = self:get_pull_button(i, true)
445+
pbutton.visible = false
446+
local target = idx > 0 and idx < bci_len and
447+
get_mech_target(self.building.contained_items[idx].item)
448+
if is_lever(target) then
449+
local label, pen = get_pull_label(target)
450+
pbutton:setLabel(label)
451+
pbutton.label.text_pen = pen
452+
pbutton.frame.t = offset
453+
pbutton.frame.r = h_offset + 9
454+
pbutton.visible = true
455+
end
456+
pbutton:updateLayout()
359457
end
360458

361459
local b = (self.frame.h % 3) == 1 and #self.links >= self.num_buttons and 0 or 1
@@ -371,6 +469,10 @@ function MechLinkOverlay:preUpdateLayout(parent_rect)
371469
if button then
372470
button.visible = false
373471
end
472+
local pbutton = self:get_pull_button(i)
473+
if pbutton then
474+
pbutton.visible = false
475+
end
374476
end
375477

376478
local h = parent_rect.height - 49

0 commit comments

Comments
 (0)