From 550cddc60481f00826ea7ccbcd8fc3897ccb7441 Mon Sep 17 00:00:00 2001 From: Warmist Date: Wed, 10 Dec 2014 00:09:28 +0200 Subject: [PATCH] Gui for item selection in advfort --- scripts/gui/advfort.lua | 71 ++++++++++----- scripts/gui/advfort_items.lua | 159 ++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+), 23 deletions(-) create mode 100644 scripts/gui/advfort_items.lua diff --git a/scripts/gui/advfort.lua b/scripts/gui/advfort.lua index dc6b33cf9..476753450 100644 --- a/scripts/gui/advfort.lua +++ b/scripts/gui/advfort.lua @@ -51,7 +51,7 @@ local utils=require 'utils' 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) 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 item_counts[job_id]=trg_job_item.quantity end + local item_suitability={} local used_item_id={} for job_id, trg_job_item in ipairs(job.job_items) do + item_suitability[job_id]={} + for _,cur_item in pairs(its) do 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 print(cur_item,msg) end ]]-- - - if (item_counts[job_id]>0 and item_suitable) or settings.build_by_items then - --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}) - 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])) - used_item_id[cur_item.id]=true + if not settings.gui_item_select then + if (item_counts[job_id]>0 and item_suitable) or settings.build_by_items then + --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}) + 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])) + used_item_id[cur_item.id]=true + 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 - for job_id, trg_job_item in ipairs(job.job_items) do - if item_counts[job_id]>0 then - print("Not enough items for this job") - return false, "Not enough items for this job" + else + if not settings.build_by_items then + for job_id, trg_job_item in ipairs(job.job_items) do + if item_counts[job_id]>0 then + print("Not enough items for this job") + return false, "Not enough items for this job" + end end end end - local haul_fix=false - if job.job_type==df.job_type.PlantSeeds then - haul_fix=true - end - if settings.teleport_items and not haul_fix then + local item_mode="teleport" + local item_modes={ + [df.job_type.PlantSeeds]="haul", + [df.job_type.ConstructBuilding]="default", + } + item_mode=item_modes[job.job_type] + + if settings.teleport_items and item_mode=="teleport" then putItemsInBuilding(args.building,job.items) end + local uncollected = getItemsUncollected(job) if #uncollected == 0 then job.flags.working=true - if haul_fix then + if item_mode=="haul" then putItemsInHauling(args.unit,job.items) end else @@ -773,7 +790,6 @@ function CheckAndFinishBuilding(args,bld) if args.job~=nil then local ok,msg=AssignJobItems(args) if not ok then - print(msg) return false,msg else AssignUnitToJob(args.job,args.unit,args.from_pos) @@ -1017,6 +1033,7 @@ function siegeWeaponActionChosen(building,actionid) local ok,msg=makeJob(args) if not ok then dfhack.gui.showAnnouncement(msg,5,1) + CancelJob(args.unit) end end end @@ -1051,7 +1068,11 @@ function usetool:onWorkShopButtonClicked(building,index,choice) if #building.jobs>0 then local job=building.jobs[#building.jobs-1] 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 elseif df.interface_button_building_category_selectorst:is_instance(choice.button) or df.interface_button_building_material_selectorst:is_instance(choice.button) then @@ -1198,7 +1219,11 @@ function usetool:farmPlot(building) if not job then print(msg) 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 MODES={ diff --git a/scripts/gui/advfort_items.lua b/scripts/gui/advfort_items.lua new file mode 100644 index 000000000..10639627e --- /dev/null +++ b/scripts/gui/advfort_items.lua @@ -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_amount0 +end +function jobitemEditor:add_item() + local cur_slot=self:get_slot() + local choices={} + table.insert(choices,{text=""}) + 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