Last active
December 15, 2015 07:49
-
-
Save warmist/5226790 to your computer and use it in GitHub Desktop.
Advfort with workshop filter and filters by race.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- allows to do jobs in adv. mode. | |
--[==[ | |
version: 0.002 | |
changelog: | |
*0.002 | |
- kind-of fixed the item problem... now they get teleported (if teleport_items=true which should be default for adventurer) | |
- gather plants still not working... Other jobs seem to work. | |
- added new-and-improved waiting. Interestingly it could be improved to be interuptable. | |
--]==] | |
--keybinding, change to your hearts content. Only the key part. | |
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 building menu"}, | |
} | |
-- building filters | |
build_filter={ | |
forbid_all=false, --this forbits all except the "allow" | |
allow={"MetalSmithsForge"}, --ignored if forbit_all=false | |
forbid={} --ignored if forbit_all==true | |
} | |
build_filter.HUMANish={ | |
forbid_all=true, | |
allow={"Masons"}, | |
forbid={} | |
} | |
--[[ FIXME: maybe let player select which to disable?]] | |
for k,v in ipairs(df.global.ui.economic_stone) do df.global.ui.economic_stone[k]=0 end | |
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 workshopJobs=require 'dfhack.workshops' | |
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} | |
function hasValue(tbl,val) | |
for k,v in pairs(tbl) do | |
if v==val then | |
return true | |
end | |
end | |
return false | |
end | |
function reverseRaceLookup(id) | |
return df.global.world.raws.creatures.all[id].creature_id | |
end | |
function deon_filter(name,type_id,subtype_id,custom_id, parent) | |
--print(name) | |
local adv=df.global.world.units.active[0] | |
local race_filter=build_filter[reverseRaceLookup(adv.race)] | |
if race_filter then | |
if race_filter.forbid_all then | |
return hasValue(race_filter.allow,name) | |
else | |
return not hasValue(race_filter.forbid,name) | |
end | |
else | |
if build_filter.forbid_all then | |
return hasValue(build_filter.allow,name) | |
else | |
return not hasValue(build_filter.forbid,name) | |
end | |
end | |
end | |
local mode_name | |
for k,v in ipairs({...}) do --setting parsing | |
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 | |
else | |
mode_name=v | |
end | |
end | |
mode=mode or 0 | |
last_building=last_building or {} | |
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) | |
dialog.showMessage("Help!?!",helptext) | |
end | |
--[[ Util functions ]]-- | |
function advGlobalPos() | |
local map=df.global.world.map | |
local wd=df.global.world.world_data | |
local adv=df.global.world.units.active[0] | |
--wd.adv_region_x*16+wd.adv_emb_x,wd.adv_region_y*16+wd.adv_emb_y | |
--return wd.adv_region_x*16+wd.adv_emb_x,wd.adv_region_y*16+wd.adv_emb_y | |
--return wd.adv_region_x*16+wd.adv_emb_x+adv.pos.x/16,wd.adv_region_y*16+wd.adv_emb_y+adv.pos.y/16 | |
--print(map.region_x,map.region_y,adv.pos.x,adv.pos.y) | |
--print(map.region_x+adv.pos.x/48, map.region_y+adv.pos.y/48,wd.adv_region_x*16+wd.adv_emb_x,wd.adv_region_y*16+wd.adv_emb_y) | |
return math.floor(map.region_x+adv.pos.x/48), math.floor(map.region_y+adv.pos.y/48) | |
end | |
function inSite() | |
local tx,ty=advGlobalPos() | |
--print(tx,ty) | |
for k,v in pairs(df.global.world.world_data.sites) do | |
local tp={v.pos.x,v.pos.y} | |
if tx>=tp[1]*16+v.rgn_min_x and tx<=tp[1]*16+v.rgn_max_x and | |
ty>=tp[2]*16+v.rgn_min_y and ty<=tp[2]*16+v.rgn_max_y then | |
--print(k) | |
return v | |
end | |
end | |
end | |
--[[ low level job management ]]-- | |
function findAction(unit,ltype) | |
ltype=ltype or df.unit_action_type.None | |
for i,v in ipairs(unit.actions) do | |
if v.type==ltype then | |
return v | |
end | |
end | |
end | |
function add_action(unit,action_data) | |
local action=findAction(unit) --find empty action | |
if action then | |
action:assign(action_data) | |
action.id=unit.next_action_id | |
unit.next_action_id=unit.next_action_id+1 | |
else | |
local tbl=copyall(action_data) | |
tbl.new=true | |
tbl.id=unit.next_action_id | |
unit.actions:insert("#",tbl) | |
unit.next_action_id=unit.next_action_id+1 | |
end | |
end | |
function addJobAction(job,unit) --what about job2? | |
if job==nil then | |
error("invalid job") | |
end | |
if findAction(unit,df.unit_action_type.Job) or findAction(unit,df.unit_action_type.Job2) then | |
print("Already has job action") | |
return | |
end | |
local action=findAction(unit) | |
local pos=copyall(unit.pos) | |
--local pos=copyall(job.pos) | |
unit.path.dest:assign(pos) | |
--job | |
local data={type=df.unit_action_type.Job,data={job={x=pos.x,y=pos.y,z=pos.z,timer=10}}} | |
--job2: | |
--local data={type=df.unit_action_type.Job2,data={job2={timer=10}}} | |
add_action(unit,data) | |
--add_action(unit,{type=df.unit_action_type.Unsteady,data={unsteady={timer=5}}}) | |
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) | |
--newJob.pos:assign(args.unit.pos) | |
args.job=newJob | |
local failed | |
for k,v in ipairs(args.pre_actions or {}) do | |
local ok,msg=v(args) | |
if not ok then | |
failed=msg | |
break | |
end | |
end | |
if failed==nil then | |
AssignUnitToJob(newJob,args.unit,args.from_pos) | |
for k,v in ipairs(args.post_actions or {}) do | |
local ok,msg=v(args) | |
if not ok then | |
failed=msg | |
break | |
end | |
end | |
if failed then | |
UnassignJob(newJob,args.unit) | |
end | |
end | |
if failed==nil then | |
dfhack.job.linkIntoWorld(newJob,true) | |
addJobAction(newJob,args.unit) | |
return newJob | |
else | |
newJob:delete() | |
return false,failed | |
end | |
end | |
function UnassignJob(job,unit,unit_pos) | |
unit.job.current_job=nil | |
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) | |
return true | |
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 SetWebRef(args) | |
local pos=args.pos | |
for k,v in pairs(df.global.world.items.other.ANY_WEBS) 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_item,item_id=v.id}) | |
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 SetCarveDir(args) | |
local job=args.job | |
local pos=args.pos | |
local from_pos=args.from_pos | |
local dirs={up=18,down=19,right=20,left=21} | |
if pos.x>from_pos.x then | |
job.item_category[dirs.right]=true | |
elseif pos.x<from_pos.x then | |
job.item_category[dirs.left]=true | |
elseif pos.y>from_pos.y then | |
job.item_category[dirs.up]=true | |
elseif pos.y<from_pos.y then | |
job.item_category[dirs.down]=true | |
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 v.item:getMeleeSkill()==item_skill and args.unit.body.weapon_bp==v.body_part_id then | |
return true | |
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 NoConstructedBuilding(args) | |
local bld=dfhack.buildings.findAtTile(args.pos) | |
if bld and bld.construction_stage==3 then | |
return false, "Can only do it on clear area or non-finished buildings" | |
end | |
return true | |
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 SameSquare(args) | |
local pos1=args.pos | |
local pos2=args.from_pos | |
if pos1.x==pos2.x and pos1.y==pos2.y and pos1.z==pos2.z then | |
return true | |
else | |
return false, "Can only do it on same square" | |
end | |
end | |
function IsHardMaterial(args) | |
local tt=dfhack.maps.getTileType(args.pos) | |
local mat=tile_attrs[tt].material | |
local hard_materials=makeset{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].material==df.tiletype_material.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,tbl) | |
local ret=tbl or {} | |
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=args.building or 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) | |
args.building=args.building or bld | |
return true | |
end | |
function chooseBuildingWidthHeightDir(args) --TODO nicer selection dialog | |
local btype=df.building_type | |
local area=makeset{"w","h"} | |
local all=makeset{"w","h","d"} | |
local needs={[btype.FarmPlot]=area,[btype.Bridge]=all, | |
[btype.RoadDirt]=area,[btype.RoadPaved]=area,[btype.ScrewPump]=makeset{"d"}, | |
[btype.AxleHorizontal]=makeset{"w","h"},[btype.WaterWheel]=makeset{"d"},[btype.Rollers]=makeset{"d"}} | |
local myneeds=needs[args.type] | |
if myneeds==nil then return end | |
if args.width==nil and myneeds.w then | |
--args.width=3 | |
dialog.showInputPrompt("Building size:", "Input building width:", nil, "1", | |
function(txt) args.width=tonumber(txt);BuildingChosen(args) end) | |
return true | |
end | |
if args.height==nil and myneeds.h then | |
--args.height=4 | |
dialog.showInputPrompt("Building size:", "Input building height:", nil, "1", | |
function(txt) args.height=tonumber(txt);BuildingChosen(args) end) | |
return true | |
end | |
if args.direction==nil and myneeds.d then | |
--args.direction=0--? | |
dialog.showInputPrompt("Building size:", "Input building direction:", nil, "0", | |
function(txt) args.direction=tonumber(txt);BuildingChosen(args) end) | |
return true | |
end | |
return false | |
--width = ..., height = ..., direction = ... | |
end | |
function BuildingChosen(inp_args,type_id,subtype_id,custom_id) | |
local args=inp_args or {} | |
args.type=type_id or args.type | |
args.subtype=subtype_id or args.subtype | |
args.custom=custom_id or args.custom_id | |
if inp_args then | |
args.pos=inp_args.pos or args.pos | |
end | |
last_building.type=args.type | |
last_building.subtype=args.subtype | |
last_building.custom=args.custom | |
if chooseBuildingWidthHeightDir(args) then | |
return | |
end | |
--if settings.build_by_items then | |
-- args.items=itemsAtPos(inp_args.from_pos) | |
--end | |
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) | |
--todo butcher test | |
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 | |
if job_item.flags1.sand_bearing and not item:isSandBearing() then | |
return false,"not sand bearing" | |
end | |
if job_item.flags1.butcherable and not (item:getType()== df.item_type.CORPSE or item:getType()==df.item_type.CORPSEPIECE) then | |
return false,"not butcherable" | |
end | |
local matinfo=dfhack.matinfo.decode(item) | |
--print(matinfo:getCraftClass()) | |
--print("Matching ",item," vs ",job_item) | |
if not matinfo:matches(job_item) then | |
--[[ | |
local true_flags={} | |
for k,v in pairs(job_item.flags1) do | |
if v then | |
table.insert(true_flags,k) | |
end | |
end | |
for k,v in pairs(job_item.flags2) do | |
if v then | |
table.insert(true_flags,k) | |
end | |
end | |
for k,v in pairs(job_item.flags3) do | |
if v then | |
table.insert(true_flags,k) | |
end | |
end | |
for k,v in pairs(true_flags) do | |
print(v) | |
end | |
--]] | |
return false,"matinfo" | |
end | |
-- some bonus checks: | |
if job_item.flags2.building_material and not item:isBuildMat() then | |
return false,"non-build mat" | |
end | |
-- ***************** | |
--print("--Matched") | |
--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 | |
local ok=false | |
for k,v in pairs(matinfo.material.reaction_product.id) do | |
if v.value==job_item.has_material_reaction_product then | |
ok=true | |
break | |
end | |
end | |
if not ok then | |
return false, "no material reaction product" | |
end | |
end | |
if job_item.reaction_class~="" then | |
local ok=false | |
for k,v in pairs(matinfo.material.reaction_class) do | |
if v.value==job_item.reaction_class then | |
ok=true | |
break | |
end | |
end | |
if not ok then | |
return false, "no material reaction class" | |
end | |
end | |
return true | |
end | |
function getItemsUncollected(job) | |
local ret={} | |
for id,jitem in pairs(job.items) do | |
local x,y,z=dfhack.items.getPosition(jitem.item) | |
if x~=job.pos.x or y~=job.pos.y or z~=job.pos.z then | |
table.insert(ret,jitem) | |
end | |
end | |
return ret | |
end | |
function AddItem(tbl,item,recurse,skip_add) | |
if not skip_add then | |
table.insert(tbl,item) | |
end | |
if recurse then | |
local subitems=dfhack.items.getContainedItems(item) | |
if subitems~=nil then | |
for k,v in pairs(subitems) do | |
AddItem(tbl,v,recurse) | |
end | |
end | |
end | |
end | |
function EnumItems(args) | |
local ret=args.table or {} | |
if args.all then | |
for k,v in pairs(df.global.world.items.all) do | |
if v.flags.on_ground then | |
AddItem(ret,v,args.deep) | |
end | |
end | |
elseif args.pos~=nil then | |
for k,v in pairs(df.global.world.items.all) do | |
if v.pos.x==args.pos.x and v.pos.y==args.pos.y and v.pos.z==args.pos.z and v.flags.on_ground then | |
AddItem(ret,v,args.deep) | |
end | |
end | |
end | |
if args.unit~=nil then | |
for k,v in pairs(args.unit.inventory) do | |
if args.inv[v.mode] then | |
AddItem(ret,v.item,args.deep) | |
elseif args.deep then | |
AddItem(ret,v.item,args.deep,true) | |
end | |
end | |
end | |
return ret | |
end | |
function putItemsInBuilding(building,job_item_refs) | |
for k,v in ipairs(job_item_refs) do | |
--local pos=dfhack.items.getPosition(v) | |
if not dfhack.items.moveToBuilding(v.item,building,0) then | |
print("Could not put item:",k,v.item) | |
end | |
v.is_fetching=0 | |
end | |
end | |
function AssignJobItems(args) | |
if settings.df_assign then --use df default logic and hope that it would work | |
return true | |
end | |
-- first find items that you want to use for the job | |
local job=args.job | |
local its | |
if settings.check_inv then | |
its=EnumItems{pos=args.from_pos,unit=args.unit, | |
inv={[df.unit_inventory_item.T_mode.Hauled]=settings.use_worn,[df.unit_inventory_item.T_mode.Worn]=settings.use_worn, | |
[df.unit_inventory_item.T_mode.Weapon]=settings.use_worn,},deep=true} | |
else | |
its=EnumItems{pos=args.from_pos} | |
end | |
--[[ job item editor... | |
jobitemEditor{job=args.job,items=its}:show() | |
local ok=job.flags.working or job.flags.fetching | |
if not ok then | |
return ok, "Stuff" | |
else | |
return ok | |
end | |
--]] | |
-- [=[ | |
--[[while(#job.items>0) do --clear old job items | |
job.items[#job.items-1]:delete() | |
job.items:erase(#job.items-1) | |
end]] | |
printall(its) | |
local item_counts={} | |
for job_id, trg_job_item in ipairs(job.job_items) do | |
item_counts[job_id]=trg_job_item.quantity | |
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 (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 | |
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 | |
return false, "Not enough items for this job" | |
end | |
end | |
end | |
if settings.teleport_items then | |
putItemsInBuilding(args.building,job.items) | |
end | |
local uncollected = getItemsUncollected(job) | |
if #uncollected == 0 then | |
job.flags.working=true | |
else | |
job.flags.fetching=true | |
uncollected[1].is_fetching=1 | |
end | |
--todo set working for workshops if items are present, else set fetching (and at least one item to is_fetching=1) | |
--job.flags.working=true | |
return true | |
--]=] | |
end | |
function CheckAndFinishBuilding(args,bld) | |
args.building=args.building or bld | |
for idx,job in pairs(bld.jobs) do | |
if job.job_type==df.job_type.ConstructBuilding then | |
args.job=job | |
break | |
end | |
end | |
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) | |
end | |
else | |
local t={items=buildings.getFiltersByType({},bld:getType(),bld:getSubtype(),bld:getCustomType())} | |
args.pre_actions={dfhack.curry(setFiltersUp,t),AssignJobItems,AssignBuildingRef} | |
local ok,msg=makeJob(args) | |
return ok,msg | |
end | |
end | |
function AssignJobToBuild(args) | |
local bld=args.building or dfhack.buildings.findAtTile(args.pos) | |
args.building=bld | |
args.job_type=df.job_type.ConstructBuilding | |
if bld~=nil then | |
CheckAndFinishBuilding(args,bld) | |
else | |
bdialog.BuildingDialog{on_select=dfhack.curry(BuildingChosen,args),hide_none=true,building_filter=deon_filter}:show() | |
end | |
return true | |
end | |
function BuildLast(args) | |
local bld=dfhack.buildings.findAtTile(args.pos) | |
args.job_type=df.job_type.ConstructBuilding | |
if bld~=nil then | |
CheckAndFinishBuilding(args,bld) | |
else | |
--bdialog.BuildingDialog{on_select=dfhack.curry(BuildingChosen,args),hide_none=true}:show() | |
if last_building and last_building.type then | |
BuildingChosen(args,last_building.type,last_building.subtype,last_building.custom) | |
end | |
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 | |
--no job to continue | |
if not c_job then return end | |
--reset suspends... | |
c_job.flags.suspend=false | |
for k,v in pairs(c_job.items) do --try fetching missing items | |
if v.is_fetching==1 then | |
unit.path.dest:assign(v.item.pos) | |
return | |
end | |
end | |
--unit.path.dest:assign(c_job.pos) -- FIXME: job pos is not always the target pos!! | |
addJobAction(c_job,unit) | |
end | |
actions={ | |
{"CarveFortification" ,df.job_type.CarveFortification,{IsWall,IsHardMaterial}}, | |
{"DetailWall" ,df.job_type.DetailWall,{IsWall,IsHardMaterial}}, | |
{"DetailFloor" ,df.job_type.DetailFloor,{IsFloor,IsHardMaterial,SameSquare}}, | |
{"CarveTrack" ,df.job_type.CarveTrack,{IsFloor,IsHardMaterial} | |
,{SetCarveDir}}, | |
{"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,SameSquare}}, | |
{"RemoveConstruction" ,df.job_type.RemoveConstruction,{IsConstruct}}, | |
{"RemoveBuilding" ,RemoveBuilding,{IsBuilding}}, | |
{"RemoveStairs" ,df.job_type.RemoveStairs,{IsStairs,NotConstruct}}, | |
--{"HandleLargeCreature" ,df.job_type.HandleLargeCreature,{isUnit},{SetCreatureRef}}, | |
{"Build" ,AssignJobToBuild,{NoConstructedBuilding}}, | |
{"BuildLast" ,BuildLast,{NoConstructedBuilding}}, | |
{"Clean" ,df.job_type.Clean,{}}, | |
{"GatherWebs" ,df.job_type.CollectWebs,{--[[HasWeb]]},{SetWebRef}}, | |
} | |
for id,action in pairs(actions) do | |
if action[1]==mode_name then | |
mode=id-1 | |
break | |
end | |
end | |
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) ",(actions[(mode or 0)+1][1] or ""),adv.job.current_job.completion_timer) | |
else | |
return actions[(mode or 0)+1][1] or " " | |
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=self:callback("getModeName")},{gap=1,key=keybinds.nextJob.key}, | |
} | |
}, | |
wid.Label{ | |
view_id="shopLabel", | |
frame = {l=35,xalign=0,yalign=0}, | |
visible=false, | |
text={ | |
{id="text1",gap=1,key=keybinds.workshop.key,key_sep="()", text="Workshop menu",pen=dfhack.pen.parse{fg=COLOR_YELLOW,bg=0}}} | |
}, | |
wid.Label{ | |
view_id="siteLabel", | |
frame = {t=1,xalign=-1,yalign=0}, | |
visible=false, | |
text={ | |
{id="text1", text="Site:"},{id="site", text="name"} | |
} | |
} | |
} | |
local labors=df.global.world.units.active[0].status.labors | |
for i,v in ipairs(labors) do | |
labors[i]=true | |
end | |
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:onHelp() | |
showHelp() | |
end | |
function setFiltersUp(specific,args) | |
local job=args.job | |
if specific.job_fields~=nil then | |
job:assign(specific.job_fields) | |
end | |
--printall(specific) | |
for _,v in ipairs(specific.items) do | |
--printall(v) | |
local filter=v | |
filter.new=true | |
job.job_items:insert("#",filter) | |
end | |
return true | |
end | |
function onWorkShopJobChosen(args,idx,choice) | |
args.pos=args.from_pos | |
args.building=args.building or dfhack.buildings.findAtTile(args.pos) | |
args.job_type=choice.job_id | |
args.post_actions={AssignBuildingRef} | |
args.pre_actions={dfhack.curry(setFiltersUp,choice.filter),AssignJobItems} | |
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 siegeWeaponActionChosen(building,actionid) | |
local args | |
if actionid==1 then | |
building.facing=(building.facing+1)%4 | |
elseif actionid==2 then | |
local action=df.job_type.LoadBallista | |
if building:getSubtype()==df.siegeengine_type.Catapult then | |
action=df.job_type.LoadCatapult | |
end | |
args={} | |
args.job_type=action | |
args.unit=df.global.world.units.active[0] | |
local from_pos={x=args.unit.pos.x,y=args.unit.pos.y, z=args.unit.pos.z} | |
args.from_pos=from_pos | |
args.pos=from_pos | |
args.pre_actions={dfhack.curry(setFiltersUp,{items={{}}})} | |
--issue a job... | |
elseif actionid==3 then | |
local action=df.job_type.FireBallista | |
if building:getSubtype()==df.siegeengine_type.Catapult then | |
action=df.job_type.FireCatapult | |
end | |
args={} | |
args.job_type=action | |
args.unit=df.global.world.units.active[0] | |
local from_pos={x=args.unit.pos.x,y=args.unit.pos.y, z=args.unit.pos.z} | |
args.from_pos=from_pos | |
args.pos=from_pos | |
--another job? | |
end | |
if args~=nil then | |
args.post_actions={AssignBuildingRef} | |
local ok,msg=makeJob(args) | |
if not ok then | |
dfhack.gui.showAnnouncement(msg,5,1) | |
end | |
end | |
end | |
function putItemToBuilding(building,item) | |
if building:getType()==df.building_type.Table then | |
dfhack.items.moveToBuilding(item,building,0) | |
else | |
local container=building.contained_items[0].item --todo maybe iterate over all, add if usemode==2? | |
dfhack.items.moveToContainer(item,container) | |
end | |
end | |
function usetool:openPutWindow(building) | |
local adv=df.global.world.units.active[0] | |
local items=EnumItems{pos=adv.pos,unit=adv, | |
inv={[df.unit_inventory_item.T_mode.Hauled]=true,--[df.unit_inventory_item.T_mode.Worn]=true, | |
[df.unit_inventory_item.T_mode.Weapon]=true,},deep=true} | |
local choices={} | |
for k,v in pairs(items) do | |
table.insert(choices,{text=dfhack.items.getDescription(v,0),item=v}) | |
end | |
dialog.showListPrompt("Item choice", "Choose item to put into:", COLOR_WHITE,choices,function (idx,choice) putItemToBuilding(building,choice.item) end) | |
end | |
function usetool:openSiegeWindow(building) | |
dialog.showListPrompt("Engine job choice", "Choose what to do:",COLOR_WHITE,{"Turn","Load","Fire"}, | |
dfhack.curry(siegeWeaponActionChosen,building)) | |
end | |
function usetool:onWorkShopButtonClicked(building,index,choice) | |
local adv=df.global.world.units.active[0] | |
if df.interface_button_building_new_jobst:is_instance(choice.button) then | |
choice.button:click() | |
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} | |
end | |
elseif df.interface_button_building_category_selectorst:is_instance(choice.button) or | |
df.interface_button_building_material_selectorst:is_instance(choice.button) then | |
choice.button:click() | |
self:openShopWindowButtoned(building,true) | |
end | |
end | |
function usetool:openShopWindowButtoned(building,no_reset) | |
self:setupFields() | |
local wui=df.global.ui_sidebar_menus.workshop_job | |
if not no_reset then | |
-- [[ manual reset incase the df-one does not exist? | |
wui:assign{category_id=-1,mat_type=-1,mat_index=-1} | |
for k,v in pairs(wui.material_category) do | |
wui.material_category[k]=false | |
end | |
--]] | |
--[[building:fillSidebarMenu() | |
if #wui.choices_all>0 then | |
wui.choices_all[#wui.choices_all-1]:click() | |
end | |
--]] | |
end | |
building:fillSidebarMenu() | |
local list={} | |
for id,choice in pairs(wui.choices_visible) do | |
table.insert(list,{text=utils.call_with_string(choice,"getLabel"),button=choice}) | |
end | |
if #list ==0 and not no_reset then | |
print("Fallback") | |
self:openShopWindow(building) | |
return | |
--qerror("No jobs for this workshop") | |
end | |
dialog.showListPrompt("Workshop job choice", "Choose what to make",COLOR_WHITE,list,self:callback("onWorkShopButtonClicked",building) | |
,nil, nil,true) | |
end | |
function usetool:openShopWindow(building) | |
local adv=df.global.world.units.active[0] | |
local filter_pile=workshopJobs.getJobs(building:getType(),building:getSubtype(),building:getCustomType()) | |
if filter_pile then | |
local state={unit=adv,from_pos={x=adv.pos.x,y=adv.pos.y, z=adv.pos.z,building=building} | |
,screen=self,bld=building,common=filter_pile.common} | |
choices={} | |
for k,v in pairs(filter_pile) do | |
table.insert(choices,{job_id=0,text=v.name:lower(),filter=v}) | |
end | |
dialog.showListPrompt("Workshop job choice", "Choose what to make",COLOR_WHITE,choices,dfhack.curry(onWorkShopJobChosen,state) | |
,nil, nil,true) | |
else | |
qerror("No jobs for this workshop") | |
end | |
end | |
function usetool:armCleanTrap(building) | |
local adv=df.global.world.units.active[0] | |
--[[ | |
Lever, | |
PressurePlate, | |
CageTrap, | |
StoneFallTrap, | |
WeaponTrap, | |
TrackStop | |
--]] | |
if building.state==0 then | |
--CleanTrap | |
--[[ LoadCageTrap, | |
LoadStoneTrap, | |
LoadWeaponTrap, | |
]] | |
if building.trap_type==df.trap_type.Lever then | |
--link | |
return | |
end | |
--building.trap_type==df.trap_type.PressurePlate then | |
--settings/link | |
local args={unit=adv,post_actions={AssignBuildingRef,AssignJobItems},pos=adv.pos,from_pos=adv.pos, | |
building=building,job_type=df.job_type.CleanTrap} | |
if building.trap_type==df.trap_type.CageTrap then | |
args.job_type=df.job_type.LoadCageTrap | |
local job_filter={items={{quantity=1,item_type=df.item_type.CAGE}} } | |
args.pre_actions={dfhack.curry(setFiltersUp,job_filter)} | |
elseif building.trap_type==df.trap_type.StoneFallTrap then | |
args.job_type=df.job_type.LoadStoneTrap | |
local job_filter={items={{quantity=1,item_type=df.item_type.BOULDER}} } | |
args.pre_actions={dfhack.curry(setFiltersUp,job_filter)} | |
elseif building.trap_type==df.trap_type.WeaponTrap then | |
qerror("TODO") | |
else | |
return | |
end | |
local job,msg=makeJob(args) | |
if not job then | |
print(msg) | |
end | |
end | |
end | |
function usetool:hiveActions(building) | |
local adv=df.global.world.units.active[0] | |
local args={unit=adv,post_actions={AssignBuildingRef,AssignJobItems},pos=adv.pos, | |
from_pos=adv.pos,job_type=df.job_type.InstallColonyInHive,building=building} | |
local job_filter={items={{quantity=1,item_type=df.item_type.VERMIN}} } | |
args.pre_actions={dfhack.curry(setFiltersUp,job_filter)} | |
local job,msg=makeJob(args) | |
if not job then | |
print(msg) | |
end | |
--InstallColonyInHive, | |
--CollectHiveProducts, | |
end | |
function usetool:operatePump(building) | |
local adv=df.global.world.units.active[0] | |
makeJob{unit=adv,post_actions={AssignBuildingRef},pos=adv.pos,from_pos=adv.pos,job_type=df.job_type.OperatePump} | |
end | |
function usetool:farmPlot(building) | |
local adv=df.global.world.units.active[0] | |
local do_harvest=false | |
for id, con_item in pairs(building.contained_items) do | |
if con_item.use_mode==2 and con_item.item:getType()==df.item_type.PLANT then | |
if same_xyz(adv.pos,con_item.item.pos) then | |
do_harvest=true | |
end | |
end | |
end | |
--check if there tile is without plantseeds,add job | |
local args={unit=adv,pos=adv.pos,from_pos=adv.pos, | |
} | |
if not do_harvest then | |
local seedjob={items={{quantity=1,item_type=df.item_type.SEEDS}}} | |
args.job_type=df.job_type.PlantSeeds | |
args.pre_actions={dfhack.curry(setFiltersUp,seedjob)} | |
args.post_actions={AssignBuildingRef} | |
else | |
args.job_type=df.job_type.HarvestPlants | |
args.post_actions={AssignBuildingRef} | |
end | |
local job,msg=makeJob(args) | |
if not job then | |
print(msg) | |
else | |
--print(AssignJobItems(args)) --WHY U NO WORK? | |
end | |
end | |
MODES={ | |
[df.building_type.Table]={ --todo filters... | |
name="Put items", | |
input=usetool.openPutWindow, | |
}, | |
[df.building_type.Coffin]={ | |
name="Put items", | |
input=usetool.openPutWindow, | |
}, | |
[df.building_type.Box]={ | |
name="Put items", | |
input=usetool.openPutWindow, | |
}, | |
[df.building_type.Weaponrack]={ | |
name="Put items", | |
input=usetool.openPutWindow, | |
}, | |
[df.building_type.Armorstand]={ | |
name="Put items", | |
input=usetool.openPutWindow, | |
}, | |
[df.building_type.Cabinet]={ | |
name="Put items", | |
input=usetool.openPutWindow, | |
}, | |
[df.building_type.Workshop]={ | |
name="Workshop menu", | |
input=usetool.openShopWindowButtoned, | |
}, | |
[df.building_type.Furnace]={ | |
name="Workshop menu", | |
input=usetool.openShopWindowButtoned, | |
}, | |
[df.building_type.SiegeEngine]={ | |
name="Siege menu", | |
input=usetool.openSiegeWindow, | |
}, | |
[df.building_type.FarmPlot]={ | |
name="Plant/Harvest", | |
input=usetool.farmPlot, | |
}, | |
[df.building_type.ScrewPump]={ | |
name="Operate Pump", | |
input=usetool.operatePump, | |
}, | |
[df.building_type.Trap]={ | |
name="Interact", | |
input=usetool.armCleanTrap, | |
}, | |
[df.building_type.Hive]={ | |
name="Hive actions", | |
input=usetool.hiveActions, | |
} | |
} | |
function usetool:shopMode(enable,mode,building) | |
self.subviews.shopLabel.visible=enable | |
if mode then | |
self.subviews.shopLabel:itemById("text1").text=mode.name | |
self.building=building | |
end | |
self.mode=mode | |
end | |
function usetool:shopInput(keys) | |
if keys[keybinds.workshop.key] then | |
self:openShopWindowButtoned(self.in_shop) | |
end | |
end | |
function usetool:setupFields() | |
local adv=df.global.world.units.active[0] | |
local civ_id=df.global.world.units.active[0].civ_id | |
local ui=df.global.ui | |
ui.civ_id = civ_id | |
ui.main.fortress_entity=df.historical_entity.find(civ_id) | |
ui.race_id=adv.race | |
local nem=dfhack.units.getNemesis(adv) | |
if nem then | |
local links=nem.figure.entity_links | |
for _,link in ipairs(links) do | |
local hist_entity=df.historical_entity.find(link.entity_id) | |
if hist_entity and hist_entity.type==df.historical_entity_type.SiteGovernment then | |
ui.group_id=link.entity_id | |
break | |
end | |
end | |
end | |
local site= inSite() | |
if site then | |
ui.site_id=site.id | |
end | |
end | |
function usetool:fieldInput(keys) | |
local adv=df.global.world.units.active[0] | |
local cur_mode=actions[(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)%#actions | |
elseif keys[keybinds.prevJob.key] then | |
mode=mode-1 | |
if mode<0 then mode=#actions-1 end | |
--elseif keys.A_LOOK then | |
-- self:sendInputToParent("A_LOOK") | |
elseif keys["A_SHORT_WAIT"] then | |
--ContinueJob(adv) | |
self:sendInputToParent("A_SHORT_WAIT") | |
elseif keys[keybinds.continue.key] then | |
ContinueJob(adv) | |
self:sendInputToParent("A_SHORT_WAIT") | |
self.long_wait=true | |
else | |
if self.mode~=nil then | |
if keys[keybinds.workshop.key] then | |
self.mode.input(self,self.building) | |
end | |
self:fieldInput(keys) | |
else | |
self:fieldInput(keys) | |
end | |
end | |
local site=inSite() | |
if site then | |
self.subviews.siteLabel.visible=true | |
self.subviews.siteLabel:itemById("site").text=dfhack.TranslateName(site.name) | |
else | |
self.subviews.siteLabel.visible=false | |
end | |
end | |
function usetool:onIdle() | |
local adv=df.global.world.units.active[0] | |
local job_ptr=adv.job.current_job | |
local job=findAction(adv,df.unit_action_type.Job) | |
if job_ptr and self.long_wait and not job then | |
if adv.job.current_job.completion_timer==0 or adv.job.current_job.completion_timer==-1 then | |
self.long_wait=false | |
end | |
ContinueJob(adv) | |
self:sendInputToParent("A_SHORT_WAIT") --todo continue till finished | |
end | |
self._native.parent:logic() | |
end | |
function usetool:isOnBuilding() | |
local adv=df.global.world.units.active[0] | |
local bld=dfhack.buildings.findAtTile(adv.pos) | |
if bld and MODES[bld:getType()]~=nil and bld:getBuildStage()==bld:getMaxBuildStage() then | |
return true,MODES[bld:getType()],bld | |
else | |
return false | |
end | |
end | |
function usetool:onRenderBody(dc) | |
self:shopMode(self:isOnBuilding()) | |
self:renderParent() | |
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment