Skip to content

Commit 83a6303

Browse files
committed
Simplify logic and implement keybinds for goto and actions
1 parent dcf48b9 commit 83a6303

File tree

1 file changed

+86
-35
lines changed

1 file changed

+86
-35
lines changed

gui/siegemanager.lua

Lines changed: 86 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@ local gui = require('gui')
22
local widgets = require('gui.widgets')
33
local textures = require('gui.textures')
44

5-
local function activity_button_split(ascii, pens, x, y)
5+
--
6+
-- Button label definitions
7+
--
8+
local function make_button(ascii, pens, x, y)
69
local out = {}
10+
-- Grid of 3x3 tiles
711
for i=1,3 do
812
local tmp = {}
913
for j=1,3 do
@@ -37,8 +41,8 @@ local function make_activity_button(ch, color, border_color, border_acolor, x, y
3741
end
3842

3943
return {
40-
inactive = activity_button_split(ascii, make_pens(border_color, color), x, y),
41-
active = activity_button_split(ascii, make_pens(border_acolor, color), ax, ay)
44+
inactive = make_button(ascii, make_pens(border_color, color), x, y),
45+
active = make_button(ascii, make_pens(border_acolor, color), ax, ay)
4246
}
4347
end
4448

@@ -65,7 +69,7 @@ local goto_button_color = {
6569
{COLOR_LIGHTCYAN, COLOR_LIGHTRED, COLOR_LIGHTCYAN},
6670
{COLOR_LIGHTCYAN, COLOR_LIGHTCYAN, COLOR_LIGHTCYAN},
6771
}
68-
local goto_button = activity_button_split(goto_button_ascii, goto_button_color, 32, 0)
72+
local goto_button = make_button(goto_button_ascii, goto_button_color, 32, 0)
6973

7074

7175
-- TODO: The usage of these icons requires the ability to adjust screentexpos_flag
@@ -151,7 +155,7 @@ end
151155
-- Obtain a list of siege engine buildings on the map with specific information
152156
local function get_siege_engines()
153157
local siege_list = {}
154-
for _, building in ipairs(df.global.world.buildings.all) do
158+
for _, building in ipairs(df.global.world.buildings.other.IN_PLAY) do
155159
if not df.building_siegeenginest:is_instance(building) then goto continue end
156160
if not building.flags.exists then goto continue end
157161

@@ -174,8 +178,8 @@ local function get_siege_engines()
174178
or job.job_type == df.job_type.FireBallista
175179
or job.job_type == df.job_type.FireBoltThrower then
176180
-- Display `Ready` instead of firing when in standby mode
177-
-- as the same jobtype is used when actively firing and waiting.
178-
-- This is to reduce confusion as no projectiles are made
181+
-- as the same job_type is used when actively firing and waiting.
182+
-- This is to reduce confusion as no projectiles are fired
179183
active_job = building.action == 2 and 'Ready' or 'Firing'
180184
end
181185
end
@@ -198,9 +202,9 @@ local function get_siege_engines()
198202
return siege_list
199203
end
200204

201-
-- Set siegeengine action, returning false if the building wasn't found
205+
-- Set siegeengine action, returning false if the building isn't found
202206
local function set_siege_engine_action(id, action)
203-
for _, building in ipairs(df.global.world.buildings.all) do
207+
for _, building in ipairs(df.global.world.buildings.other.IN_PLAY) do
204208
if building.id == id then
205209
if not df.building_siegeenginest:is_instance(building) then return false end
206210
building.action = action
@@ -214,7 +218,7 @@ end
214218
SiegeEngineList = defclass(SiegeEngineList, widgets.Panel)
215219
SiegeEngineList.ATTRS = {
216220
view_id='list',
217-
frame={l=0, r=0, t=3, b=3},
221+
frame={l=0, r=0, t=1, b=5},
218222
frame_style=gui.FRAME_INTERIOR,
219223

220224
-- Filters by siegeengine_type, -1 being all
@@ -224,7 +228,7 @@ SiegeEngineList.ATTRS = {
224228
function SiegeEngineList:init()
225229
self:refresh_data()
226230

227-
self.refresh_rate = 60
231+
self.refresh_rate = 30
228232
self.refresh_timer = 0
229233

230234
self.button_start_x = 24
@@ -240,9 +244,10 @@ function SiegeEngineList:init()
240244
self:refresh_view(true)
241245
end
242246

247+
-- Used to manage how often the ui data refreshes
243248
function SiegeEngineList:onRenderBody()
244249
self.refresh_timer = self.refresh_timer + 1
245-
if (self.refresh_timer < self.refresh_rate) then
250+
if (self.refresh_timer > self.refresh_rate) then
246251
self.refresh_timer = 0
247252
self:refresh_data()
248253
end
@@ -260,15 +265,18 @@ local function concat_tables(to, from)
260265
end
261266
end
262267

263-
-- TODO: Replace constants with df.siegeengine_action enum once merged
268+
-- TODO: Replace constants with df.siegeengine_action enum once structures merged
264269
local action_button_order={3, 4, 2, 1, 0}
270+
local action_button_keybinds = {'CUSTOM_SHIFT_F', 'CUSTOM_SHIFT_T', 'CUSTOM_SHIFT_P', 'CUSTOM_SHIFT_L', 'CUSTOM_SHIFT_N'}
265271

266-
local function add_multiline(to, from)
267-
concat_tables(to[1], from[1])
268-
concat_tables(to[2], from[2])
269-
concat_tables(to[3], from[3])
272+
-- Add a multiline label definition from `from` to `to` starting at y=y_start or 0
273+
local function add_multiline(to, from, y_start)
274+
for i, item in pairs(from) do
275+
concat_tables(to[i + (y_start or 0)], from[i])
276+
end
270277
end
271278

279+
-- Label string callbacks, used to update the display without resetting the scrolling List
272280
local action_text_pen = dfhack.pen.parse({ fg=COLOR_GREEN })
273281
function SiegeEngineList:get_action_text(id)
274282
return self.engines[id].active_job or ''
@@ -294,6 +302,7 @@ function SiegeEngineList:get_activity_button_tile(id, action, x, y)
294302
return activity_buttons[action][self.engines[id].action == action and 'active' or 'inactive'][y][x].tile
295303
end
296304

305+
-- Generate the multiline Label display for an engine
297306
function SiegeEngineList:make_entry_text(engine)
298307
local lines = {
299308
{{text=self:callback('get_name_text', engine.id), width=self.button_start_x}},
@@ -308,10 +317,10 @@ function SiegeEngineList:make_entry_text(engine)
308317
-- Goto Position Button
309318
add_multiline(lines, goto_button)
310319

311-
-- Blank
320+
-- Padding following goto button
312321
add_multiline(lines, {{{text='', width=3}},{{text='', width=3}},{{text='', width=3}}})
313322

314-
-- FireAtWill, PracticeFire, PrepareToFire, KeepLoaded, NotInUse
323+
-- Siege Engine activity selection buttons
315324
for _, button_action in ipairs(action_button_order) do
316325
for y=1,3 do
317326
for x=1,3 do
@@ -320,6 +329,7 @@ function SiegeEngineList:make_entry_text(engine)
320329
end
321330
end
322331

332+
-- Transform multiline label into a single label with newlines
323333
local out_tokens = {}
324334
for i=1,3 do
325335
concat_tables(out_tokens, lines[i])
@@ -329,6 +339,8 @@ function SiegeEngineList:make_entry_text(engine)
329339
return out_tokens
330340
end
331341

342+
-- Refresh the engine information being displayed, but not the list.
343+
-- Updating data here *does not* add or remove new/deleted engines.
332344
function SiegeEngineList:refresh_data()
333345
local old_engines = self.engines
334346
self.engines = get_siege_engines()
@@ -350,19 +362,40 @@ function SiegeEngineList:refresh_data()
350362
end
351363
end
352364

365+
-- Refresh the engine list, updating to display new/deleted engines correctly.
353366
function SiegeEngineList:refresh_view(refresh_data)
354367
if refresh_data then self:refresh_data() end
355368
local choices = {}
356369
for _, data in pairs(self.engines) do
357370
table.insert(choices, {
358371
text=self:make_entry_text(data),
359372
search_key="",
360-
data=data
373+
data=data.id
361374
});
362375
end
363376
self.subviews.list:setChoices(choices)
364377
end
365378

379+
function SiegeEngineList:reveal_selected()
380+
local _, selected = self.subviews.list:getSelected()
381+
if selected ~= nil then
382+
dfhack.gui.revealInDwarfmodeMap(self.engines[selected.data].pos, true, true)
383+
end
384+
end
385+
386+
function SiegeEngineList:set_selected_action(action)
387+
local _, selected = self.subviews.list:getSelected()
388+
389+
local successful = set_siege_engine_action(selected.data, action)
390+
if not successful then
391+
self:refresh_view(true)
392+
return
393+
end
394+
395+
-- Successfully updated, just update the cached state
396+
self.engines[selected.data].action = action
397+
end
398+
366399
function SiegeEngineList:onInput(keys)
367400
if not keys._MOUSE_L then
368401
SiegeEngineList.super.onInput(self, keys)
@@ -382,13 +415,13 @@ function SiegeEngineList:onInput(keys)
382415
return
383416
end
384417

385-
self.subviews.list:setSelected(idx)
418+
list:setSelected(idx)
386419

387-
local engine = list:getChoices()[idx].data
420+
-- 0 is goto, 1 is blank, following are action buttons
388421
local button_pressed = math.ceil((x-self.button_start_x+1)/3)-1
389422

390423
if button_pressed == 0 then
391-
dfhack.gui.revealInDwarfmodeMap(engine.pos, true, true)
424+
self:reveal_selected()
392425
return
393426
end
394427

@@ -398,14 +431,7 @@ function SiegeEngineList:onInput(keys)
398431
end
399432

400433
local action = action_button_order[button_pressed-1]
401-
local successful = set_siege_engine_action(engine.id, action)
402-
if not successful then
403-
self:refresh_view(true)
404-
return
405-
end
406-
407-
-- Successfully updated, just update the cached state
408-
self.engines[engine.id].action = action
434+
self:set_selected_action(action)
409435
end
410436

411437
-- SiegeManager
@@ -423,7 +449,7 @@ function SiegeManager:init()
423449
self:addviews({
424450
SiegeEngineList {},
425451
widgets.CycleHotkeyLabel {
426-
frame={b=1},
452+
frame={b=3},
427453
key='CUSTOM_T',
428454
on_change=self:callback('set_type_filter'),
429455
label='Show Types:',
@@ -435,12 +461,38 @@ function SiegeManager:init()
435461
},
436462
initial_option=1,
437463
},
464+
widgets.HotkeyLabel {
465+
frame={b=0},
466+
key='CUSTOM_CTRL_C',
467+
label='Reveal in World',
468+
on_activate=self:callback('reveal_selected')
469+
},
438470
})
471+
472+
for i, action_button in ipairs(action_button_order) do
473+
self:addviews({
474+
widgets.HotkeyLabel {
475+
frame = {b=1, l=(i - 1)*2},
476+
key = action_button_keybinds[i],
477+
key_sep = i == #action_button_order and ': ' or '',
478+
label = i == #action_button_order and 'Set Action' or '',
479+
on_activate = self:callback('set_action', action_button)
480+
}
481+
})
482+
end
439483
end
440484

441485
function SiegeManager:set_type_filter(new)
442486
self.subviews.list.type_filter = new
443-
self.subviews.list:hard_refresh()
487+
self.subviews.list:refresh_view(true)
488+
end
489+
490+
function SiegeManager:reveal_selected()
491+
self.subviews.list:reveal_selected()
492+
end
493+
494+
function SiegeManager:set_action(action)
495+
self.subviews.list:set_selected_action(action)
444496
end
445497

446498
-- SiegeManagerScreen
@@ -459,5 +511,4 @@ if not dfhack.isMapLoaded() then
459511
qerror('requires a map to be loaded')
460512
end
461513

462-
view = SiegeManagerScreen{}:show()
463-
-- view = view and view:raise() or SiegeManagerScreen{}:show()
514+
view = view and view:raise() or SiegeManagerScreen{}:show()

0 commit comments

Comments
 (0)