2012-11-28 17:26:10 -07:00
-- allows to do jobs in adv. mode.
2013-06-14 01:20:36 -06:00
2014-12-07 13:17:37 -07:00
--[==[
2014-12-08 13:19:22 -07:00
version : 0.003
2014-12-07 13:17:37 -07:00
changelog :
2014-12-08 13:19:22 -07:00
* 0.003
- fixed farms ( i think ... )
- added faster time pasing ( yay for random deaths from local wildlife )
- still hasn ' t fixed gather plants. but you can visit local market, buy a few local fruits/vegetables eat them and use seeds
- other stuff
2014-12-07 13:17:37 -07:00
* 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 .
--]==]
2013-06-14 01:20:36 -06:00
--keybinding, change to your hearts content. Only the key part.
2012-12-01 09:20:27 -07:00
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 " } ,
2012-12-06 09:27:54 -07:00
workshop = { key = " CHANGETAB " , desc = " Show building menu " } ,
2012-12-01 09:20:27 -07:00
}
2013-06-14 01:20:36 -06:00
-- building filters
build_filter = {
2014-11-30 12:46:46 -07:00
forbid_all = false , --this forbits all except the "allow"
allow = { " MetalSmithsForge " } , --ignored if forbit_all=false
forbid = { } --ignored if forbit_all==true
2013-06-14 01:20:36 -06:00
}
build_filter.HUMANish = {
2014-11-30 12:46:46 -07:00
forbid_all = true ,
allow = { " Masons " } ,
forbid = { }
2013-06-14 01:20:36 -06:00
}
2013-02-04 22:21:44 -07:00
2014-12-07 13:17:37 -07:00
--[[ 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
2012-11-28 17:26:10 -07:00
local gui = require ' gui '
local wid = require ' gui.widgets '
local dialog = require ' gui.dialogs '
local buildings = require ' dfhack.buildings '
2012-11-29 11:49:16 -07:00
local bdialog = require ' gui.buildings '
2012-12-03 12:49:17 -07:00
local workshopJobs = require ' dfhack.workshops '
2013-01-03 14:21:57 -07:00
local utils = require ' utils '
2012-11-29 02:56:05 -07:00
2012-11-29 08:16:32 -07:00
local tile_attrs = df.tiletype . attrs
2012-12-01 09:20:27 -07:00
2014-12-09 15:09:28 -07:00
settings = { build_by_items = false , use_worn = false , check_inv = false , teleport_items = true , df_assign = false , gui_item_select = false }
2012-12-03 12:49:17 -07:00
2013-06-14 01:20:36 -06:00
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 )
2014-12-07 13:17:37 -07:00
--print(name)
2013-06-14 01:20:36 -06:00
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
2012-12-03 12:49:17 -07:00
local mode_name
for k , v in ipairs ( { ... } ) do --setting parsing
2012-11-29 15:02:03 -07:00
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
2012-12-03 12:49:17 -07:00
else
mode_name = v
2012-11-29 15:02:03 -07:00
end
end
2012-12-01 09:20:27 -07:00
2012-11-28 17:26:10 -07:00
mode = mode or 0
2013-03-05 15:22:59 -07:00
last_building = last_building or { }
2012-12-01 09:20:27 -07:00
2012-11-28 17:26:10 -07:00
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 )
2013-01-04 16:41:44 -07:00
dialog.showMessage ( " Help!?! " , helptext )
2012-11-28 17:26:10 -07:00
end
2013-03-03 08:33:07 -07:00
--[[ 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
2012-12-03 12:49:17 -07:00
--[[ low level job management ]] --
2014-11-30 12:46:46 -07:00
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
2012-11-28 17:26:10 -07:00
end
end
2014-11-30 12:46:46 -07:00
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}}})
2012-11-28 17:26:10 -07:00
end
2012-12-03 12:49:17 -07:00
function makeJob ( args )
2012-12-01 09:20:27 -07:00
local newJob = df.job : new ( )
newJob.id = df.global . job_next_id
2012-11-28 17:26:10 -07:00
df.global . job_next_id = df.global . job_next_id + 1
2014-11-30 12:46:46 -07:00
newJob.flags . special = true
2012-12-01 09:20:27 -07:00
newJob.job_type = args.job_type
newJob.completion_timer =- 1
2012-11-29 15:02:03 -07:00
2012-12-01 09:20:27 -07:00
newJob.pos : assign ( args.pos )
2014-11-30 12:46:46 -07:00
--newJob.pos:assign(args.unit.pos)
2012-12-01 09:20:27 -07:00
args.job = newJob
2012-12-03 12:49:17 -07:00
local failed
2012-11-29 15:02:03 -07:00
for k , v in ipairs ( args.pre_actions or { } ) do
local ok , msg = v ( args )
if not ok then
2012-12-03 12:49:17 -07:00
failed = msg
break
2012-11-29 15:02:03 -07:00
end
end
2012-12-03 12:49:17 -07:00
if failed == nil then
2012-12-01 09:20:27 -07:00
AssignUnitToJob ( newJob , args.unit , args.from_pos )
2012-12-03 12:49:17 -07:00
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
2012-11-29 15:02:03 -07:00
end
2012-12-03 12:49:17 -07:00
if failed == nil then
2014-11-30 12:46:46 -07:00
dfhack.job . linkIntoWorld ( newJob , true )
addJobAction ( newJob , args.unit )
2012-12-03 12:49:17 -07:00
return newJob
else
newJob : delete ( )
return false , failed
2012-11-28 17:26:10 -07:00
end
2012-12-03 12:49:17 -07:00
2012-11-28 17:26:10 -07:00
end
2012-12-03 12:49:17 -07:00
function UnassignJob ( job , unit , unit_pos )
unit.job . current_job = nil
end
2012-11-28 17:26:10 -07:00
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 )
2012-12-03 12:49:17 -07:00
return true
2012-11-28 17:26:10 -07:00
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
2013-06-14 01:20:36 -06:00
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
2012-11-28 17:26:10 -07:00
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
2013-03-19 13:49:35 -06:00
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
2012-11-28 17:26:10 -07:00
function MakePredicateWieldsItem ( item_skill )
local pred = function ( args )
local inv = args.unit . inventory
for k , v in pairs ( inv ) do
2013-03-21 03:50:14 -06:00
if v.mode == 1 and v.item : getMeleeSkill ( ) == item_skill and args.unit . body.weapon_bp == v.body_part_id then
return true
2012-11-28 17:26:10 -07:00
end
end
return false , " Correct tool not equiped "
end
return pred
end
2012-11-29 15:02:03 -07:00
2012-11-28 17:26:10 -07:00
function makeset ( args )
local tbl = { }
for k , v in pairs ( args ) do
tbl [ v ] = true
end
return tbl
end
2012-11-29 08:16:32 -07:00
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
2012-12-06 09:27:54 -07:00
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
2012-11-29 08:50:22 -07:00
function IsBuilding ( args )
if dfhack.buildings . findAtTile ( args.pos ) then
return true
end
return false , " Can only do it on buildings "
end
2012-11-28 17:26:10 -07:00
function IsConstruct ( args )
local tt = dfhack.maps . getTileType ( args.pos )
2012-11-29 08:50:22 -07:00
if tile_attrs [ tt ] . material == df.tiletype_material . CONSTRUCTION then
2012-11-28 17:26:10 -07:00
return true
else
return false , " Can only do it on constructions "
end
end
2013-01-03 14:21:57 -07:00
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
2012-11-29 08:16:32 -07:00
function IsHardMaterial ( args )
local tt = dfhack.maps . getTileType ( args.pos )
local mat = tile_attrs [ tt ] . material
2013-01-03 14:21:57 -07:00
local hard_materials = makeset { df.tiletype_material . STONE , df.tiletype_material . FEATURE ,
2012-11-29 08:16:32 -07:00
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
2012-11-28 17:26:10 -07:00
function IsWall ( args )
local tt = dfhack.maps . getTileType ( args.pos )
2012-11-29 08:16:32 -07:00
if tile_attrs [ tt ] . shape == df.tiletype_shape . WALL then
2012-11-28 17:26:10 -07:00
return true
else
return false , " Can only do it on walls "
end
end
function IsTree ( args )
local tt = dfhack.maps . getTileType ( args.pos )
2014-11-30 12:46:46 -07:00
if tile_attrs [ tt ] . material == df.tiletype_material . TREE then
2012-11-28 17:26:10 -07:00
return true
else
return false , " Can only do it on trees "
end
end
function IsPlant ( args )
2012-11-29 08:16:32 -07:00
local tt = dfhack.maps . getTileType ( args.pos )
2012-12-01 09:20:27 -07:00
if tile_attrs [ tt ] . shape == df.tiletype_shape . SHRUB then
2012-11-29 08:16:32 -07:00
return true
else
return false , " Can only do it on plants "
end
end
function IsWater ( args )
2012-11-28 17:26:10 -07:00
return true
end
2012-11-29 08:16:32 -07:00
2012-11-28 17:26:10 -07:00
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
2012-12-06 09:27:54 -07:00
function itemsAtPos ( pos , tbl )
local ret = tbl or { }
2012-11-28 17:26:10 -07:00
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 )
2014-12-07 13:17:37 -07:00
local bld = args.building or dfhack.buildings . findAtTile ( args.pos )
2012-11-28 17:26:10 -07:00
args.job . general_refs : insert ( " # " , { new = df.general_ref_building_holderst , building_id = bld.id } )
bld.jobs : insert ( " # " , args.job )
2014-12-07 13:17:37 -07:00
args.building = args.building or bld
2012-12-03 12:49:17 -07:00
return true
2012-11-29 08:16:32 -07:00
end
2013-01-04 16:41:44 -07:00
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
2012-11-29 11:49:16 -07:00
function BuildingChosen ( inp_args , type_id , subtype_id , custom_id )
2013-01-04 16:41:44 -07:00
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
2013-03-05 15:22:59 -07:00
last_building.type = args.type
last_building.subtype = args.subtype
last_building.custom = args.custom
2013-01-04 16:41:44 -07:00
if chooseBuildingWidthHeightDir ( args ) then
2013-03-05 15:22:59 -07:00
2013-01-04 16:41:44 -07:00
return
end
2012-11-29 15:02:03 -07:00
--if settings.build_by_items then
-- args.items=itemsAtPos(inp_args.from_pos)
--end
2012-11-29 11:49:16 -07:00
buildings.constructBuilding ( args )
2012-11-28 17:26:10 -07:00
end
2012-11-29 15:02:03 -07:00
2012-11-29 08:50:22 -07:00
function RemoveBuilding ( args )
2012-11-29 08:24:45 -07:00
local bld = dfhack.buildings . findAtTile ( args.pos )
2012-11-29 08:50:22 -07:00
if bld ~= nil then
2012-11-29 08:24:45 -07:00
bld : queueDestroy ( )
2012-11-29 08:50:22 -07:00
for k , v in ipairs ( bld.jobs ) do
if v.job_type == df.job_type . DestroyBuilding then
2012-11-29 15:02:03 -07:00
AssignUnitToJob ( v , args.unit , args.from_pos )
return true
2012-11-29 08:50:22 -07:00
end
end
2012-11-29 15:02:03 -07:00
return false , " Building removal job failed to be created "
else
return false , " No building to remove "
2012-11-29 08:24:45 -07:00
end
end
2012-12-01 09:20:27 -07:00
2012-12-03 12:49:17 -07:00
function isSuitableItem ( job_item , item )
2012-12-09 14:07:13 -07:00
--todo butcher test
2012-12-01 09:20:27 -07:00
if job_item.item_type ~=- 1 then
if item : getType ( ) ~= job_item.item_type then
2013-01-04 16:41:44 -07:00
2012-12-01 09:20:27 -07:00
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
2013-01-06 09:58:58 -07:00
if job_item.flags1 . sand_bearing and not item : isSandBearing ( ) then
return false , " not sand bearing "
end
2013-02-04 22:21:44 -07:00
if job_item.flags1 . butcherable and not ( item : getType ( ) == df.item_type . CORPSE or item : getType ( ) == df.item_type . CORPSEPIECE ) then
2013-01-06 09:58:58 -07:00
return false , " not butcherable "
end
2012-12-01 09:20:27 -07:00
local matinfo = dfhack.matinfo . decode ( item )
--print(matinfo:getCraftClass())
2012-12-03 12:49:17 -07:00
--print("Matching ",item," vs ",job_item)
2014-12-07 13:17:37 -07:00
2012-12-01 09:20:27 -07:00
if not matinfo : matches ( job_item ) then
2014-12-07 13:17:37 -07:00
--[[
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
--]]
2012-12-01 09:20:27 -07:00
return false , " matinfo "
end
2012-12-03 12:49:17 -07:00
-- some bonus checks:
if job_item.flags2 . building_material and not item : isBuildMat ( ) then
return false , " non-build mat "
end
-- *****************
--print("--Matched")
2012-12-01 09:20:27 -07:00
--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
2012-12-09 14:07:13 -07:00
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
2012-12-01 09:20:27 -07:00
end
if job_item.reaction_class ~= " " then
2012-12-09 15:14:05 -07:00
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
2012-12-01 09:20:27 -07:00
end
return true
end
2012-12-03 12:49:17 -07:00
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
2013-03-09 03:54:07 -07:00
function AddItem ( tbl , item , recurse , skip_add )
if not skip_add then
table.insert ( tbl , item )
end
2012-12-06 09:27:54 -07:00
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 )
2013-03-09 03:54:07 -07:00
elseif args.deep then
AddItem ( ret , v.item , args.deep , true )
2012-12-06 09:27:54 -07:00
end
end
end
return ret
end
2014-12-07 13:17:37 -07:00
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
2014-12-08 13:19:22 -07:00
function putItemsInHauling ( unit , job_item_refs )
for k , v in ipairs ( job_item_refs ) do
--local pos=dfhack.items.getPosition(v)
if not dfhack.items . moveToInventory ( v.item , unit , 0 , 0 ) then
print ( " Could not put item: " , k , v.item )
end
v.is_fetching = 0
end
end
2012-12-03 12:49:17 -07:00
function AssignJobItems ( args )
if settings.df_assign then --use df default logic and hope that it would work
2012-11-29 15:02:03 -07:00
return true
end
2012-12-03 12:49:17 -07:00
-- first find items that you want to use for the job
2012-11-29 15:02:03 -07:00
local job = args.job
2014-12-07 13:17:37 -07:00
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
2013-01-03 14:21:57 -07:00
--[[ 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
--]]
-- [=[
2012-11-29 15:02:03 -07:00
--[[while(#job.items>0) do --clear old job items
job.items [ # job.items - 1 ] : delete ( )
job.items : erase ( # job.items - 1 )
end ] ]
2014-12-08 13:19:22 -07:00
2012-12-03 12:49:17 -07:00
local item_counts = { }
for job_id , trg_job_item in ipairs ( job.job_items ) do
item_counts [ job_id ] = trg_job_item.quantity
end
2014-12-09 15:09:28 -07:00
local item_suitability = { }
2012-11-29 15:02:03 -07:00
local used_item_id = { }
for job_id , trg_job_item in ipairs ( job.job_items ) do
2014-12-09 15:09:28 -07:00
item_suitability [ job_id ] = { }
2012-11-29 15:02:03 -07:00
for _ , cur_item in pairs ( its ) do
if not used_item_id [ cur_item.id ] then
2012-12-01 09:20:27 -07:00
2014-12-09 15:09:28 -07:00
local item_suitable , msg = isSuitableItem ( trg_job_item , cur_item )
if item_suitable or settings.build_by_items then
table.insert ( item_suitability [ job_id ] , cur_item )
end
2014-12-07 13:17:37 -07:00
--[[
if msg then
print ( cur_item , msg )
end
] ] --
2014-12-09 15:09:28 -07:00
if not settings.gui_item_select then
if ( item_counts [ job_id ] > 0 and item_suitable ) or settings.build_by_items then
--cur_item.flags.in_job=true
job.items : insert ( " # " , { new = true , item = cur_item , role = df.job_item_ref . T_role.Reagent , job_item_idx = job_id } )
item_counts [ job_id ] = item_counts [ job_id ] - cur_item : getTotalDimension ( )
--print(string.format("item added, job_item_id=%d, item %s, quantity left=%d",job_id,tostring(cur_item),item_counts[job_id]))
used_item_id [ cur_item.id ] = true
end
2012-11-29 15:02:03 -07:00
end
end
end
end
2014-12-09 15:09:28 -07:00
if settings.gui_item_select then
require ( ' gui.script ' ) . start ( function ( )
require ( ' hack.scripts.gui.advfort_items ' ) . showItemEditor ( job , item_suitability )
end )
2012-12-01 09:20:27 -07:00
2014-12-09 15:09:28 -07:00
else
if not settings.build_by_items then
for job_id , trg_job_item in ipairs ( job.job_items ) do
if item_counts [ job_id ] > 0 then
print ( " Not enough items for this job " )
return false , " Not enough items for this job "
end
2012-11-29 15:02:03 -07:00
end
end
end
2014-12-09 15:09:28 -07:00
local item_mode = " teleport "
local item_modes = {
[ df.job_type . PlantSeeds ] = " haul " ,
[ df.job_type . ConstructBuilding ] = " default " ,
}
item_mode = item_modes [ job.job_type ]
if settings.teleport_items and item_mode == " teleport " then
2014-12-07 13:17:37 -07:00
putItemsInBuilding ( args.building , job.items )
end
2014-12-09 15:09:28 -07:00
2012-12-03 12:49:17 -07:00
local uncollected = getItemsUncollected ( job )
if # uncollected == 0 then
job.flags . working = true
2014-12-09 15:09:28 -07:00
if item_mode == " haul " then
2014-12-08 13:19:22 -07:00
putItemsInHauling ( args.unit , job.items )
end
2012-12-03 12:49:17 -07:00
else
job.flags . fetching = true
2013-01-06 09:58:58 -07:00
uncollected [ 1 ] . is_fetching = 1
2012-12-03 12:49:17 -07:00
end
2014-12-08 13:19:22 -07:00
2012-11-29 15:02:03 -07:00
return true
2013-01-03 14:21:57 -07:00
--]=]
2012-11-29 15:02:03 -07:00
end
2014-12-07 13:17:37 -07:00
2013-03-05 15:22:59 -07:00
function CheckAndFinishBuilding ( args , bld )
2014-12-07 13:17:37 -07:00
args.building = args.building or bld
2013-03-05 15:22:59 -07:00
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
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
2012-11-28 17:26:10 -07:00
function AssignJobToBuild ( args )
2014-12-07 13:17:37 -07:00
local bld = args.building or dfhack.buildings . findAtTile ( args.pos )
args.building = bld
2012-11-29 15:02:03 -07:00
args.job_type = df.job_type . ConstructBuilding
2012-11-28 17:26:10 -07:00
if bld ~= nil then
2013-03-05 15:22:59 -07:00
CheckAndFinishBuilding ( args , bld )
2012-11-28 17:26:10 -07:00
else
2013-06-14 01:20:36 -06:00
bdialog.BuildingDialog { on_select = dfhack.curry ( BuildingChosen , args ) , hide_none = true , building_filter = deon_filter } : show ( )
2012-11-28 17:26:10 -07:00
end
2012-11-29 15:02:03 -07:00
return true
2012-11-28 17:26:10 -07:00
end
2013-03-05 15:22:59 -07:00
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
2012-11-29 09:49:36 -07:00
function CancelJob ( unit )
local c_job = unit.job . current_job
if c_job then
2012-12-01 09:20:27 -07:00
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
2012-11-29 09:49:36 -07:00
end
end
2012-11-28 17:26:10 -07:00
function ContinueJob ( unit )
local c_job = unit.job . current_job
2014-11-30 12:46:46 -07:00
--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
2012-11-28 17:26:10 -07:00
end
end
2014-12-07 13:17:37 -07:00
--unit.path.dest:assign(c_job.pos) -- FIXME: job pos is not always the target pos!!
2014-11-30 12:46:46 -07:00
addJobAction ( c_job , unit )
2012-11-28 17:26:10 -07:00
end
2012-12-01 09:20:27 -07:00
2012-12-03 12:49:17 -07:00
actions = {
2013-01-03 14:21:57 -07:00
{ " CarveFortification " , df.job_type . CarveFortification , { IsWall , IsHardMaterial } } ,
2014-11-30 12:46:46 -07:00
{ " DetailWall " , df.job_type . DetailWall , { IsWall , IsHardMaterial } } ,
{ " DetailFloor " , df.job_type . DetailFloor , { IsFloor , IsHardMaterial , SameSquare } } ,
{ " CarveTrack " , df.job_type . CarveTrack , { IsFloor , IsHardMaterial }
2013-03-19 13:49:35 -06:00
, { SetCarveDir } } ,
2012-11-28 17:26:10 -07:00
{ " 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}},
2012-12-03 12:49:17 -07:00
{ " TameAnimal " , df.job_type . TameAnimal , { IsUnit } , { SetCreatureRef } } ,
2013-01-04 16:41:44 -07:00
{ " GatherPlants " , df.job_type . GatherPlants , { IsPlant , SameSquare } } ,
2012-11-29 08:50:22 -07:00
{ " RemoveConstruction " , df.job_type . RemoveConstruction , { IsConstruct } } ,
{ " RemoveBuilding " , RemoveBuilding , { IsBuilding } } ,
2012-12-03 12:49:17 -07:00
{ " RemoveStairs " , df.job_type . RemoveStairs , { IsStairs , NotConstruct } } ,
2012-11-28 17:26:10 -07:00
--{"HandleLargeCreature" ,df.job_type.HandleLargeCreature,{isUnit},{SetCreatureRef}},
2012-12-06 09:27:54 -07:00
{ " Build " , AssignJobToBuild , { NoConstructedBuilding } } ,
2013-03-05 15:22:59 -07:00
{ " BuildLast " , BuildLast , { NoConstructedBuilding } } ,
2013-01-04 16:41:44 -07:00
{ " Clean " , df.job_type . Clean , { } } ,
2013-06-14 01:20:36 -06:00
{ " GatherWebs " , df.job_type . CollectWebs , { --[[HasWeb]] } , { SetWebRef } } ,
2012-11-28 17:26:10 -07:00
}
2012-12-03 12:49:17 -07:00
for id , action in pairs ( actions ) do
if action [ 1 ] == mode_name then
mode = id - 1
break
end
end
2012-11-28 17:26:10 -07:00
usetool = defclass ( usetool , gui.Screen )
2012-12-01 09:42:23 -07:00
usetool.focus_path = ' advfort '
2012-11-28 17:26:10 -07:00
function usetool : getModeName ( )
local adv = df.global . world.units . active [ 0 ]
if adv.job . current_job then
2012-12-03 12:49:17 -07:00
return string.format ( " %s working(%d) " , ( actions [ ( mode or 0 ) + 1 ] [ 1 ] or " " ) , adv.job . current_job.completion_timer )
2012-11-28 17:26:10 -07:00
else
2012-12-03 12:49:17 -07:00
return actions [ ( mode or 0 ) + 1 ] [ 1 ] or " "
2012-11-28 17:26:10 -07:00
end
end
2012-12-03 12:49:17 -07:00
2012-11-28 17:26:10 -07:00
function usetool : init ( args )
self : addviews {
wid.Label {
2012-12-01 09:20:27 -07:00
view_id = " mainLabel " ,
2012-11-28 17:26:10 -07:00
frame = { xalign = 0 , yalign = 0 } ,
2014-01-07 09:15:49 -07:00
text = { { key = keybinds.prevJob . key } , { gap = 1 , text = self : callback ( " getModeName " ) } , { gap = 1 , key = keybinds.nextJob . key } ,
2012-12-01 09:20:27 -07:00
}
2012-11-29 15:02:03 -07:00
} ,
2012-12-01 09:20:27 -07:00
2012-11-29 15:02:03 -07:00
wid.Label {
2012-12-01 09:20:27 -07:00
view_id = " shopLabel " ,
frame = { l = 35 , xalign = 0 , yalign = 0 } ,
2012-11-29 15:02:03 -07:00
visible = false ,
2012-12-01 09:20:27 -07:00
text = {
2012-12-03 12:49:17 -07:00
{ id = " text1 " , gap = 1 , key = keybinds.workshop . key , key_sep = " () " , text = " Workshop menu " , pen = dfhack.pen . parse { fg = COLOR_YELLOW , bg = 0 } } }
2013-03-03 08:33:07 -07:00
} ,
wid.Label {
view_id = " siteLabel " ,
frame = { t = 1 , xalign =- 1 , yalign = 0 } ,
visible = false ,
text = {
{ id = " text1 " , text = " Site: " } , { id = " site " , text = " name " }
2012-11-28 17:26:10 -07:00
}
}
2013-03-03 08:33:07 -07:00
}
2014-12-07 13:17:37 -07:00
local labors = df.global . world.units . active [ 0 ] . status.labors
for i , v in ipairs ( labors ) do
labors [ i ] = true
end
2012-11-29 02:56:05 -07:00
end
2012-11-28 17:26:10 -07:00
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 } ,
}
2012-11-29 02:56:05 -07:00
ALLOWED_KEYS = {
A_MOVE_N = true , A_MOVE_S = true , A_MOVE_W = true , A_MOVE_E = true , A_MOVE_NW = true ,
2012-11-29 03:41:27 -07:00
A_MOVE_NE = true , A_MOVE_SW = true , A_MOVE_SE = true , A_STANCE = true , SELECT = true , A_MOVE_DOWN_AUX = true ,
2012-11-29 08:16:32 -07:00
A_MOVE_UP_AUX = true , A_LOOK = true , CURSOR_DOWN = true , CURSOR_UP = true , CURSOR_LEFT = true , CURSOR_RIGHT = true ,
2012-11-29 09:33:04 -07:00
CURSOR_UPLEFT = true , CURSOR_UPRIGHT = true , CURSOR_DOWNLEFT = true , CURSOR_DOWNRIGHT = true , A_CLEAR_ANNOUNCEMENTS = true ,
2012-11-29 09:49:36 -07:00
CURSOR_UP_Z = true , CURSOR_DOWN_Z = true ,
2012-11-29 02:56:05 -07:00
}
2012-11-28 17:26:10 -07:00
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
2012-12-03 12:49:17 -07:00
function setFiltersUp ( specific , args )
2012-12-01 09:20:27 -07:00
local job = args.job
2012-12-03 12:49:17 -07:00
if specific.job_fields ~= nil then
job : assign ( specific.job_fields )
2012-12-01 09:20:27 -07:00
end
2012-12-03 12:49:17 -07:00
--printall(specific)
for _ , v in ipairs ( specific.items ) do
--printall(v)
local filter = v
2012-12-01 09:20:27 -07:00
filter.new = true
job.job_items : insert ( " # " , filter )
end
return true
end
function onWorkShopJobChosen ( args , idx , choice )
args.pos = args.from_pos
2014-12-07 15:55:46 -07:00
args.building = args.building or dfhack.buildings . findAtTile ( args.pos )
2012-12-01 09:20:27 -07:00
args.job_type = choice.job_id
args.post_actions = { AssignBuildingRef }
2012-12-03 12:49:17 -07:00
args.pre_actions = { dfhack.curry ( setFiltersUp , choice.filter ) , AssignJobItems }
local job , msg = makeJob ( args )
2012-12-01 09:20:27 -07:00
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
2012-12-03 12:49:17 -07:00
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 )
2014-12-09 15:09:28 -07:00
CancelJob ( args.unit )
2012-12-03 12:49:17 -07:00
end
end
end
2012-12-06 09:27:54 -07:00
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 ,
2013-03-03 08:33:07 -07:00
inv = { [ df.unit_inventory_item . T_mode.Hauled ] = true , --[df.unit_inventory_item.T_mode.Worn]=true,
2012-12-06 09:27:54 -07:00
[ 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
2013-01-04 16:41:44 -07:00
dialog.showListPrompt ( " Item choice " , " Choose item to put into: " , COLOR_WHITE , choices , function ( idx , choice ) putItemToBuilding ( building , choice.item ) end )
2012-12-06 09:27:54 -07:00
end
2012-12-03 12:49:17 -07:00
function usetool : openSiegeWindow ( building )
2013-01-04 16:41:44 -07:00
dialog.showListPrompt ( " Engine job choice " , " Choose what to do: " , COLOR_WHITE , { " Turn " , " Load " , " Fire " } ,
2012-12-03 12:49:17 -07:00
dfhack.curry ( siegeWeaponActionChosen , building ) )
end
2013-01-03 14:21:57 -07:00
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 )
2014-12-09 15:09:28 -07:00
local ok , msg = AssignJobItems { job = job , from_pos = adv.pos , pos = adv.pos , unit = adv , building = building }
if not ok then
dfhack.gui . showAnnouncement ( msg , 5 , 1 )
CancelJob ( adv )
end
2013-01-03 14:21:57 -07:00
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
2013-01-03 15:48:24 -07:00
2013-01-03 14:21:57 -07:00
function usetool : openShopWindowButtoned ( building , no_reset )
2013-01-03 15:48:24 -07:00
self : setupFields ( )
2013-01-03 14:21:57 -07:00
local wui = df.global . ui_sidebar_menus.workshop_job
if not no_reset then
2013-01-03 15:48:24 -07:00
-- [[ manual reset incase the df-one does not exist?
2013-01-03 14:21:57 -07:00
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
2013-01-03 15:48:24 -07:00
--]]
--[[building:fillSidebarMenu()
2013-01-03 14:53:42 -07:00
if # wui.choices_all > 0 then
wui.choices_all [ # wui.choices_all - 1 ] : click ( )
end
2013-01-03 15:48:24 -07:00
--]]
2013-01-03 14:21:57 -07:00
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
2013-01-03 15:48:24 -07:00
if # list == 0 and not no_reset then
print ( " Fallback " )
2013-01-03 14:21:57 -07:00
self : openShopWindow ( building )
return
--qerror("No jobs for this workshop")
end
2013-01-04 16:41:44 -07:00
dialog.showListPrompt ( " Workshop job choice " , " Choose what to make " , COLOR_WHITE , list , self : callback ( " onWorkShopButtonClicked " , building )
2013-01-03 14:21:57 -07:00
, nil , nil , true )
end
2012-12-01 09:20:27 -07:00
function usetool : openShopWindow ( building )
local adv = df.global . world.units . active [ 0 ]
2013-01-03 14:21:57 -07:00
2012-12-03 12:49:17 -07:00
local filter_pile = workshopJobs.getJobs ( building : getType ( ) , building : getSubtype ( ) , building : getCustomType ( ) )
2012-12-01 09:20:27 -07:00
if filter_pile then
2014-12-07 15:55:46 -07:00
local state = { unit = adv , from_pos = { x = adv.pos . x , y = adv.pos . y , z = adv.pos . z , building = building }
2012-12-01 09:20:27 -07:00
, screen = self , bld = building , common = filter_pile.common }
choices = { }
for k , v in pairs ( filter_pile ) do
2012-12-03 12:49:17 -07:00
table.insert ( choices , { job_id = 0 , text = v.name : lower ( ) , filter = v } )
2012-12-01 09:20:27 -07:00
end
2013-01-04 16:41:44 -07:00
dialog.showListPrompt ( " Workshop job choice " , " Choose what to make " , COLOR_WHITE , choices , dfhack.curry ( onWorkShopJobChosen , state )
2012-12-01 09:20:27 -07:00
, nil , nil , true )
2012-12-08 15:53:03 -07:00
else
qerror ( " No jobs for this workshop " )
2012-12-01 09:20:27 -07:00
end
end
2013-02-04 22:21:44 -07:00
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 ,
] ]
2013-03-03 08:33:07 -07:00
if building.trap_type == df.trap_type . Lever then
--link
return
end
--building.trap_type==df.trap_type.PressurePlate then
--settings/link
2014-12-07 15:55:46 -07:00
local args = { unit = adv , post_actions = { AssignBuildingRef , AssignJobItems } , pos = adv.pos , from_pos = adv.pos ,
building = building , job_type = df.job_type . CleanTrap }
2013-02-04 22:21:44 -07:00
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 ]
2014-12-07 15:55:46 -07:00
local args = { unit = adv , post_actions = { AssignBuildingRef , AssignJobItems } , pos = adv.pos ,
from_pos = adv.pos , job_type = df.job_type . InstallColonyInHive , building = building }
2013-02-04 22:21:44 -07:00
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
2013-01-04 16:41:44 -07:00
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 )
2013-01-06 09:58:58 -07:00
if not job then
2013-01-04 16:41:44 -07:00
print ( msg )
2013-01-06 09:58:58 -07:00
else
2014-12-09 15:09:28 -07:00
local ok , msg = AssignJobItems ( args )
if not ok then
dfhack.gui . showAnnouncement ( msg , 5 , 1 )
CancelJob ( args.unit )
end
2013-01-04 16:41:44 -07:00
end
end
2012-12-03 12:49:17 -07:00
MODES = {
2012-12-06 09:27:54 -07:00
[ 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 ,
} ,
2012-12-03 12:49:17 -07:00
[ df.building_type . Workshop ] = {
name = " Workshop menu " ,
2013-01-03 14:21:57 -07:00
input = usetool.openShopWindowButtoned ,
2012-12-03 12:49:17 -07:00
} ,
2012-12-08 15:53:03 -07:00
[ df.building_type . Furnace ] = {
name = " Workshop menu " ,
2013-01-03 14:21:57 -07:00
input = usetool.openShopWindowButtoned ,
2012-12-08 15:53:03 -07:00
} ,
2012-12-03 12:49:17 -07:00
[ df.building_type . SiegeEngine ] = {
name = " Siege menu " ,
input = usetool.openSiegeWindow ,
} ,
2013-01-04 16:41:44 -07:00
[ df.building_type . FarmPlot ] = {
name = " Plant/Harvest " ,
input = usetool.farmPlot ,
2013-02-04 22:21:44 -07:00
} ,
[ df.building_type . ScrewPump ] = {
name = " Operate Pump " ,
input = usetool.operatePump ,
} ,
[ df.building_type . Trap ] = {
2013-03-03 08:33:07 -07:00
name = " Interact " ,
2013-02-04 22:21:44 -07:00
input = usetool.armCleanTrap ,
} ,
[ df.building_type . Hive ] = {
name = " Hive actions " ,
input = usetool.hiveActions ,
2013-01-04 16:41:44 -07:00
}
2012-12-03 12:49:17 -07:00
}
function usetool : shopMode ( enable , mode , building )
2012-12-01 09:20:27 -07:00
self.subviews . shopLabel.visible = enable
2012-12-03 12:49:17 -07:00
if mode then
2013-03-03 08:33:07 -07:00
self.subviews . shopLabel : itemById ( " text1 " ) . text = mode.name
self.building = building
2012-12-03 12:49:17 -07:00
end
self.mode = mode
2012-12-01 09:20:27 -07:00
end
function usetool : shopInput ( keys )
if keys [ keybinds.workshop . key ] then
2013-01-03 14:21:57 -07:00
self : openShopWindowButtoned ( self.in_shop )
2012-12-01 09:20:27 -07:00
end
end
2013-03-03 08:33:07 -07:00
2013-01-03 15:48:24 -07:00
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
2012-12-01 09:20:27 -07:00
function usetool : fieldInput ( keys )
local adv = df.global . world.units . active [ 0 ]
2012-12-03 12:49:17 -07:00
local cur_mode = actions [ ( mode or 0 ) + 1 ]
2012-12-01 09:20:27 -07:00
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
2012-12-03 12:49:17 -07:00
ok , msg = makeJob ( state )
2012-12-01 09:20:27 -07:00
--(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
2014-12-08 13:19:22 -07:00
self : sendInputToParent ( " A_SHORT_WAIT " )
2012-12-01 09:20:27 -07:00
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
2012-11-28 17:26:10 -07:00
function usetool : onInput ( keys )
2012-11-29 09:49:36 -07:00
local adv = df.global . world.units . active [ 0 ]
2013-03-03 08:33:07 -07:00
2012-11-28 17:26:10 -07:00
if keys.LEAVESCREEN then
2012-11-29 09:33:04 -07:00
if df.global . cursor.x ~=- 30000 then
self : sendInputToParent ( " LEAVESCREEN " )
else
self : dismiss ( )
2012-11-29 09:49:36 -07:00
CancelJob ( adv )
2012-11-29 09:33:04 -07:00
end
2012-12-01 09:20:27 -07:00
elseif keys [ keybinds.nextJob . key ] then
2012-12-03 12:49:17 -07:00
mode = ( mode + 1 ) %# actions
2012-12-01 09:20:27 -07:00
elseif keys [ keybinds.prevJob . key ] then
2012-11-28 17:26:10 -07:00
mode = mode - 1
2012-12-03 12:49:17 -07:00
if mode < 0 then mode =# actions - 1 end
2012-11-28 17:26:10 -07:00
--elseif keys.A_LOOK then
-- self:sendInputToParent("A_LOOK")
2014-11-30 12:46:46 -07:00
elseif keys [ " A_SHORT_WAIT " ] then
--ContinueJob(adv)
self : sendInputToParent ( " A_SHORT_WAIT " )
2012-12-01 09:20:27 -07:00
elseif keys [ keybinds.continue . key ] then
2014-12-08 13:19:22 -07:00
--ContinueJob(adv)
--self:sendInputToParent("A_SHORT_WAIT")
2014-11-30 12:46:46 -07:00
self.long_wait = true
2012-11-28 17:26:10 -07:00
else
2012-12-03 12:49:17 -07:00
if self.mode ~= nil then
if keys [ keybinds.workshop . key ] then
self.mode . input ( self , self.building )
end
self : fieldInput ( keys )
2012-12-01 09:20:27 -07:00
else
self : fieldInput ( keys )
2012-11-28 17:26:10 -07:00
end
end
2013-03-03 08:33:07 -07:00
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
2012-11-28 17:26:10 -07:00
end
2014-12-07 13:17:37 -07:00
2014-11-30 12:46:46 -07:00
function usetool : onIdle ( )
local adv = df.global . world.units . active [ 0 ]
2014-12-07 13:17:37 -07:00
local job_ptr = adv.job . current_job
2014-12-08 13:19:22 -07:00
local job_action = findAction ( adv , df.unit_action_type . Job )
2014-11-30 12:46:46 -07:00
2014-12-08 13:19:22 -07:00
if job_ptr and self.long_wait and not job_action then
if adv.job . current_job.completion_timer ==- 1 then
2014-11-30 12:46:46 -07:00
self.long_wait = false
end
ContinueJob ( adv )
self : sendInputToParent ( " A_SHORT_WAIT " ) --todo continue till finished
end
self._native . parent : logic ( )
end
2012-12-03 12:49:17 -07:00
function usetool : isOnBuilding ( )
local adv = df.global . world.units . active [ 0 ]
local bld = dfhack.buildings . findAtTile ( adv.pos )
2012-12-08 15:53:03 -07:00
if bld and MODES [ bld : getType ( ) ] ~= nil and bld : getBuildStage ( ) == bld : getMaxBuildStage ( ) then
2012-12-03 12:49:17 -07:00
return true , MODES [ bld : getType ( ) ] , bld
else
return false
end
end
function usetool : onRenderBody ( dc )
self : shopMode ( self : isOnBuilding ( ) )
self : renderParent ( )
end
2012-12-01 09:42:23 -07:00
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
2012-11-28 17:26:10 -07:00
usetool ( ) : show ( )