Gui for item selection in advfort

develop
Warmist 2014-12-10 00:09:28 +02:00
parent f47565465e
commit 550cddc604
2 changed files with 207 additions and 23 deletions

@ -51,7 +51,7 @@ local utils=require 'utils'
local tile_attrs = df.tiletype.attrs local tile_attrs = df.tiletype.attrs
settings={build_by_items=false,use_worn=false,check_inv=true,teleport_items=true,df_assign=false} settings={build_by_items=false,use_worn=false,check_inv=false,teleport_items=true,df_assign=false,gui_item_select=false}
function hasValue(tbl,val) function hasValue(tbl,val)
for k,v in pairs(tbl) do for k,v in pairs(tbl) do
@ -707,48 +707,65 @@ function AssignJobItems(args)
for job_id, trg_job_item in ipairs(job.job_items) do for job_id, trg_job_item in ipairs(job.job_items) do
item_counts[job_id]=trg_job_item.quantity item_counts[job_id]=trg_job_item.quantity
end end
local item_suitability={}
local used_item_id={} local used_item_id={}
for job_id, trg_job_item in ipairs(job.job_items) do for job_id, trg_job_item in ipairs(job.job_items) do
item_suitability[job_id]={}
for _,cur_item in pairs(its) do for _,cur_item in pairs(its) do
if not used_item_id[cur_item.id] then if not used_item_id[cur_item.id] then
local item_suitable,msg=isSuitableItem(trg_job_item,cur_item) local item_suitable,msg=isSuitableItem(trg_job_item,cur_item)
if item_suitable or settings.build_by_items then
table.insert(item_suitability[job_id],cur_item)
end
--[[ --[[
if msg then if msg then
print(cur_item,msg) print(cur_item,msg)
end end
]]-- ]]--
if not settings.gui_item_select then
if (item_counts[job_id]>0 and item_suitable) or settings.build_by_items then if (item_counts[job_id]>0 and item_suitable) or settings.build_by_items then
--cur_item.flags.in_job=true --cur_item.flags.in_job=true
job.items:insert("#",{new=true,item=cur_item,role=df.job_item_ref.T_role.Reagent,job_item_idx=job_id}) job.items:insert("#",{new=true,item=cur_item,role=df.job_item_ref.T_role.Reagent,job_item_idx=job_id})
item_counts[job_id]=item_counts[job_id]-cur_item:getTotalDimension() item_counts[job_id]=item_counts[job_id]-cur_item:getTotalDimension()
--print(string.format("item added, job_item_id=%d, item %s, quantity left=%d",job_id,tostring(cur_item),item_counts[job_id])) --print(string.format("item added, job_item_id=%d, item %s, quantity left=%d",job_id,tostring(cur_item),item_counts[job_id]))
used_item_id[cur_item.id]=true used_item_id[cur_item.id]=true
end
end end
end end
end end
end end
if settings.gui_item_select then
require('gui.script').start(function()
require('hack.scripts.gui.advfort_items').showItemEditor(job,item_suitability)
end)
if not settings.build_by_items then else
for job_id, trg_job_item in ipairs(job.job_items) do if not settings.build_by_items then
if item_counts[job_id]>0 then for job_id, trg_job_item in ipairs(job.job_items) do
print("Not enough items for this job") if item_counts[job_id]>0 then
return false, "Not enough items for this job" print("Not enough items for this job")
return false, "Not enough items for this job"
end
end end
end end
end end
local haul_fix=false local item_mode="teleport"
if job.job_type==df.job_type.PlantSeeds then local item_modes={
haul_fix=true [df.job_type.PlantSeeds]="haul",
end [df.job_type.ConstructBuilding]="default",
if settings.teleport_items and not haul_fix then }
item_mode=item_modes[job.job_type]
if settings.teleport_items and item_mode=="teleport" then
putItemsInBuilding(args.building,job.items) putItemsInBuilding(args.building,job.items)
end end
local uncollected = getItemsUncollected(job) local uncollected = getItemsUncollected(job)
if #uncollected == 0 then if #uncollected == 0 then
job.flags.working=true job.flags.working=true
if haul_fix then if item_mode=="haul" then
putItemsInHauling(args.unit,job.items) putItemsInHauling(args.unit,job.items)
end end
else else
@ -773,7 +790,6 @@ function CheckAndFinishBuilding(args,bld)
if args.job~=nil then if args.job~=nil then
local ok,msg=AssignJobItems(args) local ok,msg=AssignJobItems(args)
if not ok then if not ok then
print(msg)
return false,msg return false,msg
else else
AssignUnitToJob(args.job,args.unit,args.from_pos) AssignUnitToJob(args.job,args.unit,args.from_pos)
@ -1017,6 +1033,7 @@ function siegeWeaponActionChosen(building,actionid)
local ok,msg=makeJob(args) local ok,msg=makeJob(args)
if not ok then if not ok then
dfhack.gui.showAnnouncement(msg,5,1) dfhack.gui.showAnnouncement(msg,5,1)
CancelJob(args.unit)
end end
end end
end end
@ -1051,7 +1068,11 @@ function usetool:onWorkShopButtonClicked(building,index,choice)
if #building.jobs>0 then if #building.jobs>0 then
local job=building.jobs[#building.jobs-1] local job=building.jobs[#building.jobs-1]
AssignUnitToJob(job,adv,adv.pos) AssignUnitToJob(job,adv,adv.pos)
AssignJobItems{job=job,from_pos=adv.pos,pos=adv.pos,unit=adv,building=building} local ok,msg=AssignJobItems{job=job,from_pos=adv.pos,pos=adv.pos,unit=adv,building=building}
if not ok then
dfhack.gui.showAnnouncement(msg,5,1)
CancelJob(adv)
end
end end
elseif df.interface_button_building_category_selectorst:is_instance(choice.button) or elseif df.interface_button_building_category_selectorst:is_instance(choice.button) or
df.interface_button_building_material_selectorst:is_instance(choice.button) then df.interface_button_building_material_selectorst:is_instance(choice.button) then
@ -1198,7 +1219,11 @@ function usetool:farmPlot(building)
if not job then if not job then
print(msg) print(msg)
else else
print(AssignJobItems(args)) --WHY U NO WORK? local ok, msg=AssignJobItems(args)
if not ok then
dfhack.gui.showAnnouncement(msg,5,1)
CancelJob(args.unit)
end
end end
end end
MODES={ MODES={

@ -0,0 +1,159 @@
local _ENV = mkmodule('hack.scripts.gui.advfort_items')
local gui=require('gui')
local wid=require('gui.widgets')
local gscript=require('gui.script')
jobitemEditor=defclass(jobitemEditor,gui.FramedScreen)
jobitemEditor.ATTRS{
frame_style = gui.GREY_LINE_FRAME,
frame_inset = 1,
allow_add=false,
allow_remove=false,
allow_any_item=false,
job=DEFAULT_NIL,
items=DEFAULT_NIL,
}
function update_slot_text(slot)
local items=""
for i,v in ipairs(slot.items) do
items=items.." "..dfhack.items.getDescription(v,0)
if i~=#slot.items then
items=items..","
end
end
slot.text=string.format("%02d. Filled(%d/%d):%s",slot.id+1,slot.filled_amount,slot.job_item.quantity,items)
end
--items-> table => key-> id of job.job_items, value-> table => key (num), value => item(ref)
function jobitemEditor:init(args)
--self.job=args.job
if self.job==nil then qerror("This screen must have job target") end
if self.items==nil then qerror("This screen must have item list") end
self:addviews{
wid.Label{
view_id = 'label',
text = args.prompt,
text_pen = args.text_pen,
frame = { l = 0, t = 0 },
},
wid.List{
view_id = 'itemList',
frame = { l = 0, t = 2 ,b=2},
},
wid.Label{
frame = { b=1,l=1},
text ={{text= ": cancel",
key = "LEAVESCREEN",
on_activate= self:callback("dismiss")
},
{
gap=3,
text= ": accept",
key = "SEC_SELECT",
on_activate= self:callback("commit"),
enabled=self:callback("jobValid")
},
{
gap=3,
text= ": add",
key = "CUSTOM_A",
enabled=self:callback("can_add"),
on_activate= self:callback("add_item")
},
{
gap=3,
text= ": remove",
key = "CUSTOM_R",
enabled=self:callback("can_remove"),
on_activate= self:callback("remove_item")
},}
},
}
self.assigned={}
self:fill()
end
function jobitemEditor:get_slot()
local idx,choice=self.subviews.itemList:getSelected()
return choice
end
function jobitemEditor:can_add()
local slot=self:get_slot()
return slot.filled_amount<slot.job_item.quantity
end
function jobitemEditor:can_remove()
local slot=self:get_slot()
return #slot.items>0
end
function jobitemEditor:add_item()
local cur_slot=self:get_slot()
local choices={}
table.insert(choices,{text="<no item>"})
for k,v in pairs(cur_slot.choices) do
if not self.assigned[v.id] then
table.insert(choices,{text=dfhack.items.getDescription(v,0),item=v})
end
end
gscript.start(function ()
local _,_2,choice=gscript.showListPrompt("which item?", "Select item", COLOR_WHITE, choices)
if choice ~= nil and choice.item~=nil then
self:add_item_to_slot(cur_slot,choice.item)
end
end
)
end
function jobitemEditor:add_item_to_slot(slot,item)
table.insert(slot.items,item)
slot.filled_amount=slot.filled_amount+item:getTotalDimension()
self.assigned[item.id]=true
update_slot_text(slot)
self.subviews.itemList:setChoices(self.slots)
end
function jobitemEditor:remove_item()
local slot=self:get_slot()
for k,v in pairs(slot.items) do
self.assigned[v.id]=nil
end
slot.items={}
slot.filled_amount=0
update_slot_text(slot)
self.subviews.itemList:setChoices(self.slots)
end
function jobitemEditor:fill()
self.slots={}
for k,v in pairs(self.items) do
table.insert(self.slots,{job_item=self.job.job_items[k], id=k, items={},choices=v,filled_amount=0,slot_id=#self.slots})
update_slot_text(self.slots[#self.slots])
end
self.subviews.itemList:setChoices(self.slots)
end
function jobitemEditor:jobValid()
for k,v in pairs(self.slots) do
if v.filled_amount<v.job_item.quantity then
return false
end
end
return true
end
function jobitemEditor:commit()
for _,slot in pairs(self.slots) do
for _1,cur_item in pairs(slot.items) do
self.job.items:insert("#",{new=true,item=cur_item,role=df.job_item_ref.T_role.Reagent,job_item_idx=slot.id})
end
end
self:dismiss()
end
function showItemEditor(job,item_selections)
jobitemEditor{
job = job,
items = item_selections,
on_close = gscript.qresume(nil)
}:show()
return gscript.wait()
end
return _ENV