Work started on adventurer workshops.

develop
Warmist 2012-12-01 18:20:27 +02:00
parent 0fb5ad7729
commit 397fdb00ae
1 changed files with 328 additions and 108 deletions

@ -1,4 +1,16 @@
-- allows to do jobs in adv. mode. -- allows to do jobs in adv. mode.
keybinds={
nextJob={key="CUSTOM_SHIFT_T",desc="Next job in the list"},
prevJob={key="CUSTOM_SHIFT_R",desc="Previous job in the list"},
continue={key="A_WAIT",desc="Continue job if available"},
down_alt1={key="CUSTOM_CTRL_D",desc="Use job down"},
down_alt2={key="CURSOR_DOWN_Z_AUX",desc="Use job down"},
up_alt1={key="CUSTOM_CTRL_E",desc="Use job up"},
up_alt2={key="CURSOR_UP_Z_AUX",desc="Use job up"},
use_same={key="A_MOVE_SAME_SQUARE",desc="Use job at the tile you are standing"},
workshop={key="CHANGETAB",desc="Show workshop jobs"},
}
local gui = require 'gui' local gui = require 'gui'
local wid=require 'gui.widgets' local wid=require 'gui.widgets'
local dialog=require 'gui.dialogs' local dialog=require 'gui.dialogs'
@ -6,6 +18,7 @@ local buildings=require 'dfhack.buildings'
local bdialog=require 'gui.buildings' local bdialog=require 'gui.buildings'
local tile_attrs = df.tiletype.attrs local tile_attrs = df.tiletype.attrs
settings={build_by_items=false,check_inv=false,df_assign=true} settings={build_by_items=false,check_inv=false,df_assign=true}
for k,v in ipairs({...}) do for k,v in ipairs({...}) do
if v=="-c" or v=="--cheat" then if v=="-c" or v=="--cheat" then
@ -18,17 +31,10 @@ for k,v in ipairs({...}) do
settings.df_assign=false settings.df_assign=false
end end
end end
mode=mode or 0 mode=mode or 0
keybinds={
key_next={key="CUSTOM_SHIFT_T",desc="Next job in the list"},
key_prev={key="CUSTOM_SHIFT_R",desc="Previous job in the list"},
key_continue={key="A_WAIT",desc="Continue job if available"},
key_down_alt1={key="CUSTOM_CTRL_D",desc="Use job down"},
key_down_alt2={key="CURSOR_DOWN_Z_AUX",desc="Use job down"},
key_up_alt1={key="CUSTOM_CTRL_E",desc="Use job up"},
key_up_alt2={key="CURSOR_UP_Z_AUX",desc="Use job up"},
key_use_same={key="A_MOVE_SAME_SQUARE",desc="Use job at the tile you are standing"},
}
function Disclaimer(tlb) function Disclaimer(tlb)
local dsc={"The Gathering Against ",{text="Goblin ",pen=dfhack.pen.parse{fg=COLOR_GREEN,bg=0}}, "Oppresion ", local dsc={"The Gathering Against ",{text="Goblin ",pen=dfhack.pen.parse{fg=COLOR_GREEN,bg=0}}, "Oppresion ",
"(TGAGO) is not responsible for all ",NEWLINE,"the damage that this tool can (and will) cause to you and your loved worlds",NEWLINE,"and/or sanity.Please use with caution.",NEWLINE,{text="Magma not included.",pen=dfhack.pen.parse{fg=COLOR_LIGHTRED,bg=0}}} "(TGAGO) is not responsible for all ",NEWLINE,"the damage that this tool can (and will) cause to you and your loved worlds",NEWLINE,"and/or sanity.Please use with caution.",NEWLINE,{text="Magma not included.",pen=dfhack.pen.parse{fg=COLOR_LIGHTRED,bg=0}}}
@ -57,6 +63,7 @@ function showHelp()
Disclaimer(helptext) Disclaimer(helptext)
require("gui.dialogs").showMessage("Help!?!",helptext) require("gui.dialogs").showMessage("Help!?!",helptext)
end end
function getLastJobLink() function getLastJobLink()
local st=df.global.world.job_list local st=df.global.world.job_list
while st.next~=nil do while st.next~=nil do
@ -64,24 +71,24 @@ function getLastJobLink()
end end
return st return st
end end
function AddNewJob(job) function addNewJob(job)
local nn=getLastJobLink() local lastLink=getLastJobLink()
local nl=df.job_list_link:new() local newLink=df.job_list_link:new()
nl.prev=nn newLink.prev=lastLink
nn.next=nl lastLink.next=newLink
nl.item=job newLink.item=job
job.list_link=nl job.list_link=newLink
end end
function MakeJob(args) function MakeJob(args)
local nj=df.job:new() local newJob=df.job:new()
nj.id=df.global.job_next_id newJob.id=df.global.job_next_id
df.global.job_next_id=df.global.job_next_id+1 df.global.job_next_id=df.global.job_next_id+1
--nj.flags.special=true --newJob.flags.special=true
nj.job_type=args.job_type newJob.job_type=args.job_type
nj.completion_timer=-1 newJob.completion_timer=-1
nj.pos:assign(args.pos) newJob.pos:assign(args.pos)
args.job=nj args.job=newJob
local failed=false local failed=false
for k,v in ipairs(args.pre_actions or {}) do for k,v in ipairs(args.pre_actions or {}) do
local ok,msg=v(args) local ok,msg=v(args)
@ -91,13 +98,13 @@ function MakeJob(args)
end end
end end
if not failed then if not failed then
AssignUnitToJob(nj,args.unit,args.from_pos) AssignUnitToJob(newJob,args.unit,args.from_pos)
end end
for k,v in ipairs(args.post_actions or {}) do for k,v in ipairs(args.post_actionss or {}) do
v(args) v(args)
end end
AddNewJob(nj) addNewJob(newJob)
return nj return newJob
end end
function AssignUnitToJob(job,unit,unit_pos) function AssignUnitToJob(job,unit,unit_pos)
@ -219,7 +226,7 @@ function IsTree(args)
end end
function IsPlant(args) function IsPlant(args)
local tt=dfhack.maps.getTileType(args.pos) local tt=dfhack.maps.getTileType(args.pos)
if tile_attrs[tt].shape==df.tiletype_shape.PLANT then if tile_attrs[tt].shape==df.tiletype_shape.SHRUB then
return true return true
else else
return false, "Can only do it on plants" return false, "Can only do it on plants"
@ -282,10 +289,58 @@ function RemoveBuilding(args)
return false,"No building to remove" return false,"No building to remove"
end end
end end
function AssignJobItems(args) function isSuitableItem(job_item,item)
if settings.df_assign then
if job_item.item_type~=-1 then
if item:getType()~= job_item.item_type then
return false, "type"
elseif job_item.item_subtype~=-1 then
if item:getSubtype()~=job_item.item_subtype then
return false,"subtype"
end
end
end
if job_item.mat_type~=-1 then
if item:getActualMaterial()~= job_item.mat_type then --unless we would want to make hist-fig specific reactions
return false, "material"
elseif job_item.mat_index~=-1 then
if item:getActualMaterialIndex()~=job_item.mat_index then
return false,"material index"
end
end
end
local matinfo=dfhack.matinfo.decode(item)
--print(matinfo:getCraftClass())
if not matinfo:matches(job_item) then
return false,"matinfo"
end
--reagen_index?? reaction_id??
if job_item.metal_ore~=-1 and not item:isMetalOre(job_item.metal_ore) then
return false,"metal ore"
end
if job_item.min_dimension~=-1 then
end
if #job_item.contains~=0 then
end
if job_item.has_tool_use~=-1 then
if not item:hasToolUse(job_item.has_tool_use) then
return false,"tool use"
end
end
if job_item.has_material_reaction_product~="" then
end
if job_item.reaction_class~="" then
end
return true return true
end end
function AssignJobItems(args,is_workshop_job)
if settings.df_assign and not is_workshop_job then
return true
end
--print("Assign")
--printall(args) --printall(args)
local job=args.job local job=args.job
local its=itemsAtPos(args.from_pos) local its=itemsAtPos(args.from_pos)
@ -293,6 +348,16 @@ function AssignJobItems(args)
for k,v in pairs(args.unit.inventory) do for k,v in pairs(args.unit.inventory) do
table.insert(its,v.item) table.insert(its,v.item)
end end
local contained={}
for k,v in pairs(its) do
local cc=dfhack.items.getContainedItems(v)
for _,c_item in pairs(cc) do
table.insert(contained,c_item)
end
end
for k,v in pairs(contained) do
table.insert(its,v)
end
end end
--[[while(#job.items>0) do --clear old job items --[[while(#job.items>0) do --clear old job items
job.items[#job.items-1]:delete() job.items[#job.items-1]:delete()
@ -302,8 +367,12 @@ 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
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
if (trg_job_item.quantity>0 and dfhack.job.isSuitableItem(trg_job_item, cur_item:getType(), cur_item:getSubtype()) and
dfhack.job.isSuitableMaterial(trg_job_item, cur_item:getMaterial(), cur_item:getMaterialIndex())) or settings.build_by_items then local item_suitable,msg=isSuitableItem(trg_job_item,cur_item)
--if msg then
-- print(cur_item,msg)
--end
if (trg_job_item.quantity>0 and item_suitable) or settings.build_by_items then
job.items:insert("#",{new=true,item=cur_item,role=2,job_item_idx=job_id}) job.items:insert("#",{new=true,item=cur_item,role=2,job_item_idx=job_id})
trg_job_item.quantity=trg_job_item.quantity-1 trg_job_item.quantity=trg_job_item.quantity-1
--print(string.format("item added, job_item_id=%d, item %s, quantity left=%d",job_id,tostring(cur_item),trg_job_item.quantity)) --print(string.format("item added, job_item_id=%d, item %s, quantity left=%d",job_id,tostring(cur_item),trg_job_item.quantity))
@ -312,11 +381,7 @@ function AssignJobItems(args)
end end
end end
end end
--[[print("+============+")
printall(job.items)
print("-============-")
printall(job.job_items)
print("+============+")]]--
if not settings.build_by_items then if not settings.build_by_items then
for job_id, trg_job_item in ipairs(job.job_items) do for job_id, trg_job_item in ipairs(job.job_items) do
if trg_job_item.quantity>0 then if trg_job_item.quantity>0 then
@ -352,6 +417,13 @@ function CancelJob(unit)
local c_job=unit.job.current_job local c_job=unit.job.current_job
if c_job then if c_job then
unit.job.current_job =nil --todo add real cancelation unit.job.current_job =nil --todo add real cancelation
for k,v in pairs(c_job.general_refs) do
if df.general_ref_unit_workerst:is_instance(v) then
v:delete()
c_job.general_refs:erase(k)
return
end
end
end end
end end
function ContinueJob(unit) function ContinueJob(unit)
@ -367,14 +439,29 @@ function ContinueJob(unit)
unit.path.dest:assign(c_job.pos) unit.path.dest:assign(c_job.pos)
end end
end end
function AddItemRefMason(args)
--printall(args)
args.job.job_items:insert("#",{new=true,mat_type=0,quantity=1})
return true
end
workshops={ workshops={
[df.workshop_type.Mason]={ --[=[
common={item_type=df.item_type.BOULDER,vector_id=df.job_item_vector_id.BOULDER, mat_type=0,flags2={non_economic=true,},flags3={hard=true}}, [df.workshop_type.Jewelers]={
--TODO add material.IS_GEM
[df.job_type.CutGems]={{test={isMaterialGem},item_type=df.item_type.BOULDER},
[df.job_type.EncrustWithGems]={{item_type=df.item_type.SMALLGEM},{flags1={improvable=true,finished_goods=true}},
[df.job_type.EncrustWithGems]={{item_type=df.item_type.SMALLGEM},{flags1={improvable=true,ammo=true}},
[df.job_type.EncrustWithGems]={{item_type=df.item_type.SMALLGEM},{flags1={improvable=true,furniture=true}},
}
]=]
[df.workshop_type.Fishery]={
common={quantity=1},
[df.job_type.PrepareRawFish]={{item_type=df.item_type.FISH_RAW,flags1={unrotten=true}}},
[df.job_type.ExtractFromRawFish]={{flags1={unrotten=true,extract_bearing_fish=true}},{item_type=df.item_type.FLASK,flags1={empty=true,glass=true}}},
[df.job_type.CatchLiveFish]={}, -- no items?
},
[df.workshop_type.Still]={
common={quantity=1},
[df.job_type.BrewDrink]={{flags1={distillable=true},vector_id=22},{flags1={empty=true},flags3={food_storage=true}}},
[df.job_type.ExtractFromPlants]={{item_type=df.item_type.PLANT,flags1={unrotten=true,extract_bearing_plant=true}},{item_type=df.item_type.FLASK,flags1={empty=true}}},
},
[df.workshop_type.Masons]={
common={item_type=df.item_type.BOULDER,item_subtype=-1,vector_id=df.job_item_vector_id.BOULDER, mat_type=0,mat_index=-1,quantity=1,flags2={non_economic=true},flags3={hard=true}},
[df.job_type.ConstructArmorStand]={{}}, [df.job_type.ConstructArmorStand]={{}},
[df.job_type.ConstructBlocks]={{}}, [df.job_type.ConstructBlocks]={{}},
[df.job_type.ConstructThrone]={{}}, [df.job_type.ConstructThrone]={{}},
@ -384,7 +471,7 @@ workshops={
[df.job_type.ConstructHatchCover]={{}}, [df.job_type.ConstructHatchCover]={{}},
[df.job_type.ConstructGrate]={{}}, [df.job_type.ConstructGrate]={{}},
[df.job_type.ConstructCabinet]={{}}, [df.job_type.ConstructCabinet]={{}},
[df.job_type.ConstructCofer]={{}}, [df.job_type.ConstructChest]={{}},
[df.job_type.ConstructStatue]={{}}, [df.job_type.ConstructStatue]={{}},
[df.job_type.ConstructSlab]={{}}, [df.job_type.ConstructSlab]={{}},
[df.job_type.ConstructTable]={{}}, [df.job_type.ConstructTable]={{}},
@ -392,7 +479,52 @@ workshops={
[df.job_type.ConstructQuern]={{}}, [df.job_type.ConstructQuern]={{}},
[df.job_type.ConstructMillstone]={{}}, [df.job_type.ConstructMillstone]={{}},
}, },
[df.workshop_type.Carpenters]={
common={item_type=df.item_type.WOOD,vector_id=df.job_item_vector_id.WOOD,quantity=1},
[df.job_type.MakeBarrel]={{}},
--[[ from raws
[df.job_type.MakeShield]={{}},
[df.job_type.MakeShield]={item_subtype=1,{}}, --buckler
[df.job_type.MakeWeapon]={item_subtype=23,{}}, --training spear -> from raws...
[df.job_type.MakeWeapon]={item_subtype=22,{}}, --training sword
[df.job_type.MakeWeapon]={item_subtype=21,{}}, --training axe
--]]
[df.job_type.ConstructBlocks]={{}},
[df.job_type.MakeBucket]={{}},
[df.job_type.MakeAnimalTrap]={{}},
[df.job_type.MakeCage]={{}},
[df.job_type.ConstructArmorStand]={{}},
[df.job_type.ConstructBed]={{}},
[df.job_type.ConstructThrone]={{}},
[df.job_type.ConstructCoffin]={{}},
[df.job_type.ConstructDoor]={{}},
[df.job_type.ConstructFloodgate]={{}},
[df.job_type.ConstructHatchCover]={{}},
[df.job_type.ConstructGrate]={{}},
[df.job_type.ConstructCabinet]={{}},
[df.job_type.ConstructBin]={{}},
[df.job_type.ConstructChest]={{}},
[df.job_type.ConstructStatue]={{}},
[df.job_type.ConstructSlab]={{}},
[df.job_type.ConstructTable]={{}},
[df.job_type.ConstructWeaponRack]={{}},
--[[ from raws
[df.job_type.MakeTrapComponent]={item_subtype=1,{}}, --corkscrew
[df.job_type.MakeTrapComponent]={item_subtype=2,{}}, --ball
[df.job_type.MakeTrapComponent]={item_subtype=4,{}}, --spike
[df.job_type.MakeTool]={item_subtype=16,{}}, --minecart (?? maybe from raws?)
--]]
[df.job_type.ConstructSplint]={{}},
[df.job_type.ConstructCrutch]={{}},
},
[df.workshop_type.Mechanics]={
common={quantity=1},
[df.job_type.ConstructMechanisms]={{item_type=df.item_type.BOULDER,item_subtype=-1,vector_id=df.job_item_vector_id.BOULDER, mat_type=0,mat_index=-1,quantity=1,flags2={non_economic=true},flags3={hard=true}}},
[df.job_type.ConstructTractionBench]={{item_type=df.item_type.TABLE},{item_type=df.item_type.MECHANISM},{item_type=df.item_type.CHAIN}}
},
} }
dig_modes={ dig_modes={
{"CarveFortification" ,df.job_type.CarveFortification,{IsWall,IsHardMat}}, {"CarveFortification" ,df.job_type.CarveFortification,{IsWall,IsHardMat}},
{"DetailWall" ,df.job_type.DetailWall,{IsWall,IsHardMat}}, {"DetailWall" ,df.job_type.DetailWall,{IsWall,IsHardMat}},
@ -422,9 +554,6 @@ dig_modes={
usetool=defclass(usetool,gui.Screen) usetool=defclass(usetool,gui.Screen)
function usetool:getShopMode()
return "In shop"
end
function usetool:getModeName() function usetool:getModeName()
local adv=df.global.world.units.active[0] local adv=df.global.world.units.active[0]
if adv.job.current_job then if adv.job.current_job then
@ -434,23 +563,36 @@ function usetool:getModeName()
end end
end end
function usetool:isOnWorkshop()
local adv=df.global.world.units.active[0]
local bld=dfhack.buildings.findAtTile(adv.pos)
if bld and bld:getType()==df.building_type.Workshop and bld.construction_stage==3 then
return true,bld
else
return false
end
end
function usetool:init(args) function usetool:init(args)
self:addviews{ self:addviews{
wid.Label{ wid.Label{
view_id="main_label", view_id="mainLabel",
frame = {xalign=0,yalign=0}, frame = {xalign=0,yalign=0},
text={{key=keybinds.key_prev.key},{gap=1,text=dfhack.curry(usetool.getModeName,self)},{gap=1,key=keybinds.key_next.key}} text={{key=keybinds.prevJob.key},{gap=1,text=dfhack.curry(usetool.getModeName,self)},{gap=1,key=keybinds.nextJob.key},
}
}, },
wid.Label{ wid.Label{
view_id="shop_label", view_id="shopLabel",
frame = {l=35,xalign=0,yalign=0},
visible=false, visible=false,
frame = {xalign=0,yalign=0}, text={
text={{key=keybinds.key_prev.key},{gap=1,text=dfhack.curry(usetool.getShopMode,self),pen=dfhack.pen.parse{fg=COLOR_YELLOW,bg=0}},{gap=1,key=keybinds.key_next.key}} {gap=1,key=keybinds.workshop.key,key_sep="()", text="Workshop Mode",pen=dfhack.pen.parse{fg=COLOR_YELLOW,bg=0}}}
} }
} }
end end
function usetool:onRenderBody(dc) function usetool:onRenderBody(dc)
self:shopMode(self:isOnWorkshop())
self:renderParent() self:renderParent()
end end
function usetool:onIdle() function usetool:onIdle()
@ -494,33 +636,83 @@ end
function usetool:onHelp() function usetool:onHelp()
showHelp() showHelp()
end end
function usetool:onInput(keys) function setFiltersUp(common,specific,args)
local job=args.job
for k,v in pairs(specific) do
if type(k)=="string" then
job[k]=v
end
end
for _,v in ipairs(specific) do
local filter
filter=require("utils").clone(common or {})
filter.new=true
require("utils").assign(filter,v)
--printall(filter)
job.job_items:insert("#",filter)
end
return true
end
function onWorkShopJobChosen(args,idx,choice)
args.pos=args.from_pos
args.job_type=choice.job_id
args.post_actions={AssignBuildingRef}
args.pre_actions={dfhack.curry(setFiltersUp,args.common,choice.filter),function(args)return AssignJobItems(args,true) end}
local job,msg=MakeJob(args)
if not job then
dfhack.gui.showAnnouncement(msg,5,1)
end
args.job=job
--[[for _,v in ipairs(choice.filter) do
local filter=require("utils").clone(args.common)
filter.new=true
require("utils").assign(filter,v)
--printall(filter)
job.job_items:insert("#",filter)
end--]]
--local ok,msg=AssignJobItems(args)
--print(ok,msg)
end
function usetool:openShopWindow(building)
local adv=df.global.world.units.active[0] local adv=df.global.world.units.active[0]
if keys.LEAVESCREEN then
if df.global.cursor.x~=-30000 then local shop_type=building:getSubtype()
self:sendInputToParent("LEAVESCREEN")
else local filter_pile=workshops[shop_type]
self:dismiss()
CancelJob(adv) if filter_pile then
local state={unit=adv,from_pos={x=adv.pos.x,y=adv.pos.y, z=adv.pos.z}
,screen=self,bld=building,common=filter_pile.common}
choices={}
for k,v in pairs(filter_pile) do
if k~= "common" then
table.insert(choices,{job_id=k,text=df.job_type[k]:lower(),filter=v})
end end
elseif keys[keybinds.key_next.key] then end
mode=(mode+1)%#dig_modes require("gui.dialogs").showListPrompt("Workshop job choice", "Choose what to make",COLOR_WHITE,choices,dfhack.curry(onWorkShopJobChosen,state)
elseif keys[keybinds.key_prev.key] then ,nil, nil,true)
mode=mode-1 end
if mode<0 then mode=#dig_modes-1 end end
--elseif keys.A_LOOK then function usetool:shopMode(enable,wshop)
-- self:sendInputToParent("A_LOOK") self.subviews.shopLabel.visible=enable
elseif keys[keybinds.key_continue.key] then self.in_shop=wshop
ContinueJob(adv) end
self:sendInputToParent("A_WAIT") function usetool:shopInput(keys)
else if keys[keybinds.workshop.key] then
self:openShopWindow(self.in_shop)
end
end
function usetool:fieldInput(keys)
local adv=df.global.world.units.active[0]
local cur_mode=dig_modes[(mode or 0)+1] local cur_mode=dig_modes[(mode or 0)+1]
local failed=false local failed=false
for code,_ in pairs(keys) do for code,_ in pairs(keys) do
--print(code) --print(code)
if MOVEMENT_KEYS[code] then if MOVEMENT_KEYS[code] then
local state={unit=adv,pos=moddedpos(adv.pos,MOVEMENT_KEYS[code]),dir=MOVEMENT_KEYS[code], local state={unit=adv,pos=moddedpos(adv.pos,MOVEMENT_KEYS[code]),dir=MOVEMENT_KEYS[code],
from_pos={x=adv.pos.x,y=adv.pos.y, z=adv.pos.z},post_action=cur_mode[4],pre_actions=cur_mode[5],job_type=cur_mode[2],screen=self} from_pos={x=adv.pos.x,y=adv.pos.y, z=adv.pos.z},post_actions=cur_mode[4],pre_actions=cur_mode[5],job_type=cur_mode[2],screen=self}
if code=="SELECT" then if code=="SELECT" then
if df.global.cursor.x~=-30000 then if df.global.cursor.x~=-30000 then
state.pos={x=df.global.cursor.x,y=df.global.cursor.y,z=df.global.cursor.z} state.pos={x=df.global.cursor.x,y=df.global.cursor.y,z=df.global.cursor.z}
@ -564,6 +756,34 @@ function usetool:onInput(keys)
end end
end end
end end
end
function usetool:onInput(keys)
local adv=df.global.world.units.active[0]
if keys.LEAVESCREEN then
if df.global.cursor.x~=-30000 then
self:sendInputToParent("LEAVESCREEN")
else
self:dismiss()
CancelJob(adv)
end
elseif keys[keybinds.nextJob.key] then
mode=(mode+1)%#dig_modes
elseif keys[keybinds.prevJob.key] then
mode=mode-1
if mode<0 then mode=#dig_modes-1 end
--elseif keys.A_LOOK then
-- self:sendInputToParent("A_LOOK")
elseif keys[keybinds.continue.key] then
ContinueJob(adv)
self:sendInputToParent("A_WAIT")
else
if self.in_shop then
self:shopInput(keys)
self:fieldInput(keys)
else
self:fieldInput(keys)
end
end end
end end
usetool():show() usetool():show()