dfhack/scripts/gui/advfort.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()