-
Notifications
You must be signed in to change notification settings - Fork 227
Expand file tree
/
Copy pathlever-interface.lua
More file actions
228 lines (205 loc) · 6.26 KB
/
lever-interface.lua
File metadata and controls
228 lines (205 loc) · 6.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
-- List and pull levers
local gui = require('gui')
local guidm = require('gui.dwarfmode')
local utils = require('utils')
local widgets = require('gui.widgets')
local lever_script = reqscript('lever')
local REFRESH_MS = 1000
local function get_levers()
local levers = {}
for _, building in ipairs(df.global.world.buildings.other.TRAP) do
if building.trap_type == df.trap_type.Lever then
table.insert(levers, building)
end
end
return levers
end
local function get_lever_label(lever)
local status = (lever.state == 1) and 'Pulled' or 'Not Pulled'
local name = utils.getBuildingName(lever)
local queued = 0
for _, job in ipairs(lever.jobs) do
if job.job_type == df.job_type.PullLever then
queued = queued + 1
end
end
local queued_text = queued > 0 and (' (queued: %d)'):format(queued) or ''
return ('[%s] %s (#%d)%s'):format(status, name, lever.id, queued_text)
end
local function get_queued_count(levers)
local queued = 0
for _, lever in ipairs(levers) do
for _, job in ipairs(lever.jobs) do
if job.job_type == df.job_type.PullLever then
queued = queued + 1
end
end
end
return queued
end
LeverWindow = defclass(LeverWindow, widgets.Window)
LeverWindow.ATTRS{
frame_title = 'Lever Tasks',
frame = {w=60, h=18, r=2},
}
function LeverWindow:init()
local _, screen_height = dfhack.screen.getWindowSize()
if screen_height then
self.frame.t = math.max(0, math.floor((screen_height - self.frame.h) / 2))
end
self.next_refresh_ms = dfhack.getTickCount() + REFRESH_MS
self.filter_text = ''
self:addviews{
widgets.EditField{
view_id='search',
frame={t=0, l=0, r=0},
label_text='Search: ',
on_change=self:callback('set_filter'),
},
widgets.List{
view_id='lever_list',
frame={t=1, l=0, r=0, b=4},
on_submit=self:callback('queue_pull'),
on_select=self:callback('focus_lever'),
},
widgets.Label{
view_id='empty_message',
frame={t=1, l=0, r=0},
text='No levers found.',
visible=false,
},
widgets.HotkeyLabel{
frame={b=3, l=0},
label='Pull selected lever',
key='CUSTOM_P',
on_activate=self:callback('queue_pull'),
},
widgets.HotkeyLabel{
frame={b=2, l=0},
label='Remove queued pulls',
key='CUSTOM_X',
on_activate=self:callback('remove_queued_pulls'),
},
widgets.Label{
view_id='queued_count',
frame={b=3, r=0},
text='Queued pulls: 0',
auto_width=true,
},
widgets.HotkeyLabel{
frame={b=1, l=0},
label='Refresh list',
key='CUSTOM_R',
on_activate=self:callback('refresh_list'),
},
}
self:refresh_list()
end
function LeverWindow:set_filter(text)
self.filter_text = text or ''
self:refresh_list()
end
function LeverWindow:refresh_list()
local list = self.subviews.lever_list
local selected_id
if list then
local _, selected = list:getSelected()
if selected and selected.data then
selected_id = selected.data.id
end
end
local choices = {}
local levers = get_levers()
table.sort(levers, function(a, b)
if a.state == b.state then
return a.id < b.id
end
return a.state > b.state
end)
local filter = (self.filter_text or ''):lower()
local filtered_levers = {}
if filter == '' then
filtered_levers = levers
else
for _, lever in ipairs(levers) do
local name = utils.getBuildingName(lever)
if name:lower():find(filter, 1, true) then
table.insert(filtered_levers, lever)
end
end
end
local selected_idx = 1
for idx, lever in ipairs(filtered_levers) do
table.insert(choices, {text=get_lever_label(lever), data=lever})
if selected_id and lever.id == selected_id then
selected_idx = idx
end
end
list:setChoices(choices, selected_idx)
self.subviews.empty_message.visible = #choices == 0
self.subviews.queued_count:setText(('Queued pulls: %d'):format(get_queued_count(levers)))
end
function LeverWindow:queue_pull()
local _, choice = self.subviews.lever_list:getSelected()
if not choice then
return
end
lever_script.leverPullJob(choice.data, false)
self:refresh_list()
end
function LeverWindow:remove_queued_pulls()
local _, choice = self.subviews.lever_list:getSelected()
if not choice then
return
end
local jobs = {}
for _, job in ipairs(choice.data.jobs) do
if job.job_type == df.job_type.PullLever then
table.insert(jobs, job)
end
end
for _, job in ipairs(jobs) do
dfhack.job.removeJob(job)
end
self:refresh_list()
end
function LeverWindow:onRenderFrame(dc, rect)
LeverWindow.super.onRenderFrame(self, dc, rect)
local list = self.subviews.lever_list
local hover_idx = list:getIdxUnderMouse()
if hover_idx and hover_idx ~= self.hover_index then
self.hover_index = hover_idx
list:setSelected(hover_idx)
local _, choice = list:getSelected()
if choice then
self:focus_lever(nil, choice)
end
end
end
function LeverWindow:onRenderBody()
if dfhack.getTickCount() >= self.next_refresh_ms then
self.next_refresh_ms = dfhack.getTickCount() + REFRESH_MS
self:refresh_list()
end
end
function LeverWindow:focus_lever(_, choice)
if not choice then
return
end
local lever = choice.data
local pos = {x=lever.centerx, y=lever.centery, z=lever.z}
dfhack.gui.revealInDwarfmodeMap(pos, true, true)
guidm.setCursorPos(pos)
end
LeverScreen = defclass(LeverScreen, gui.ZScreen)
LeverScreen.ATTRS{focus_path='lever'}
function LeverScreen:init()
self:addviews{LeverWindow{}}
end
function LeverScreen:onDismiss()
view = nil
end
if not dfhack.isMapLoaded() then
qerror('gui/lever requires a map to be loaded')
end
view = view and view:raise() or LeverScreen{}:show()