--local _ENV = mkmodule('gui.addjob-replace') -- does not work for some reason
-- print("loading job overlay")
local eventful = require 'plugins.eventful'
local utils = require 'utils'
local gui = require 'gui'
local guidm = require 'gui.dwarfmode'
local guimat = require 'gui.materials'
local widgets = require 'gui.widgets'
local dlg = require 'gui.dialogs'
local ws = require 'dfhack.workshops'
MyJobOverlay = defclass(MyJobOverlay, guidm.WorkshopOverlay)
MyJobOverlay.focus_path = "dwarfmode/QueryBuilding/Some/Workshop/AddJob"
MyJobOverlay.myWorkshop = 'MYWORKSHOP'
MyJobOverlay.firstpage = true -- which level of the menu we are in.
MyJobOverlay.ATTRS {
wshop = DEFAULT_NIL, -- presumably unused
frame_inset = 1,
frame_background = COLOR_BLACK,
}
-- setting up the basic menu structure
function MyJobOverlay:init(args)
self:addviews{
widgets.Label{
frame = { l = 0, t = 0 },
text = {
{ text = 'workshop',}
}
},
widgets.List{
view_id = 'list',
frame = { l = 0, r = 0, t = 2 }, --, b = 2
on_submit = self:callback('onSubmitItem'),
scroll_keys = widgets.SECONDSCROLL,
},
widgets.Label{
view_id = 'back',
frame = { l = 0, b = 0 },
text = {
{ key = 'LEAVESCREEN', text = ': Back',
on_activate = self:callback('dismiss') } -- should check wether to close or go back one level
}
},
}
self:initListChoices()
end
-- first layer of the menu. these choices are over a couple of reaction classes but could be others as well
function MyJobOverlay:initListChoices()
local choices = {}
table.insert(choices, {text = 'some group of materials', key = 'CUSTOM_A', cb = self:callback('initMatMode', 'MY_REACTION_CLASS_1')})
table.insert(choices, {text = 'another group', key = 'CUSTOM_B', cb = self:callback('initMatMode', 'MY_REACTION_CLASS_2')})
table.insert(choices, {text = 'weird stuff', key = 'CUSTOM_C', cb = self:callback('initMatMode', 'MY_REACTION_CLASS_3')})
self:pushContext('Top Layer', choices) -- name doesnt matter
end
-- check through all the materials using the reaction class from above as filter
function MyJobOverlay:initMatMode(rclass)
local choices = {}
local foo = true
for i,mat in ipairs(df.global.world.raws.inorganics) do
local m = mat.material
if mat.material.reaction_class then
for k, v in pairs(mat.material.reaction_class) do
if (v.value == rclass) then
-- print("found mat: "..mat.id.." in reaction class: "..rclass)
self:addMaterial(choices, mat.material, i, mat, rclass)
end
end
end
end
self:pushContext(rclass, choices)
end
-- add choices into the second level of the menu for each material that qualifies
-- (should check here if items are available so menu items can be displayed in red / disabled)
function MyJobOverlay:addMaterial(choices, mat, idx, parent, rclass)
-- Find the material name
local state = 0
if mat.heat.melting_point <= 10015 then
state = 1
end
local name = mat.state_name[state]
name = string.gsub(name, '^frozen ','')
name = string.gsub(name, '^molten ','')
name = string.gsub(name, '^condensed ','')
name = string.gsub(name, '^boiling ','')
table.insert(choices, {
text = 'smelt '..name,
search_key = key,
material = mat,
mat_type = 0,
mat_index = idx,
cls = rclass,
})
end
function MyJobOverlay:pushContext(name, choices)
if not self.back_stack then
self.back_stack = {}
self.firstpage = true
else
table.insert(self.back_stack, {
context_str = self.context_str,
all_choices = self.subviews.list:getChoices(),
selected = self.subviews.list:getSelected(),
})
self.firstpage = false
end
self.context_str = name
self.subviews.list:setChoices(choices, 1)
end
function MyJobOverlay:onGoBack()
local save = table.remove(self.back_stack)
self.firstpage = true
self.context_str = save.context_str
self.subviews.list:setChoices(save.all_choices)
end
function MyJobOverlay:onSubmitItem(idx, item)
if item.cb then
item:cb(idx)
else
self:submitMaterial(item.text, item.material, item.mat_type, item.mat_index, item.cls)
end
end
local function get_reaction(name)
if not reaction_id_cache then
reaction_id_cache = {}
for i,v in ipairs(df.global.world.raws.reactions) do
reaction_id_cache[v.code] = i
end
end
local id = reaction_id_cache[name] or -1
return id, df.reaction.find(id)
end
-- setting up some fields for each job item
local function reagentToJobItem(reagent,react_id,reagentId, typ, index, cls)
local ret_item
ret_item = utils.clone_with_default(reagent, ws.input_filter_defaults)
ret_item.reaction_id = react_id
ret_item.reagent_index = reagentId
ret_item.new = true --?
if reagent.code == 'ore' then -- we check the name of the reagent here to only set the below fields for the main ingredient
ret_item.mat_type = typ
ret_item.mat_index = index
ret_item.reaction_class = cls
end
return ret_item
end
-- after selecting a material, we select the appropriate reaction if multiple are present
-- then we create a job and feed it with item/material data from that reaction & our selection
function MyJobOverlay:submitMaterial(text, mat, typ, index, cls) -- mat unused
-- selecting a reaction based on the mat choice, because they may need different secondary ingredients
-- you could use just one reaction for all and instead add job items later
local rname
if cls == 'MY_REACTION_CLASS_3' then
rname = 'SPECIAL_REACTION'
else
rname = 'EXAMPLE_REACTION'
end
local rid, reaction = get_reaction(rname)
local job = df.job:new()
job.id = df.global.job_next_id
df.global.job_next_id = df.global.job_next_id + 1
dfhack.job.linkIntoWorld(job, true)
job_fields = {
job_type = df.job_type.CustomReaction,
reaction_name = rname,
mat_type = typ,
mat_index = index,
}
job:assign(job_fields)
job.general_refs:insert("#",{new = df.general_ref_building_holderst,building_id = self.wshop.id}) -- workshop reference
for reagentId,reagent in pairs(reaction.reagents) do -- reaction reagents need some more fields before they can be used in the job
job.job_items:insert('#', reagentToJobItem(reagent,rid,reagentId, typ, index, cls))
end
-- need to add additional fuel here for [FUEL] reactions, if not at a magma powedered shop
-- too lazy & and not tested
-- local fuel={item_type=df.item_type.BAR,mat_type=df.builtin_mats.COAL}
-- job.job_items:insert('#', reagentToJobItem(fuel,rid,reagentId, typ, index, cls))
self.wshop.jobs:insert("#",job)
self:dismiss()
end
function MyJobOverlay:onInput(keys)
if keys.LEAVESCREEN or keys.LEAVESCREEN_ALL then
if not self.firstpage and not keys.LEAVESCREEN_ALL then
self:onGoBack()
else
self:dismiss()
if self.on_cancel then
self.on_cancel()
end
end
else
self:inputToSubviews(keys)
end
end
function MyJobOverlay:onDestroy()
if self.on_close then
self.on_close()
end
end
-- if we submit a job choice, we dont want to leave the whole workshop, so we just re-enter it
function MyJobOverlay:on_close()
gui.simulateInput(dfhack.gui.getCurViewscreen(), 'LEAVESCREEN')
gui.simulateInput(dfhack.gui.getCurViewscreen(), 'D_BUILDJOB')
end
-- we query this function every frame to see if the gui focus changed to the menu we want to replace
local function queryFocus()
local wshop = dfhack.gui.getSelectedBuilding()
if wshop and wshop.custom_type and df.building_def_workshopst.find(wshop.custom_type).code == MyJobOverlay.myWorkshop then
if dfhack.gui.getFocusString(dfhack.gui.getCurViewscreen()) == MyJobOverlay.focus_path and
wshop:getMaxBuildStage() == wshop:getBuildStage() then -- this is probably unnecessary because the Addjob focus isnt there if unbuilt
-- print("entered focus menu")
MyJobOverlay{wshop=wshop}:show()
dfhack.timeout_active(timer, nil)
return
end
timer = dfhack.timeout(1,'frames',queryFocus) -- we are still in the building, but in a different focus. so keep the query going
else
-- print("left workshop menu")
dfhack.timeout_active(timer, nil)
return
end
end
-- eventful calls this when we enter the workshop registered below, and this in turn enables above callin
function fillSideBarCallback(wshop)
timer = dfhack.timeout(1,'frames',queryFocus)
end
eventful.registerSidebar(MyJobOverlay.myWorkshop, fillSideBarCallback, true)
-- print("job overlay loaded")
-- return _ENV