794 lines
28 KiB
Lua
794 lines
28 KiB
Lua
-- 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 wid=require 'gui.widgets'
|
|
local dialog=require 'gui.dialogs'
|
|
local buildings=require 'dfhack.buildings'
|
|
local bdialog=require 'gui.buildings'
|
|
|
|
local tile_attrs = df.tiletype.attrs
|
|
|
|
settings={build_by_items=false,check_inv=false,df_assign=true}
|
|
for k,v in ipairs({...}) do
|
|
if v=="-c" or v=="--cheat" then
|
|
settings.build_by_items=true
|
|
settings.df_assign=false
|
|
elseif v=="-i" or v=="--inventory" then
|
|
settings.check_inv=true
|
|
settings.df_assign=false
|
|
elseif v=="-a" or v=="--nodfassign" then
|
|
settings.df_assign=false
|
|
end
|
|
end
|
|
|
|
mode=mode or 0
|
|
|
|
|
|
function Disclaimer(tlb)
|
|
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}}}
|
|
if tlb then
|
|
for _,v in ipairs(dsc) do
|
|
table.insert(tlb,v)
|
|
end
|
|
end
|
|
return dsc
|
|
end
|
|
function showHelp()
|
|
local helptext={
|
|
"This tool allow you to perform jobs as a dwarf would in dwarf mode. When ",NEWLINE,
|
|
"cursor is available you can press ",{key="SELECT", text="select",key_sep="()"},
|
|
" to enqueue a job from",NEWLINE,"pointer location. If job is 'Build' and there is no planed construction",NEWLINE,
|
|
"at cursor this tool show possible building choices.",NEWLINE,NEWLINE,{text="Keybindings:",pen=dfhack.pen.parse{fg=COLOR_CYAN,bg=0}},NEWLINE
|
|
}
|
|
for k,v in pairs(keybinds) do
|
|
table.insert(helptext,{key=v.key,text=v.desc,key_sep=":"})
|
|
table.insert(helptext,NEWLINE)
|
|
end
|
|
table.insert(helptext,{text="CAREFULL MOVE",pen=dfhack.pen.parse{fg=COLOR_LIGHTGREEN,bg=0}})
|
|
table.insert(helptext,": use job in that direction")
|
|
table.insert(helptext,NEWLINE)
|
|
table.insert(helptext,NEWLINE)
|
|
Disclaimer(helptext)
|
|
require("gui.dialogs").showMessage("Help!?!",helptext)
|
|
end
|
|
|
|
function getLastJobLink()
|
|
local st=df.global.world.job_list
|
|
while st.next~=nil do
|
|
st=st.next
|
|
end
|
|
return st
|
|
end
|
|
function addNewJob(job)
|
|
local lastLink=getLastJobLink()
|
|
local newLink=df.job_list_link:new()
|
|
newLink.prev=lastLink
|
|
lastLink.next=newLink
|
|
newLink.item=job
|
|
job.list_link=newLink
|
|
end
|
|
function MakeJob(args)
|
|
local newJob=df.job:new()
|
|
newJob.id=df.global.job_next_id
|
|
df.global.job_next_id=df.global.job_next_id+1
|
|
--newJob.flags.special=true
|
|
newJob.job_type=args.job_type
|
|
newJob.completion_timer=-1
|
|
|
|
newJob.pos:assign(args.pos)
|
|
args.job=newJob
|
|
local failed=false
|
|
for k,v in ipairs(args.pre_actions or {}) do
|
|
local ok,msg=v(args)
|
|
if not ok then
|
|
failed=true
|
|
return false,msg
|
|
end
|
|
end
|
|
if not failed then
|
|
AssignUnitToJob(newJob,args.unit,args.from_pos)
|
|
end
|
|
for k,v in ipairs(args.post_actionss or {}) do
|
|
v(args)
|
|
end
|
|
addNewJob(newJob)
|
|
return newJob
|
|
end
|
|
|
|
function AssignUnitToJob(job,unit,unit_pos)
|
|
job.general_refs:insert("#",{new=df.general_ref_unit_workerst,unit_id=unit.id})
|
|
unit.job.current_job=job
|
|
unit_pos=unit_pos or {x=job.pos.x,y=job.pos.y,z=job.pos.z}
|
|
unit.path.dest:assign(unit_pos)
|
|
end
|
|
function SetCreatureRef(args)
|
|
local job=args.job
|
|
local pos=args.pos
|
|
for k,v in pairs(df.global.world.units.active) do
|
|
if v.pos.x==pos.x and v.pos.y==pos.y and v.pos.z==pos.z then
|
|
job.general_refs:insert("#",{new=df.general_ref_unit_cageest,unit_id=v.id})
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
function SetPatientRef(args)
|
|
local job=args.job
|
|
local pos=args.pos
|
|
for k,v in pairs(df.global.world.units.active) do
|
|
if v.pos.x==pos.x and v.pos.y==pos.y and v.pos.z==pos.z then
|
|
job.general_refs:insert("#",{new=df.general_ref_unit_patientst,unit_id=v.id})
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
function MakePredicateWieldsItem(item_skill)
|
|
local pred=function(args)
|
|
local inv=args.unit.inventory
|
|
for k,v in pairs(inv) do
|
|
if v.mode==1 and df.item_weaponst:is_instance(v.item) then
|
|
if v.item.subtype.skill_melee==item_skill and args.unit.body.weapon_bp==v.body_part_id then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
return false,"Correct tool not equiped"
|
|
end
|
|
return pred
|
|
end
|
|
|
|
function makeset(args)
|
|
local tbl={}
|
|
for k,v in pairs(args) do
|
|
tbl[v]=true
|
|
end
|
|
return tbl
|
|
end
|
|
function NotConstruct(args)
|
|
local tt=dfhack.maps.getTileType(args.pos)
|
|
if tile_attrs[tt].material~=df.tiletype_material.CONSTRUCTION and dfhack.buildings.findAtTile(args.pos)==nil then
|
|
return true
|
|
else
|
|
return false, "Can only do it on non constructions"
|
|
end
|
|
end
|
|
function IsBuilding(args)
|
|
if dfhack.buildings.findAtTile(args.pos) then
|
|
return true
|
|
end
|
|
return false, "Can only do it on buildings"
|
|
end
|
|
function IsConstruct(args)
|
|
local tt=dfhack.maps.getTileType(args.pos)
|
|
if tile_attrs[tt].material==df.tiletype_material.CONSTRUCTION then
|
|
return true
|
|
else
|
|
return false, "Can only do it on constructions"
|
|
end
|
|
end
|
|
function IsHardMaterial(args)
|
|
local tt=dfhack.maps.getTileType(args.pos)
|
|
local mat=tile_attrs[tt].material
|
|
local hard_materials={df.tiletype_material.STONE,df.tiletype_material.FEATURE,
|
|
df.tiletype_material.LAVA_STONE,df.tiletype_material.MINERAL,df.tiletype_material.FROZEN_LIQUID,}
|
|
if hard_materials[mat] then
|
|
return true
|
|
else
|
|
return false, "Can only do it on hard materials"
|
|
end
|
|
end
|
|
function IsStairs(args)
|
|
local tt=dfhack.maps.getTileType(args.pos)
|
|
local shape=tile_attrs[tt].shape
|
|
if shape==df.tiletype_shape.STAIR_UP or shape==df.tiletype_shape.STAIR_DOWN or shape==df.tiletype_shape.STAIR_UPDOWN or shape==df.tiletype_shape.RAMP then
|
|
return true
|
|
else
|
|
return false,"Can only do it on stairs/ramps"
|
|
end
|
|
end
|
|
function IsFloor(args)
|
|
local tt=dfhack.maps.getTileType(args.pos)
|
|
local shape=tile_attrs[tt].shape
|
|
if shape==df.tiletype_shape.FLOOR or shape==df.tiletype_shape.BOULDER or shape==df.tiletype_shape.PEBBLES then
|
|
return true
|
|
else
|
|
return false,"Can only do it on floors"
|
|
end
|
|
end
|
|
function IsWall(args)
|
|
local tt=dfhack.maps.getTileType(args.pos)
|
|
if tile_attrs[tt].shape==df.tiletype_shape.WALL then
|
|
return true
|
|
else
|
|
return false, "Can only do it on walls"
|
|
end
|
|
end
|
|
function IsTree(args)
|
|
local tt=dfhack.maps.getTileType(args.pos)
|
|
if tile_attrs[tt].shape==df.tiletype_shape.TREE then
|
|
return true
|
|
else
|
|
return false, "Can only do it on trees"
|
|
end
|
|
end
|
|
function IsPlant(args)
|
|
local tt=dfhack.maps.getTileType(args.pos)
|
|
if tile_attrs[tt].shape==df.tiletype_shape.SHRUB then
|
|
return true
|
|
else
|
|
return false, "Can only do it on plants"
|
|
end
|
|
end
|
|
function IsWater(args)
|
|
return true
|
|
end
|
|
|
|
function IsUnit(args)
|
|
local pos=args.pos
|
|
for k,v in pairs(df.global.world.units.active) do
|
|
if v.pos.x==pos.x and v.pos.y==pos.y and v.pos.z==pos.z then
|
|
return true
|
|
end
|
|
end
|
|
return false,"Unit must be present"
|
|
end
|
|
function itemsAtPos(pos)
|
|
local ret={}
|
|
for k,v in pairs(df.global.world.items.all) do
|
|
if v.pos.x==pos.x and v.pos.y==pos.y and v.pos.z==pos.z and v.flags.on_ground then
|
|
table.insert(ret,v)
|
|
end
|
|
end
|
|
return ret
|
|
end
|
|
function AssignBuildingRef(args)
|
|
local bld=dfhack.buildings.findAtTile(args.pos)
|
|
args.job.general_refs:insert("#",{new=df.general_ref_building_holderst,building_id=bld.id})
|
|
bld.jobs:insert("#",args.job)
|
|
end
|
|
|
|
function BuildingChosen(inp_args,type_id,subtype_id,custom_id)
|
|
local args={}
|
|
args.type=type_id
|
|
args.subtype=subtype_id
|
|
args.custom=custom_id
|
|
args.pos=inp_args.pos
|
|
--if settings.build_by_items then
|
|
-- args.items=itemsAtPos(inp_args.from_pos)
|
|
--end
|
|
--printall(args.items)
|
|
buildings.constructBuilding(args)
|
|
end
|
|
|
|
|
|
function RemoveBuilding(args)
|
|
local bld=dfhack.buildings.findAtTile(args.pos)
|
|
if bld~=nil then
|
|
bld:queueDestroy()
|
|
for k,v in ipairs(bld.jobs) do
|
|
if v.job_type==df.job_type.DestroyBuilding then
|
|
AssignUnitToJob(v,args.unit,args.from_pos)
|
|
return true
|
|
end
|
|
end
|
|
return false,"Building removal job failed to be created"
|
|
else
|
|
return false,"No building to remove"
|
|
end
|
|
end
|
|
function isSuitableItem(job_item,item)
|
|
|
|
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
|
|
end
|
|
function AssignJobItems(args,is_workshop_job)
|
|
if settings.df_assign and not is_workshop_job then
|
|
return true
|
|
end
|
|
--print("Assign")
|
|
--printall(args)
|
|
local job=args.job
|
|
local its=itemsAtPos(args.from_pos)
|
|
if settings.check_inv then
|
|
for k,v in pairs(args.unit.inventory) do
|
|
table.insert(its,v.item)
|
|
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
|
|
--[[while(#job.items>0) do --clear old job items
|
|
job.items[#job.items-1]:delete()
|
|
job.items:erase(#job.items-1)
|
|
end]]
|
|
local used_item_id={}
|
|
for job_id, trg_job_item in ipairs(job.job_items) do
|
|
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)
|
|
--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})
|
|
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))
|
|
used_item_id[cur_item.id]=true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if not settings.build_by_items then
|
|
for job_id, trg_job_item in ipairs(job.job_items) do
|
|
if trg_job_item.quantity>0 then
|
|
return false, "Not enough items for this job"
|
|
end
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
function AssignJobToBuild(args)
|
|
local bld=dfhack.buildings.findAtTile(args.pos)
|
|
args.job_type=df.job_type.ConstructBuilding
|
|
if bld~=nil then
|
|
if #bld.jobs>0 then
|
|
args.job=bld.jobs[0]
|
|
local ok,msg=AssignJobItems(args)
|
|
if not ok then
|
|
return false,msg
|
|
else
|
|
AssignUnitToJob(bld.jobs[0],args.unit,args.from_pos) --todo check if correct job type
|
|
end
|
|
else
|
|
args.pre_actions={AssignJobItems}
|
|
local ok,msg=MakeJob(args)
|
|
return ok,msg
|
|
end
|
|
else
|
|
bdialog.BuildingDialog{on_select=dfhack.curry(BuildingChosen,args),hide_none=true}:show()
|
|
end
|
|
return true
|
|
end
|
|
function CancelJob(unit)
|
|
local c_job=unit.job.current_job
|
|
if c_job then
|
|
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
|
|
function ContinueJob(unit)
|
|
local c_job=unit.job.current_job
|
|
if c_job then
|
|
c_job.flags.suspend=false
|
|
for k,v in pairs(c_job.items) do
|
|
if v.is_fetching==1 then
|
|
unit.path.dest:assign(v.item.pos)
|
|
return
|
|
end
|
|
end
|
|
unit.path.dest:assign(c_job.pos)
|
|
end
|
|
end
|
|
workshops={
|
|
--[=[
|
|
[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,flags3={hard=true}},--flags2={non_economic=true},
|
|
[df.job_type.ConstructArmorStand]={{}},
|
|
[df.job_type.ConstructBlocks]={{}},
|
|
[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.ConstructChest]={{}},
|
|
[df.job_type.ConstructStatue]={{}},
|
|
[df.job_type.ConstructSlab]={{}},
|
|
[df.job_type.ConstructTable]={{}},
|
|
[df.job_type.ConstructWeaponRack]={{}},
|
|
[df.job_type.ConstructQuern]={{}},
|
|
[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,
|
|
flags3={hard=true}}}, -- flags2={non_economic=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={
|
|
{"CarveFortification" ,df.job_type.CarveFortification,{IsWall,IsHardMat}},
|
|
{"DetailWall" ,df.job_type.DetailWall,{IsWall,IsHardMat}},
|
|
{"DetailFloor" ,df.job_type.DetailFloor,{IsFloor,IsHardMat}},
|
|
--{"CarveTrack" ,df.job_type.CarveTrack}, -- does not work??
|
|
{"Dig" ,df.job_type.Dig,{MakePredicateWieldsItem(df.job_skill.MINING),IsWall}},
|
|
{"CarveUpwardStaircase" ,df.job_type.CarveUpwardStaircase,{MakePredicateWieldsItem(df.job_skill.MINING),IsWall}},
|
|
{"CarveDownwardStaircase",df.job_type.CarveDownwardStaircase,{MakePredicateWieldsItem(df.job_skill.MINING)}},
|
|
{"CarveUpDownStaircase" ,df.job_type.CarveUpDownStaircase,{MakePredicateWieldsItem(df.job_skill.MINING)}},
|
|
{"CarveRamp" ,df.job_type.CarveRamp,{MakePredicateWieldsItem(df.job_skill.MINING),IsWall}},
|
|
{"DigChannel" ,df.job_type.DigChannel,{MakePredicateWieldsItem(df.job_skill.MINING)}},
|
|
{"FellTree" ,df.job_type.FellTree,{MakePredicateWieldsItem(df.job_skill.AXE),IsTree}},
|
|
{"Fish" ,df.job_type.Fish,{IsWater}},
|
|
--{"Diagnose Patient" ,df.job_type.DiagnosePatient,{IsUnit},{SetPatientRef}},
|
|
--{"Surgery" ,df.job_type.Surgery,{IsUnit},{SetPatientRef}},
|
|
--{"TameAnimal" ,df.job_type.TameAnimal,{IsUnit},{SetCreatureRef}},
|
|
{"GatherPlants" ,df.job_type.GatherPlants,{IsPlant}},
|
|
{"RemoveConstruction" ,df.job_type.RemoveConstruction,{IsConstruct}},
|
|
{"RemoveBuilding" ,RemoveBuilding,{IsBuilding}},
|
|
--{"HandleLargeCreature" ,df.job_type.HandleLargeCreature,{isUnit},{SetCreatureRef}},
|
|
{"Build" ,AssignJobToBuild},
|
|
--{"ConstructBlocks" ,df.job_type.ConstructBlocks,{},{AssignBuildingRef},{AddItemRefMason,AssignJobItems}},
|
|
{"RemoveStairs" ,df.job_type.RemoveStairs,{IsStairs,NotConstruct}},
|
|
--{"LoadCageTrap" ,df.job_type.LoadCageTrap,{},{SetBuildingRef},{AssignJobItems}},
|
|
|
|
}
|
|
|
|
|
|
usetool=defclass(usetool,gui.Screen)
|
|
usetool.focus_path = 'advfort'
|
|
function usetool:getModeName()
|
|
local adv=df.global.world.units.active[0]
|
|
if adv.job.current_job then
|
|
return string.format("%s working(%d) ",(dig_modes[(mode or 0)+1][1] or ""),adv.job.current_job.completion_timer)
|
|
else
|
|
return dig_modes[(mode or 0)+1][1] or " "
|
|
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)
|
|
self:addviews{
|
|
wid.Label{
|
|
view_id="mainLabel",
|
|
frame = {xalign=0,yalign=0},
|
|
text={{key=keybinds.prevJob.key},{gap=1,text=dfhack.curry(usetool.getModeName,self)},{gap=1,key=keybinds.nextJob.key},
|
|
}
|
|
},
|
|
|
|
|
|
wid.Label{
|
|
view_id="shopLabel",
|
|
frame = {l=35,xalign=0,yalign=0},
|
|
visible=false,
|
|
text={
|
|
{gap=1,key=keybinds.workshop.key,key_sep="()", text="Workshop Mode",pen=dfhack.pen.parse{fg=COLOR_YELLOW,bg=0}}}
|
|
}
|
|
}
|
|
end
|
|
function usetool:onRenderBody(dc)
|
|
self:shopMode(self:isOnWorkshop())
|
|
self:renderParent()
|
|
end
|
|
function usetool:onIdle()
|
|
|
|
self._native.parent:logic()
|
|
end
|
|
MOVEMENT_KEYS = {
|
|
A_CARE_MOVE_N = { 0, -1, 0 }, A_CARE_MOVE_S = { 0, 1, 0 },
|
|
A_CARE_MOVE_W = { -1, 0, 0 }, A_CARE_MOVE_E = { 1, 0, 0 },
|
|
A_CARE_MOVE_NW = { -1, -1, 0 }, A_CARE_MOVE_NE = { 1, -1, 0 },
|
|
A_CARE_MOVE_SW = { -1, 1, 0 }, A_CARE_MOVE_SE = { 1, 1, 0 },
|
|
--[[A_MOVE_N = { 0, -1, 0 }, A_MOVE_S = { 0, 1, 0 },
|
|
A_MOVE_W = { -1, 0, 0 }, A_MOVE_E = { 1, 0, 0 },
|
|
A_MOVE_NW = { -1, -1, 0 }, A_MOVE_NE = { 1, -1, 0 },
|
|
A_MOVE_SW = { -1, 1, 0 }, A_MOVE_SE = { 1, 1, 0 },--]]
|
|
A_CUSTOM_CTRL_D = { 0, 0, -1 },
|
|
A_CUSTOM_CTRL_E = { 0, 0, 1 },
|
|
CURSOR_UP_Z_AUX = { 0, 0, 1 }, CURSOR_DOWN_Z_AUX = { 0, 0, -1 },
|
|
A_MOVE_SAME_SQUARE={0,0,0},
|
|
SELECT={0,0,0},
|
|
}
|
|
ALLOWED_KEYS={
|
|
A_MOVE_N=true,A_MOVE_S=true,A_MOVE_W=true,A_MOVE_E=true,A_MOVE_NW=true,
|
|
A_MOVE_NE=true,A_MOVE_SW=true,A_MOVE_SE=true,A_STANCE=true,SELECT=true,A_MOVE_DOWN_AUX=true,
|
|
A_MOVE_UP_AUX=true,A_LOOK=true,CURSOR_DOWN=true,CURSOR_UP=true,CURSOR_LEFT=true,CURSOR_RIGHT=true,
|
|
CURSOR_UPLEFT=true,CURSOR_UPRIGHT=true,CURSOR_DOWNLEFT=true,CURSOR_DOWNRIGHT=true,A_CLEAR_ANNOUNCEMENTS=true,
|
|
CURSOR_UP_Z=true,CURSOR_DOWN_Z=true,
|
|
}
|
|
function moddedpos(pos,delta)
|
|
return {x=pos.x+delta[1],y=pos.y+delta[2],z=pos.z+delta[3]}
|
|
end
|
|
function usetool:onDismiss()
|
|
local adv=df.global.world.units.active[0]
|
|
--TODO: cancel job
|
|
--[[if adv and adv.job.current_job then
|
|
local cj=adv.job.current_job
|
|
adv.jobs.current_job=nil
|
|
cj:delete()
|
|
end]]
|
|
end
|
|
function usetool:onHelp()
|
|
showHelp()
|
|
end
|
|
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 shop_type=building:getSubtype()
|
|
|
|
local filter_pile=workshops[shop_type]
|
|
|
|
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
|
|
require("gui.dialogs").showListPrompt("Workshop job choice", "Choose what to make",COLOR_WHITE,choices,dfhack.curry(onWorkShopJobChosen,state)
|
|
,nil, nil,true)
|
|
end
|
|
end
|
|
function usetool:shopMode(enable,wshop)
|
|
self.subviews.shopLabel.visible=enable
|
|
self.in_shop=wshop
|
|
end
|
|
function usetool:shopInput(keys)
|
|
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 failed=false
|
|
for code,_ in pairs(keys) do
|
|
--print(code)
|
|
if MOVEMENT_KEYS[code] then
|
|
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_actions=cur_mode[4],pre_actions=cur_mode[5],job_type=cur_mode[2],screen=self}
|
|
if code=="SELECT" 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}
|
|
else
|
|
break
|
|
end
|
|
end
|
|
|
|
for _,p in pairs(cur_mode[3] or {}) do
|
|
local ok,msg=p(state)
|
|
if ok==false then
|
|
dfhack.gui.showAnnouncement(msg,5,1)
|
|
failed=true
|
|
end
|
|
end
|
|
|
|
if not failed then
|
|
local ok,msg
|
|
if type(cur_mode[2])=="function" then
|
|
ok,msg=cur_mode[2](state)
|
|
else
|
|
ok,msg=MakeJob(state)
|
|
--(adv,moddedpos(adv.pos,MOVEMENT_KEYS[code]),cur_mode[2],adv.pos,cur_mode[4])
|
|
|
|
end
|
|
|
|
if code=="SELECT" then
|
|
self:sendInputToParent("LEAVESCREEN")
|
|
end
|
|
if ok then
|
|
self:sendInputToParent("A_WAIT")
|
|
else
|
|
dfhack.gui.showAnnouncement(msg,5,1)
|
|
end
|
|
end
|
|
return code
|
|
end
|
|
if code~="_STRING" and code~="_MOUSE_L" and code~="_MOUSE_R" then
|
|
if ALLOWED_KEYS[code] then
|
|
self:sendInputToParent(code)
|
|
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
|
|
if not (dfhack.gui.getCurFocus()=="dungeonmode/Look" or dfhack.gui.getCurFocus()=="dungeonmode/Default") then
|
|
qerror("This script requires an adventurer mode with (l)ook or default mode.")
|
|
end
|
|
usetool():show() |