2012-11-28 17:26:10 -07:00
-- allows to do jobs in adv. mode.
2013-06-14 01:20:36 -06:00
2015-10-23 08:37:39 -06:00
--[[=begin
gui / advfort
===========
This script allows to perform jobs in adventure mode . For more complete help
press : kbd : ` ? ` while script is running . It ' s most comfortable to use this as a
keybinding . ( e.g . ` ` keybinding set Ctrl - T gui / advfort ` ` ) . Possible arguments :
: - a , --nodfassign: uses different method to assign items.
: - i , --inventory: checks inventory for possible items to use in the job.
: - c , --cheat: relaxes item requirements for buildings (e.g. walls from bones). Implies -a
: job : selects that job ( e.g . Dig or FellTree )
An example of player digging in adventure mode :
.. image :: / docs / images / advfort . png
2015-10-28 19:44:49 -06:00
** WARNING : ** changes only persist in non procedural sites , namely : player forts , caves , and camps .
2015-10-23 08:37:39 -06:00
= end ] ]
2014-12-07 13:17:37 -07:00
--[==[
2015-09-20 11:46:13 -06:00
version : 0.044
2014-12-07 13:17:37 -07:00
changelog :
2015-09-20 11:46:13 -06:00
* 0.044
- added output to clear_jobs of number of cleared jobs
- another failed attempt at gather plants fix
- added track stop configuration window
2015-09-19 03:18:30 -06:00
* 0.043
- fixed track carving : up / down was reversed and removed ( temp ) requirements because they were not working correctly
- added checks for unsafe conditions ( currently quite stupid ) . Should save few adventurers that are trying to work in dangerous conditions ( e.g . fishing )
- unsafe checks disabled by " -u " ir " --unsafe "
2015-09-18 11:32:33 -06:00
* 0.042
- fixed ( probably for sure now ) the crash bug .
- added --clear_jobs debug option. Will delete ALL JOBS!
2015-09-16 05:05:29 -06:00
* 0.041
- fixed cooking allowing already cooked meals
2015-09-14 09:54:02 -06:00
* 0.04
- add ( - q ) uick mode . Autoselects materials .
- fixed few ( ? ) crash bugs
- fixed job errors not being shown in df
2015-09-10 05:38:44 -06:00
* 0.031
- make forbiding optional ( - s ) afe mode
2015-09-09 13:14:06 -06:00
* 0.03
- forbid doing anything in non - sites unless you are ( - c ) heating
- a bit more documentation and tidying
- add a deadlock fix
2015-02-22 01:43:12 -07:00
* 0.021
- advfort_items now autofills items
- tried out few things to fix gather plants
2015-02-03 15:04:12 -07:00
* 0.02
- fixed axles not being able to be placed in other direction ( thanks SyrusLD )
- added lever linking
- restructured advfort_items , don ' t forget to update that too!
- Added clutter view if shop is cluttered .
2015-01-26 13:35:46 -07:00
* 0.013
- fixed siege weapons and traps ( somewhat ) . Now you can load them with new menu : )
2015-01-13 01:30:53 -07:00
* 0.012
- fix for some jobs not finding correct building .
2014-12-17 14:05:48 -07:00
* 0.011
- fixed crash with building jobs ( other jobs might have been crashing too ! )
- fixed bug with building asking twice to input items
2014-12-12 01:32:22 -07:00
* 0.01
- instant job startation
- item selection screen ( ! )
- BUG : custom jobs need stuff on ground to work
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 .
2015-01-26 13:35:46 -07:00
todo list :
- document everything ! Maybe somebody would understand what is happening then and help me : <
- when building trap add to known traps ( or known adventurers ? ) so that it does not trigger on adventurer
2015-01-31 03:30:19 -07:00
bugs list :
- items blocking construction stuck the game
- burning charcoal crashed game
- gem thingies probably broken
2015-02-03 15:04:12 -07:00
- custom reactions semibroken
2015-09-09 13:14:06 -06:00
- gathering plants still broken
2015-01-26 13:35:46 -07:00
2014-12-07 13:17:37 -07:00
--]==]
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 " } ,
2015-09-09 13:30:00 -06:00
up_alt1 = { key = " CUSTOM_CTRL_E " , desc = " Use job up " } ,
2012-12-01 09:20:27 -07:00
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 " } ,
2015-09-14 09:54:02 -06:00
quick = { key = " CUSTOM_Q " , desc = " Toggle quick item select " } ,
2012-12-01 09:20:27 -07:00
}
2013-06-14 01:20:36 -06:00
-- building filters
2015-09-09 13:30:00 -06:00
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
2015-09-09 13:14:06 -06:00
--economic stone fix: just disable all of them
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 '
2014-12-12 01:32:22 -07:00
local gscript = require ' gui.script '
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-17 14:05:48 -07:00
settings = { build_by_items = false , use_worn = false , check_inv = true , teleport_items = true , df_assign = false , gui_item_select = true , only_in_sites = 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
2015-09-09 13:30:00 -06:00
else
2013-06-14 01:20:36 -06:00
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
2015-09-14 09:54:02 -06:00
elseif v == " -q " or v == " --quick " then
settings.quick = true
2015-09-19 03:18:30 -06:00
elseif v == " -u " or v == " --unsafe " then --ignore pain and etc
settings.unsafe = true
2015-09-10 05:38:44 -06:00
elseif v == " -s " or v == " --safe " then
settings.safe = true
2012-11-29 15:02:03 -07:00
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
2015-09-09 13:14:06 -06:00
elseif v == " -h " or v == " --help " then
settings.help = true
2015-09-18 11:32:33 -06:00
elseif v == " --clear_jobs " then
settings.clear_jobs = true
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
2015-09-09 13:14:06 -06:00
if settings.help then
showHelp ( )
return
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 ( )
2015-09-09 13:30:00 -06:00
2013-03-03 08:33:07 -07:00
local tx , ty = advGlobalPos ( )
2015-09-09 13:30:00 -06:00
2013-03-03 08:33:07 -07:00
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
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-11-29 15:02:03 -07:00
2014-12-12 01:32:22 -07:00
function make_native_job ( args )
if args.job == nil then
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
2014-12-17 14:05:48 -07:00
args.unlinked = true
2012-11-29 15:02:03 -07:00
end
2014-12-12 01:32:22 -07:00
end
2015-09-14 09:54:02 -06:00
function smart_job_delete ( job )
local gref_types = df.general_ref_type
2015-09-18 11:32:33 -06:00
--TODO: unmark items as in job
2015-09-14 09:54:02 -06:00
for i , v in ipairs ( job.general_refs ) do
if v : getType ( ) == gref_types.BUILDING_HOLDER then
local b = v : getBuilding ( )
if b then
2015-09-18 11:32:33 -06:00
--remove from building
2015-09-14 09:54:02 -06:00
for i , v in ipairs ( b.jobs ) do
if v == job then
b.jobs : erase ( i )
break
end
end
2015-09-18 11:32:33 -06:00
else
print ( " Warning: building holder ref was invalid while deleting job " )
end
elseif v : getType ( ) == gref_types.UNIT_WORKER then
local u = v : getUnit ( )
if u then
u.job . current_job = nil
else
print ( " Warning: unit worker ref was invalid while deleting job " )
2015-09-14 09:54:02 -06:00
end
else
print ( " Warning: failed to remove link from job with type: " , gref_types [ v : getType ( ) ] )
end
end
2015-09-18 11:32:33 -06:00
--unlink job
local link = job.list_link
if link.prev then
link.prev . next = link.next
end
if link.next then
link.next . prev = link.prev
end
link : delete ( )
--finally delete the job
job : delete ( )
end
--TODO: this logic might be better with other --starting logic--
if settings.clear_jobs then
print ( " Clearing job list! " )
2015-09-20 11:46:13 -06:00
local counter = 0
2015-09-18 11:32:33 -06:00
local job_link = df.global . world.job_list . next
while job_link and job_link.item do
local job = job_link.item
job_link = job_link.next
smart_job_delete ( job )
2015-09-20 11:46:13 -06:00
counter = counter + 1
2015-09-18 11:32:33 -06:00
end
2015-09-20 11:46:13 -06:00
print ( " Deleted: " .. counter .. " jobs " )
2015-09-18 11:32:33 -06:00
return
2015-09-14 09:54:02 -06:00
end
2014-12-12 01:32:22 -07:00
function makeJob ( args )
gscript.start ( function ( )
make_native_job ( args )
local failed
for k , v in ipairs ( args.pre_actions or { } ) do
2012-12-03 12:49:17 -07:00
local ok , msg = v ( args )
if not ok then
failed = msg
break
end
end
2014-12-12 01:32:22 -07:00
if failed == nil then
AssignUnitToJob ( args.job , 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 ( args.job , args.unit )
end
2012-12-03 12:49:17 -07:00
end
2014-12-12 01:32:22 -07:00
if failed == nil then
2014-12-17 14:05:48 -07:00
if args.unlinked then
dfhack.job . linkIntoWorld ( args.job , true )
args.unlinked = false
end
2014-12-12 01:32:22 -07:00
addJobAction ( args.job , args.unit )
args.screen : wait_tick ( )
else
2015-09-14 09:54:02 -06:00
if not args.no_job_delete then
smart_job_delete ( args.job )
end
dfhack.gui . showAnnouncement ( " Job failed: " .. failed , 5 , 1 )
2014-12-12 01:32:22 -07:00
end
end )
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
2015-02-22 01:43:12 -07:00
args.job . general_refs : insert ( " # " , { new = df.general_ref_item , item_id = v.id } )
return
2013-06-14 01:20:36 -06:00
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.down ] = true
2015-09-19 03:18:30 -06:00
elseif pos.y < from_pos.y then
job.item_category [ dirs.up ] = true
2013-03-19 13:49:35 -06:00
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 " } ,
2015-02-03 15:04:12 -07:00
[ btype.AxleHorizontal ] = all , [ btype.WaterWheel ] = makeset { " d " } , [ btype.Rollers ] = makeset { " d " } }
2013-01-04 16:41:44 -07:00
local myneeds = needs [ args.type ]
if myneeds == nil then return end
if args.width == nil and myneeds.w then
--args.width=3
2015-09-09 13:30:00 -06:00
dialog.showInputPrompt ( " Building size: " , " Input building width: " , nil , " 1 " ,
2013-01-04 16:41:44 -07:00
function ( txt ) args.width = tonumber ( txt ) ; BuildingChosen ( args ) end )
return true
end
if args.height == nil and myneeds.h then
--args.height=4
2015-09-09 13:30:00 -06:00
dialog.showInputPrompt ( " Building size: " , " Input building height: " , nil , " 1 " ,
2013-01-04 16:41:44 -07:00
function ( txt ) args.height = tonumber ( txt ) ; BuildingChosen ( args ) end )
return true
end
if args.direction == nil and myneeds.d then
--args.direction=0--?
2015-09-09 13:30:00 -06:00
dialog.showInputPrompt ( " Building size: " , " Input building direction: " , nil , " 0 " ,
2013-01-04 16:41:44 -07:00
function ( txt ) args.direction = tonumber ( txt ) ; BuildingChosen ( args ) end )
return true
end
return false
--width = ..., height = ..., direction = ...
end
2014-12-12 01:32:22 -07:00
CheckAndFinishBuilding = nil
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 { }
2015-09-09 13:30:00 -06:00
2013-01-04 16:41:44 -07:00
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
2015-09-09 13:30:00 -06:00
2013-01-04 16:41:44 -07:00
if chooseBuildingWidthHeightDir ( args ) then
return
end
2012-11-29 15:02:03 -07:00
--if settings.build_by_items then
-- args.items=itemsAtPos(inp_args.from_pos)
--end
2014-12-12 01:32:22 -07:00
args.building = buildings.constructBuilding ( args )
CheckAndFinishBuilding ( args , args.building )
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
return false , " type "
elseif job_item.item_subtype ~=- 1 then
if item : getSubtype ( ) ~= job_item.item_subtype then
return false , " subtype "
end
end
end
2015-09-09 13:30:00 -06:00
2012-12-01 09:20:27 -07:00
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)
2015-09-16 05:05:29 -06:00
if job_item.flags1 . cookable and item : getType ( ) == df.item_type . FOOD then
return false , " already cooked "
end
2014-12-07 13:17:37 -07:00
2015-02-03 15:04:12 -07:00
if type ( job_item ) ~= " table " and 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
--]]
2015-02-03 15:04:12 -07:00
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
2015-02-03 15:04:12 -07:00
-- if #job_item.contains~=0 then
-- end
2012-12-01 09:20:27 -07:00
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)
2014-12-12 01:32:22 -07:00
print ( " moving: " , tostring ( v ) , tostring ( v.item ) )
printall ( v )
2014-12-08 13:19:22 -07:00
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
2014-12-12 01:32:22 -07:00
function finish_item_assign ( args )
local job = args.job
local item_modes = {
[ df.job_type . PlantSeeds ] = " haul " ,
2014-12-17 14:05:48 -07:00
[ df.job_type . Eat ] = " haul " ,
2014-12-12 01:32:22 -07:00
}
local item_mode = item_modes [ job.job_type ] or " teleport "
if settings.teleport_items and item_mode == " teleport " then
putItemsInBuilding ( args.building , job.items )
end
local uncollected = getItemsUncollected ( job )
if # uncollected == 0 then
job.flags . working = true
if item_mode == " haul " then
putItemsInHauling ( args.unit , job.items )
end
else
job.flags . fetching = true
uncollected [ 1 ] . is_fetching = 1
end
end
2015-02-03 15:04:12 -07:00
function EnumItems_with_settings ( args )
2014-12-07 13:17:37 -07:00
if settings.check_inv then
2015-02-03 15:04:12 -07:00
return EnumItems { pos = args.from_pos , unit = args.unit ,
2014-12-07 13:17:37 -07:00
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
2015-02-03 15:04:12 -07:00
return EnumItems { pos = args.from_pos }
2014-12-07 13:17:37 -07:00
end
2015-02-03 15:04:12 -07:00
end
function find_suitable_items ( job , items , job_items )
job_items = job_items or job.job_items
2014-12-08 13:19:22 -07:00
2012-12-03 12:49:17 -07:00
local item_counts = { }
2015-02-03 15:04:12 -07:00
for job_id , trg_job_item in ipairs ( job_items ) do
2012-12-03 12:49:17 -07:00
item_counts [ job_id ] = trg_job_item.quantity
end
2015-02-03 15:04:12 -07:00
2014-12-09 15:09:28 -07:00
local item_suitability = { }
2012-11-29 15:02:03 -07:00
local used_item_id = { }
2015-02-03 15:04:12 -07:00
for job_id , trg_job_item in ipairs ( job_items ) do
2014-12-09 15:09:28 -07:00
item_suitability [ job_id ] = { }
2015-09-09 13:30:00 -06:00
2015-09-09 13:33:46 -06:00
for _ , cur_item in pairs ( items ) do
2012-11-29 15:02:03 -07:00
if not used_item_id [ cur_item.id ] then
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 )
2015-09-16 05:05:29 -06:00
else
print ( cur_item , " ok " )
2014-12-07 13:17:37 -07:00
end
2014-12-12 01:32:22 -07:00
--]]
2015-09-09 13:33:46 -06:00
if not settings.gui_item_select then
2014-12-09 15:09:28 -07:00
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
2015-09-09 13:14:06 -06:00
2015-02-03 15:04:12 -07:00
return item_suitability , item_counts
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 = EnumItems_with_settings ( args )
local item_suitability , item_counts = find_suitable_items ( job , its )
--[[while(#job.items>0) do --clear old job items
job.items [ # job.items - 1 ] : delete ( )
job.items : erase ( # job.items - 1 )
end ] ]
2014-12-12 01:32:22 -07:00
if settings.gui_item_select and # job.job_items > 0 then
local item_dialog = require ( ' hack.scripts.gui.advfort_items ' )
2015-09-14 09:54:02 -06:00
if settings.quick then --TODO not so nice hack. instead of rewriting logic for job item filling i'm using one in gui dialog...
local item_editor = item_dialog.jobitemEditor {
job = job ,
items = item_suitability ,
}
if item_editor : jobValid ( ) then
item_editor : commit ( )
finish_item_assign ( args )
return true
else
return false , " Quick select items "
end
else
2014-12-12 01:32:22 -07:00
local ret = item_dialog.showItemEditor ( job , item_suitability )
if ret then
finish_item_assign ( args )
return true
else
print ( " Failed job, i'm confused... " )
end
2015-09-14 09:54:02 -06:00
--end)
return false , " Selecting items "
end
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
2014-12-12 01:32:22 -07:00
finish_item_assign ( args )
return true
2014-12-07 13:17:37 -07:00
end
2014-12-09 15:09:28 -07:00
2012-11-29 15:02:03 -07:00
end
2014-12-07 13:17:37 -07:00
2014-12-12 01:32:22 -07:00
CheckAndFinishBuilding = function ( 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
2015-09-14 09:54:02 -06:00
args.no_job_delete = true
2013-03-05 15:22:59 -07:00
break
end
end
2015-09-09 13:30:00 -06:00
2013-03-05 15:22:59 -07:00
if args.job ~= nil then
2014-12-12 01:32:22 -07:00
args.pre_actions = { AssignJobItems }
2013-03-05 15:22:59 -07:00
else
local t = { items = buildings.getFiltersByType ( { } , bld : getType ( ) , bld : getSubtype ( ) , bld : getCustomType ( ) ) }
2014-12-17 14:05:48 -07:00
args.pre_actions = { dfhack.curry ( setFiltersUp , t ) , AssignBuildingRef } --,AssignJobItems
2013-03-05 15:22:59 -07:00
end
2015-09-14 09:54:02 -06:00
args.no_job_delete = true
2014-12-12 01:32:22 -07:00
makeJob ( args )
2013-03-05 15:22:59 -07:00
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 )
2015-09-09 13:33:46 -06:00
local c_job = unit.job . current_job
2012-11-29 09:49:36 -07:00
if c_job then
2015-09-09 13:30:00 -06:00
unit.job . current_job = nil --todo add real cancelation
2012-12-01 09:20:27 -07:00
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 )
2015-09-09 13:30:00 -06:00
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
2015-09-09 13:14:06 -06:00
--TODO: in far far future maybe add real linking?
2015-02-03 15:04:12 -07:00
-- function assign_link_refs(args )
-- local job=args.job
-- --job.general_refs:insert("#",{new=df.general_ref_building_holderst,building_id=args.building.id})
-- job.general_refs:insert("#",{new=df.general_ref_building_triggertargetst,building_id=args.triggertarget.id})
-- printall(job)
-- end
-- function assign_link_roles( args )
-- if #args.job.items~=2 then
-- print("AAA FAILED!")
-- return false
-- end
-- args.job.items[0].role=df.job_item_ref.T_role.LinkToTarget
-- args.job.items[1].role=df.job_item_ref.T_role.LinkToTrigger
-- end
function fake_linking ( lever , building , slots )
local item1 = slots [ 1 ] . items [ 1 ]
local item2 = slots [ 2 ] . items [ 1 ]
if not dfhack.items . moveToBuilding ( item1 , lever , 2 ) then
qerror ( " failed to move item to building " )
end
if not dfhack.items . moveToBuilding ( item2 , building , 2 ) then
2015-09-09 13:33:46 -06:00
qerror ( " failed to move item2 to building " )
2015-02-03 15:04:12 -07:00
end
item2.general_refs : insert ( " # " , { new = df.general_ref_building_triggerst , building_id = lever.id } )
item1.general_refs : insert ( " # " , { new = df.general_ref_building_triggertargetst , building_id = building.id } )
lever.linked_mechanisms : insert ( " # " , item2 )
--fixes...
if building : getType ( ) == df.building_type . Door then
building.door_flags . operated_by_mechanisms = true
end
dfhack.gui . showAnnouncement ( " Linked! " , COLOR_YELLOW , true )
end
function LinkBuilding ( args )
local bld = args.building or dfhack.buildings . findAtTile ( args.pos )
args.building = bld
2012-12-01 09:20:27 -07:00
2015-02-03 15:04:12 -07:00
local lever_bld
if lever_id then --intentionally global!
lever_bld = df.building . find ( lever_id )
if lever_bld == nil then
lever_id = nil
end
end
2015-09-09 13:33:46 -06:00
if lever_bld == nil then
2015-02-03 15:04:12 -07:00
if bld : getType ( ) == df.building_type . Trap and bld : getSubtype ( ) == df.trap_type . Lever then
lever_id = bld.id
dfhack.gui . showAnnouncement ( " Selected lever for linking " , COLOR_YELLOW , true )
return
else
dfhack.gui . showAnnouncement ( " You first need a lever " , COLOR_RED , true )
end
else
if lever_bld == bld then
dfhack.gui . showAnnouncement ( " Invalid target " , COLOR_RED , true ) --todo more invalid targets
return
end
-- args.job_type=df.job_type.LinkBuildingToTrigger
-- args.building=lever_bld
-- args.triggertarget=bld
-- args.pre_actions={
-- dfhack.curry(setFiltersUp,{items={{quantity=1,item_type=df.item_type.TRAPPARTS},{quantity=1,item_type=df.item_type.TRAPPARTS}}}),
-- AssignJobItems,
-- assign_link_refs,}
-- args.post_actions={AssignBuildingRef,assign_link_roles}
-- makeJob(args)
local input_filter_defaults = { --stolen from buildings lua to better customize...
item_type = df.item_type . TRAPPARTS ,
item_subtype = - 1 ,
mat_type = - 1 ,
mat_index = - 1 ,
flags1 = { } ,
flags2 = { allow_artifact = true } ,
flags3 = { } ,
flags4 = 0 ,
flags5 = 0 ,
reaction_class = ' ' ,
has_material_reaction_product = ' ' ,
metal_ore = - 1 ,
min_dimension = - 1 ,
has_tool_use = - 1 ,
quantity = 1
}
local job_items = { copyall ( input_filter_defaults ) , copyall ( input_filter_defaults ) }
local its = EnumItems_with_settings ( args )
local suitability = find_suitable_items ( nil , its , job_items )
require ( ' hack.scripts.gui.advfort_items ' ) . jobitemEditor { items = suitability , job_items = job_items , on_okay = dfhack.curry ( fake_linking , lever_bld , bld ) } : show ( )
lever_id = nil
end
--one item as LinkToTrigger role
--one item as LinkToTarget
--genref for holder(lever)
--genref for triggertarget
end
2015-09-09 13:14:06 -06:00
--[[ Plant gathering attemped fix No. 35]] --[=[ still did not work!]=]
2015-02-22 01:43:12 -07:00
function get_design_block_ev ( blk )
for i , v in ipairs ( blk.block_events ) do
if v : getType ( ) == df.block_square_event_type . designation_priority then
return v
end
end
end
function PlantGatherFix ( args )
local pos = args.pos
2015-09-20 11:46:13 -06:00
--[[args.job.flags[17]=false --??
2015-02-22 01:43:12 -07:00
local block = dfhack.maps . getTileBlock ( pos )
local ev = get_design_block_ev ( block )
if ev == nil then
block.block_events : insert ( " # " , { new = df.block_square_event_designation_priorityst } )
ev = block.block_events [ # block.block_events - 1 ]
end
ev.priority [ pos.x % 16 ] [ pos.y % 16 ] = bit32.bor ( ev.priority [ pos.x % 16 ] [ pos.y % 16 ] , 4000 )
args.job . item_category : assign { furniture = true , corpses = true , ammo = true } --this is actually required in fort mode
2015-09-20 11:46:13 -06:00
] ]
local path = args.unit . path
path.dest = pos
path.goal = df.unit_path_goal . GatherPlant
path.path . x : insert ( " # " , pos.x )
path.path . y : insert ( " # " , pos.y )
path.path . z : insert ( " # " , pos.z )
printall ( path )
2015-02-22 01:43:12 -07:00
end
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 } } ,
2015-09-19 03:18:30 -06:00
{ " CarveTrack " , df.job_type . CarveTrack , { } --TODO: check this- carving modifies standing tile but depends on direction!
2015-09-09 13:30:00 -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}},
2015-09-09 13:33:46 -06:00
{ " TameAnimal " , df.job_type . TameAnimal , { IsUnit } , { SetCreatureRef } } ,
2015-02-22 01:43:12 -07:00
{ " GatherPlants " , df.job_type . GatherPlants , { IsPlant , SameSquare } , { PlantGatherFix } } ,
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 } } ,
2015-02-03 15:04:12 -07:00
{ " Link Buildings " , LinkBuilding , { IsBuilding } } ,
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 ]
2015-09-14 09:54:02 -06:00
local ret
2012-11-28 17:26:10 -07:00
if adv.job . current_job then
2015-09-14 09:54:02 -06:00
ret = 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
2015-09-14 09:54:02 -06:00
ret = actions [ ( mode or 0 ) + 1 ] [ 1 ] or " "
2012-11-28 17:26:10 -07:00
end
2015-09-14 09:54:02 -06:00
if settings.quick then
ret = ret .. " * "
end
return ret
2012-11-28 17:26:10 -07:00
end
2012-12-03 12:49:17 -07:00
2015-09-09 13:14:06 -06:00
function usetool : update_site ( )
local site = inSite ( )
self.current_site = site
local site_label = self.subviews . siteLabel
if site then
site_label : itemById ( " site " ) . text = dfhack.TranslateName ( site.name )
else
2015-09-10 05:38:44 -06:00
if settings.safe then
2015-09-09 13:14:06 -06:00
site_label : itemById ( " site " ) . text = " <none, advfort disabled> "
2015-09-10 05:38:44 -06:00
else
site_label : itemById ( " site " ) . text = " <none, changes will not persist> "
2015-09-09 13:14:06 -06:00
end
end
end
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 = {
2015-02-03 15:04:12 -07:00
{ id = " text1 " , gap = 1 , key = keybinds.workshop . key , key_sep = " () " , text = " Workshop menu " , pen = dfhack.pen . parse { fg = COLOR_YELLOW , bg = 0 } } , { id = " clutter " } }
2013-03-03 08:33:07 -07:00
} ,
2015-09-09 13:30:00 -06:00
2013-03-03 08:33:07 -07:00
wid.Label {
view_id = " siteLabel " ,
frame = { t = 1 , xalign =- 1 , yalign = 0 } ,
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
2015-09-09 13:14:06 -06:00
self : update_site ( )
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 }
2014-12-12 01:32:22 -07:00
makeJob ( args )
2012-12-01 09:20:27 -07:00
end
2015-01-26 13:35:46 -07:00
function siegeWeaponActionChosen ( args , actionid )
local building = args.building
2015-09-09 13:30:00 -06:00
if actionid == 1 then --Turn
2015-01-26 13:35:46 -07:00
building.facing = ( args.building . facing + 1 ) % 4
return
elseif actionid == 2 then --Load
2012-12-03 12:49:17 -07:00
local action = df.job_type . LoadBallista
if building : getSubtype ( ) == df.siegeengine_type . Catapult then
action = df.job_type . LoadCatapult
2015-01-26 13:35:46 -07:00
args.pre_actions = { dfhack.curry ( setFiltersUp , { items = { { quantity = 1 } } } ) , AssignJobItems } --TODO just boulders here
else
args.pre_actions = { dfhack.curry ( setFiltersUp , { items = { { quantity = 1 , item_type = df.SIEGEAMMO } } } ) , AssignJobItems }
2012-12-03 12:49:17 -07:00
end
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
2015-01-26 13:35:46 -07:00
elseif actionid == 3 then --Fire
2012-12-03 12:49:17 -07:00
local action = df.job_type . FireBallista
if building : getSubtype ( ) == df.siegeengine_type . Catapult then
action = df.job_type . FireCatapult
end
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
end
2015-01-26 13:35:46 -07:00
args.post_actions = { AssignBuildingRef }
makeJob ( args )
2012-12-03 12:49:17 -07:00
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 )
2015-01-26 13:35:46 -07:00
local args = { building = building , screen = self }
2013-01-04 16:41:44 -07:00
dialog.showListPrompt ( " Engine job choice " , " Choose what to do: " , COLOR_WHITE , { " Turn " , " Load " , " Fire " } ,
2015-01-26 13:35:46 -07:00
dfhack.curry ( siegeWeaponActionChosen , args ) )
2012-12-03 12:49:17 -07:00
end
2013-01-03 14:21:57 -07:00
function usetool : onWorkShopButtonClicked ( building , index , choice )
local adv = df.global . world.units . active [ 0 ]
2014-12-12 01:32:22 -07:00
local args = { unit = adv , building = building }
2013-01-03 14:21:57 -07:00
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 ]
2014-12-12 01:32:22 -07:00
args.job = job
args.pos = adv.pos
args.from_pos = adv.pos
args.pre_actions = { AssignJobItems }
args.screen = self
makeJob ( args )
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 ( )
2015-02-03 15:04:12 -07:00
2013-01-03 14:21:57 -07:00
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 ]
2015-02-03 15:04:12 -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
2015-01-13 01:30:53 -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
2015-09-20 11:46:13 -06:00
function track_stop_configure ( bld ) --TODO: dedicated widget with nice interface and current setting display
local dump_choices = {
{ text = " no dumping " } ,
{ text = " N " , x = 0 , y =- 1 } , --{t="NE",x=1,y=-1},
{ text = " E " , x = 1 , y = 0 } , --{t="SE",x=1,y=1},
{ text = " S " , x = 0 , y = 1 } , --{t="SW",x=-1,y=1},
{ text = " W " , x =- 1 , y = 0 } , --{t="NW",x=-1,y=-1}
}
local choices = { " Friction " , " Dumping " }
local function chosen ( index , choice )
if choice.text == " Friction " then
dialog.showInputPrompt ( " Choose friction " , " Friction " , nil , tostring ( bld.friction ) , function ( txt )
local num = tonumber ( txt ) --TODO allow only vanilla friction settings
if num then
2015-09-21 12:11:48 -06:00
bld.friction = num
2015-09-20 11:46:13 -06:00
end
end )
else
dialog.showListPrompt ( " Dumping direction " , " Choose dumping: " , COLOR_WHITE , dump_choices , function ( index , choice )
if choice.x then
bld.use_dump = 1 --??
bld.dump_x_shift = choice.x
bld.dump_y_shift = choice.y
else
bld.use_dump = 0
end
end )
end
end
dialog.showListPrompt ( " Track stop configure " , " Choose what to change: " , COLOR_WHITE , choices , chosen )
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 ,
] ]
2015-09-09 13:30:00 -06:00
if building.trap_type == df.trap_type . Lever then
2013-03-03 08:33:07 -07:00
--link
return
end
--building.trap_type==df.trap_type.PressurePlate then
--settings/link
2015-01-26 13:35:46 -07:00
local args = { unit = adv , post_actions = { AssignBuildingRef } , pos = adv.pos , from_pos = adv.pos ,
2014-12-07 15:55:46 -07:00
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 } } }
2015-01-26 13:35:46 -07:00
args.pre_actions = { dfhack.curry ( setFiltersUp , job_filter ) , AssignJobItems }
2013-02-04 22:21:44 -07:00
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 } } }
2015-01-26 13:35:46 -07:00
args.pre_actions = { dfhack.curry ( setFiltersUp , job_filter ) , AssignJobItems }
2015-09-20 11:46:13 -06:00
elseif building.trap_type == df.trap_type . TrackStop then
--set dump and friction
track_stop_configure ( building )
return
2013-02-04 22:21:44 -07:00
else
2015-09-20 11:46:13 -06:00
print ( " TODO: trap type: " .. df.trap_type [ building.trap_type ] )
2013-02-04 22:21:44 -07:00
return
end
2014-12-12 01:32:22 -07:00
args.screen = self
makeJob ( args )
2013-02-04 22:21:44 -07:00
end
end
function usetool : hiveActions ( building )
local adv = df.global . world.units . active [ 0 ]
2015-01-26 13:35:46 -07:00
local args = { unit = adv , post_actions = { AssignBuildingRef } , pos = adv.pos ,
2014-12-12 01:32:22 -07:00
from_pos = adv.pos , job_type = df.job_type . InstallColonyInHive , building = building , screen = self }
2013-02-04 22:21:44 -07:00
local job_filter = { items = { { quantity = 1 , item_type = df.item_type . VERMIN } } }
2015-01-26 13:35:46 -07:00
args.pre_actions = { dfhack.curry ( setFiltersUp , job_filter ) , AssignJobItems }
2014-12-12 01:32:22 -07:00
makeJob ( args )
2013-02-04 22:21:44 -07:00
--InstallColonyInHive,
--CollectHiveProducts,
end
function usetool : operatePump ( building )
2015-02-03 15:04:12 -07:00
2013-02-04 22:21:44 -07:00
local adv = df.global . world.units . active [ 0 ]
2014-12-12 01:32:22 -07:00
makeJob { unit = adv , post_actions = { AssignBuildingRef } , pos = adv.pos , from_pos = adv.pos , job_type = df.job_type . OperatePump , screen = self }
2013-02-04 22:21:44 -07:00
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
2015-02-03 15:04:12 -07:00
2014-12-12 01:32:22 -07:00
local args = { unit = adv , pos = adv.pos , from_pos = adv.pos , screen = self }
if do_harvest then
2013-01-04 16:41:44 -07:00
args.job_type = df.job_type . HarvestPlants
args.post_actions = { AssignBuildingRef }
2013-01-06 09:58:58 -07:00
else
2014-12-12 01:32:22 -07:00
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 , AssignJobItems }
2013-01-04 16:41:44 -07:00
end
2014-12-12 01:32:22 -07:00
makeJob ( args )
2013-01-04 16:41:44 -07:00
end
2014-12-17 14:05:48 -07:00
function usetool : bedActions ( building )
local adv = df.global . world.units . active [ 0 ]
local args = { unit = adv , pos = adv.pos , from_pos = adv.pos , screen = self , building = building ,
job_type = df.job_type . Sleep , post_actions = { AssignBuildingRef } }
makeJob ( args )
end
function usetool : chairActions ( building )
local adv = df.global . world.units . active [ 0 ]
local eatjob = { items = { { quantity = 1 , item_type = df.item_type . FOOD } } }
local args = { unit = adv , pos = adv.pos , from_pos = adv.pos , screen = self , job_type = df.job_type . Eat , building = building ,
pre_actions = { dfhack.curry ( setFiltersUp , eatjob ) , AssignJobItems } , post_actions = { AssignBuildingRef } }
makeJob ( args )
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 ,
2014-12-17 14:05:48 -07:00
} ,
[ df.building_type . Bed ] = {
name = " Rest " ,
input = usetool.bedActions ,
} ,
[ df.building_type . Chair ] = {
name = " Eat " ,
input = usetool.chairActions ,
} ,
2012-12-03 12:49:17 -07:00
}
2015-09-09 13:33:46 -06: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
2015-02-03 15:04:12 -07:00
if building : getClutterLevel ( ) <= 1 then
self.subviews . shopLabel : itemById ( " clutter " ) . text = " "
else
self.subviews . shopLabel : itemById ( " clutter " ) . text = " Clutter: " .. tostring ( building : getClutterLevel ( ) )
end
2013-03-03 08:33:07 -07:00
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
2014-12-12 01:32:22 -07:00
function usetool : wait_tick ( )
self : sendInputToParent ( " A_SHORT_WAIT " )
end
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
2015-09-09 13:14:06 -06:00
function usetool : siteCheck ( )
2015-09-10 05:38:44 -06:00
if self.site ~= nil or not settings.safe then --TODO: add check if it's correct site (the persistant ones)
2015-09-09 13:14:06 -06:00
return true
end
return false , " You are not on site "
end
--movement and co... Also passes on allowed keys
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
2015-09-09 13:14:06 -06:00
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 --do job in the distance, TODO: check if you can still cheat-mine (and co.) remotely
2012-12-01 09:20:27 -07:00
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
2015-02-03 15:04:12 -07:00
2015-09-09 13:14:06 -06:00
--First check site
local ok , msg = self : siteCheck ( ) --TODO: some jobs might be possible without a site?
if not ok then
dfhack.gui . showAnnouncement ( msg , 5 , 1 )
failed = true
else
for _ , p in pairs ( cur_mode [ 3 ] or { } ) do --then check predicates
local ok , msg = p ( state )
if not ok then
dfhack.gui . showAnnouncement ( msg , 5 , 1 )
failed = true
end
2012-12-01 09:20:27 -07:00
end
end
2015-02-03 15:04:12 -07:00
2012-12-01 09:20:27 -07:00
if not failed then
local ok , msg
if type ( cur_mode [ 2 ] ) == " function " then
ok , msg = cur_mode [ 2 ] ( state )
else
2014-12-12 01:32:22 -07:00
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])
2015-02-03 15:04:12 -07:00
2012-12-01 09:20:27 -07:00
end
2015-02-03 15:04:12 -07:00
2012-12-01 09:20:27 -07:00
if code == " SELECT " then
self : sendInputToParent ( " LEAVESCREEN " )
end
2014-12-12 01:32:22 -07:00
self.long_wait = true
2012-12-01 09:20:27 -07:00
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
2015-02-03 15:04:12 -07:00
2012-12-01 09:20:27 -07:00
end
2015-09-09 13:14:06 -06:00
2012-11-28 17:26:10 -07:00
function usetool : onInput ( keys )
2015-09-09 13:14:06 -06:00
self : update_site ( )
2012-11-29 09:49:36 -07:00
local adv = df.global . world.units . active [ 0 ]
2015-02-03 15:04:12 -07:00
2012-11-28 17:26:10 -07:00
if keys.LEAVESCREEN then
2015-09-09 13:14:06 -06:00
if df.global . cursor.x ~=- 30000 then --if not poiting at anything
self : sendInputToParent ( " LEAVESCREEN " ) --leave poiting
2012-11-29 09:33:04 -07:00
else
2015-09-09 13:14:06 -06:00
self : dismiss ( ) --leave the adv-tools all together
2012-11-29 09:49:36 -07:00
CancelJob ( adv )
2012-11-29 09:33:04 -07:00
end
2015-09-09 13:14:06 -06:00
elseif keys [ keybinds.nextJob . key ] then --next job with looping
2012-12-03 12:49:17 -07:00
mode = ( mode + 1 ) %# actions
2015-09-09 13:14:06 -06:00
elseif keys [ keybinds.prevJob . key ] then --prev job with looping
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
2014-11-30 12:46:46 -07:00
elseif keys [ " A_SHORT_WAIT " ] then
--ContinueJob(adv)
self : sendInputToParent ( " A_SHORT_WAIT " )
2015-09-14 09:54:02 -06:00
elseif keys [ keybinds.quick . key ] then
settings.quick = not settings.quick
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
2015-09-19 03:18:30 -06:00
self.long_wait_timer = nil
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
2015-09-09 13:30:00 -06:00
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
2015-02-03 15:04:12 -07:00
2012-11-28 17:26:10 -07:00
end
2015-09-19 03:18:30 -06:00
function usetool : cancel_wait ( )
self.long_wait_timer = nil
self.long_wait = false
end
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
2015-09-19 03:18:30 -06:00
--some heuristics for unsafe conditions
if self.long_wait and not settings.unsafe then --check if player wants for canceling to happen
local counters = adv.counters
local checked_counters = { pain = true , winded = true , stunned = true , unconscious = true , suffocation = true , webbed = true , nausea = true , dizziness = true }
for k , v in pairs ( checked_counters ) do
if counters [ k ] > 0 then
dfhack.gui . showAnnouncement ( " Job: canceled waiting because unsafe - " .. k , 5 , 1 )
self : cancel_wait ( )
2015-09-21 12:11:48 -06:00
return
2015-09-19 03:18:30 -06:00
end
end
end
2015-09-09 13:14:06 -06:00
if self.long_wait and self.long_wait_timer == nil then
self.long_wait_timer = 1000 --TODO tweak this
end
2014-12-08 13:19:22 -07:00
if job_ptr and self.long_wait and not job_action then
2015-09-09 13:14:06 -06:00
if self.long_wait_timer <= 0 then --fix deadlocks with force-canceling of waiting
2015-09-19 03:18:30 -06:00
self : cancel_wait ( )
return
2015-09-09 13:14:06 -06:00
else
self.long_wait_timer = self.long_wait_timer - 1
end
2014-12-08 13:19:22 -07:00
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
2015-01-13 01:30:53 -07:00
usetool ( ) : show ( )