dfhack/scripts/gui/mechanisms.lua

155 lines
4.1 KiB
Lua

-- Shows mechanisms linked to the current building.
local utils = require 'utils'
local gui = require 'gui'
local guidm = require 'gui.dwarfmode'
function getBuildingName(building)
return utils.call_with_string(building, 'getName')
end
function getBuildingCenter(building)
return xyz2pos(building.centerx, building.centery, building.z)
end
function listMechanismLinks(building)
local lst = {}
local function push(item, mode)
if item then
lst[#lst+1] = {
obj = item, mode = mode,
name = getBuildingName(item),
center = getBuildingCenter(item)
}
end
end
push(building, 'self')
if not df.building_actual:is_instance(building) then
return lst
end
local item, tref, tgt
for _,v in ipairs(building.contained_items) do
item = v.item
if df.item_trappartsst:is_instance(item) then
tref = dfhack.items.getGeneralRef(item, df.general_ref_type.BUILDING_TRIGGER)
if tref then
push(tref:getBuilding(), 'trigger')
end
tref = dfhack.items.getGeneralRef(item, df.general_ref_type.BUILDING_TRIGGERTARGET)
if tref then
push(tref:getBuilding(), 'target')
end
end
end
return lst
end
MechanismList = defclass(MechanismList, guidm.MenuOverlay)
MechanismList.focus_path = 'mechanisms'
function MechanismList.new(building)
local self = {
links = {},
selected = 1
}
return mkinstance(MechanismList, self):init(building)
end
function MechanismList:init(building)
local links = listMechanismLinks(building)
links[1].viewport = self:getViewport()
links[1].cursor = guidm.getCursorPos()
if #links <= 1 then
links[1].mode = 'none'
end
self.links = links
self.selected = 1
return self
end
local colors = {
self = COLOR_CYAN, none = COLOR_CYAN,
trigger = COLOR_GREEN, target = COLOR_GREEN
}
local icons = {
self = 128, none = 63, trigger = 27, target = 26
}
function MechanismList:onRenderBody(dc)
dc:clear()
dc:seek(1,1):string("Mechanism Links", COLOR_WHITE):newline()
for i,v in ipairs(self.links) do
local pen = { fg=colors[v.mode], bold = (i == self.selected) }
dc:newline(1):pen(pen):char(icons[v.mode])
dc:advance(1):string(v.name)
end
local nlinks = #self.links
if nlinks <= 1 then
dc:newline():newline(1):string("This building has no links", COLOR_LIGHTRED)
end
dc:newline():newline(1):pen(COLOR_WHITE)
dc:string("Esc", COLOR_LIGHTGREEN):string(": Back, ")
dc:string("Enter", COLOR_LIGHTGREEN):string(": Switch")
end
function MechanismList:zoomToLink(link,back)
df.global.world.selected_building = link.obj
if back then
guidm.setCursorPos(link.cursor)
self:getViewport(link.viewport):set()
else
guidm.setCursorPos(link.center)
self:getViewport():reveal(link.center, 5, 0, 10):set()
end
end
function MechanismList:changeSelected(delta)
if #self.links <= 1 then return end
self.selected = 1 + (self.selected + delta - 1) % #self.links
self:zoomToLink(self.links[self.selected])
end
function MechanismList:onInput(keys)
if keys.SECONDSCROLL_UP then
self:changeSelected(-1)
elseif keys.SECONDSCROLL_DOWN then
self:changeSelected(1)
elseif keys.LEAVESCREEN then
self:dismiss()
if self.selected ~= 1 then
self:zoomToLink(self.links[1], true)
end
elseif keys.SELECT_ALL then
if self.selected > 1 then
self:init(self.links[self.selected].obj)
end
elseif keys.SELECT then
self:dismiss()
elseif self:simulateViewScroll(keys) then
return
end
end
if not df.viewscreen_dwarfmodest:is_instance(dfhack.gui.getCurViewscreen()) then
qerror("This script requires the main dwarfmode view")
end
if df.global.ui.main.mode ~= df.ui_sidebar_mode.QueryBuilding then
qerror("This script requires the 'q' interface mode")
end
local list = MechanismList.new(df.global.world.selected_building)
list:show()
list:changeSelected(1)