@ -46,6 +46,11 @@ end
collectgarbage ( )
collectgarbage ( )
function prompt_proceed ( indent )
if not indent then indent = 0 end
return utils.prompt_yes_no ( string.rep ( ' ' , indent ) .. ' Proceed? ' , true )
end
print [ [
print [ [
WARNING : THIS SCRIPT IS STRICTLY FOR DFHACK DEVELOPERS .
WARNING : THIS SCRIPT IS STRICTLY FOR DFHACK DEVELOPERS .
@ -88,7 +93,7 @@ local searcher = ms.DiffSearcher.new(data)
local function get_screen ( class , prompt )
local function get_screen ( class , prompt )
if not is_known ( ' gview ' ) then
if not is_known ( ' gview ' ) then
print ( ' Please navigate to ' .. prompt )
print ( ' Please navigate to ' .. prompt )
if not utils.prompt_yes_no( ' Proceed? ' , true ) then
if not prompt_proceed( ) then
return nil
return nil
end
end
return true
return true
@ -98,7 +103,7 @@ local function get_screen(class, prompt)
local cs = dfhack.gui . getCurViewscreen ( true )
local cs = dfhack.gui . getCurViewscreen ( true )
if not df.is_instance ( class , cs ) then
if not df.is_instance ( class , cs ) then
print ( ' Please navigate to ' .. prompt )
print ( ' Please navigate to ' .. prompt )
if not utils.prompt_yes_no( ' Proceed? ' , true ) then
if not prompt_proceed( ) then
return nil
return nil
end
end
else
else
@ -172,8 +177,9 @@ local function exec_finder(finder, names, validators)
end
end
end
end
if search then
if search then
if not dfhack.safecall ( finder ) then
local ok , err = dfhack.safecall ( finder )
if not utils.prompt_yes_no ( ' Proceed with the rest of the script? ' ) then
if not ok then
if tostring ( err ) : find ( ' abort ' ) or not utils.prompt_yes_no ( ' Proceed with the rest of the script? ' ) then
searcher : reset ( )
searcher : reset ( )
qerror ( ' Quit ' )
qerror ( ' Quit ' )
end
end
@ -217,6 +223,7 @@ local function dwarfmode_feed_input(...)
if not df.isvalid ( screen ) then
if not df.isvalid ( screen ) then
qerror ( ' could not retrieve dwarfmode screen ' )
qerror ( ' could not retrieve dwarfmode screen ' )
end
end
try_save_cursor ( )
for _ , v in ipairs ( { ... } ) do
for _ , v in ipairs ( { ... } ) do
gui.simulateInput ( screen , v )
gui.simulateInput ( screen , v )
end
end
@ -259,9 +266,29 @@ local function dwarfmode_to_top()
return true
return true
end
end
local prev_cursor = df.global . T_cursor : new ( )
prev_cursor.x = - 30000
function try_save_cursor ( )
if not dfhack.internal . getAddress ( ' cursor ' ) then return end
for _ , v in pairs ( df.global . cursor ) do
if v < 0 then
return
end
end
prev_cursor : assign ( df.global . cursor )
end
function try_restore_cursor ( )
if not dfhack.internal . getAddress ( ' cursor ' ) then return end
if prev_cursor.x >= 0 then
df.global . cursor : assign ( prev_cursor )
dwarfmode_feed_input ( ' CURSOR_DOWN_Z ' , ' CURSOR_UP_Z ' )
end
end
local function feed_menu_choice ( catnames , catkeys , enum , enter_seq , exit_seq , prompt )
local function feed_menu_choice ( catnames , catkeys , enum , enter_seq , exit_seq , prompt )
return function ( idx )
return function ( idx )
if idx == 0 and prompt and not utils.prompt_yes_no ( ' Proceed? ' , true ) then
if idx == 0 and prompt and not prompt_proceed( 2 ) then
return false
return false
end
end
if idx > 0 then
if idx > 0 then
@ -305,7 +332,7 @@ local function feed_list_choice(count,upkey,downkey)
end
end
else
else
print ( ' Please select the first list item. ' )
print ( ' Please select the first list item. ' )
if not utils.prompt_yes_no( ' Proceed? ' , true ) then
if not prompt_proceed( 2 ) then
return false
return false
end
end
return true , 0
return true , 0
@ -316,14 +343,14 @@ end
local function feed_menu_bool ( enter_seq , exit_seq )
local function feed_menu_bool ( enter_seq , exit_seq )
return function ( idx )
return function ( idx )
if idx == 0 then
if idx == 0 then
if not utils.prompt_yes_no( ' Proceed? ' , true ) then
if not prompt_proceed( 2 ) then
return false
return false
end
end
return true , 0
return true , 0
end
end
if idx == 5 then
if idx == 5 then
print ( ' Please resize the game window. ' )
print ( ' Please resize the game window. ' )
if not utils.prompt_yes_no( ' Proceed? ' , true ) then
if not prompt_proceed( 2 ) then
return false
return false
end
end
end
end
@ -539,7 +566,7 @@ end
local function find_gps ( )
local function find_gps ( )
print ( ' \n Please ensure the mouse cursor is not over the game window. ' )
print ( ' \n Please ensure the mouse cursor is not over the game window. ' )
if not utils.prompt_yes_no( ' Proceed? ' , true ) then
if not prompt_proceed( ) then
return
return
end
end
@ -875,7 +902,23 @@ end
--
--
local function find_ui_menu_width ( )
local function find_ui_menu_width ( )
local addr = searcher : find_menu_cursor ( [ [
local addr
if dwarfmode_to_top ( ) then
addr = searcher : find_interactive ( ' Auto-searching for ui_menu_width ' , ' int8_t ' , function ( idx )
local val = ( idx % 3 ) + 1
if idx == 0 then
print ( ' Switch to the default [map][menu][map] layout (with Tab) ' )
if not prompt_proceed ( 2 ) then return false end
else
dwarfmode_feed_input ( ' CHANGETAB ' , val ~= 3 and ' CHANGETAB ' )
end
return true , val
end )
end
if not addr then
addr = searcher : find_menu_cursor ( [ [
Searching for ui_menu_width . Please exit to the main
Searching for ui_menu_width . Please exit to the main
dwarfmode menu , then use Tab to do as instructed below : ] ] ,
dwarfmode menu , then use Tab to do as instructed below : ] ] ,
' int8_t ' ,
' int8_t ' ,
@ -884,10 +927,16 @@ dwarfmode menu, then use Tab to do as instructed below:]],
[ 3 ] = ' hide the menu completely ' ,
[ 3 ] = ' hide the menu completely ' ,
[ 1 ] = ' switch to the default [map][menu][map] layout ' }
[ 1 ] = ' switch to the default [map][menu][map] layout ' }
)
)
end
ms.found_offset ( ' ui_menu_width ' , addr )
ms.found_offset ( ' ui_menu_width ' , addr )
-- NOTE: Assume that the vars are adjacent, as always
-- NOTE: Assume that the vars are adjacent, as always
ms.found_offset ( ' ui_area_map_width ' , addr + 1 )
ms.found_offset ( ' ui_area_map_width ' , addr + 1 )
-- reset to make sure view is small enough for window_x/y scan on small maps
df.global . ui_menu_width = 2
df.global . ui_area_map_width = 3
end
end
--
--
@ -1087,12 +1136,20 @@ local function find_ui_workshop_job_cursor()
if dwarfmode_to_top ( ) then
if dwarfmode_to_top ( ) then
dwarfmode_feed_input ( ' D_BUILDJOB ' )
dwarfmode_feed_input ( ' D_BUILDJOB ' )
addr = searcher : find_interactive ( [ [
addr = searcher : find_interactive ( [ [
Auto - searching for ui_workshop_job_cursor . Please highlight a
Auto - searching for ui_workshop_job_cursor . Please highlight a
workshop with at least 5 contained jobs , and select as instructed : ] ] ,
Mason ' s or Carpenter ' s workshop , or any building with a job
selection interface navigable with just " Enter " : ] ] ,
' int32_t ' ,
' int32_t ' ,
feed_list_choice ( workshop_job_list_count ) ,
function ( idx )
if idx == 0 then prompt_proceed ( 2 ) end
for i = 1 , 10 - workshop_job_list_count ( ) do
dwarfmode_feed_input ( ' BUILDJOB_ADD ' , ' SELECT ' , ' SELECT ' , ' SELECT ' , ' SELECT ' , ' SELECT ' )
end
dwarfmode_feed_input ( ' SECONDSCROLL_DOWN ' )
-- adding jobs resets the cursor position, so it is difficult to determine here
return true
end ,
20
20
)
)
end
end
@ -1119,6 +1176,7 @@ local function find_ui_building_in_assign()
if dwarfmode_to_top ( ) then
if dwarfmode_to_top ( ) then
dwarfmode_feed_input ( ' D_BUILDJOB ' )
dwarfmode_feed_input ( ' D_BUILDJOB ' )
try_restore_cursor ( )
addr = searcher : find_interactive ( [ [
addr = searcher : find_interactive ( [ [
Auto - searching for ui_building_in_assign . Please select a room ,
Auto - searching for ui_building_in_assign . Please select a room ,
@ -1160,6 +1218,7 @@ local function find_ui_building_in_resize()
if dwarfmode_to_top ( ) then
if dwarfmode_to_top ( ) then
dwarfmode_feed_input ( ' D_BUILDJOB ' )
dwarfmode_feed_input ( ' D_BUILDJOB ' )
try_restore_cursor ( )
addr = searcher : find_interactive ( [ [
addr = searcher : find_interactive ( [ [
Auto - searching for ui_building_in_resize . Please select a room ,
Auto - searching for ui_building_in_resize . Please select a room ,
@ -1396,7 +1455,7 @@ function step_n_frames(cnt, feed)
while world.frame_counter - ctick < cnt do
while world.frame_counter - ctick < cnt do
print ( " Please step the game " .. ( cnt - world.frame_counter + ctick ) .. more .. " frames. " )
print ( " Please step the game " .. ( cnt - world.frame_counter + ctick ) .. more .. " frames. " )
more = ' more '
more = ' more '
if not utils.prompt_yes_no( ' Proceed? ' , true ) then
if not prompt_proceed( 2 ) then
return nil
return nil
end
end
end
end
@ -1531,9 +1590,45 @@ end
local function find_process_jobs ( )
local function find_process_jobs ( )
local zone = get_process_zone ( ) or searcher
local zone = get_process_zone ( ) or searcher
local addr
stop_autosave ( )
stop_autosave ( )
if dwarfmode_to_top ( ) and dfhack.internal . getAddress ( ' cursor ' ) then
local cursor = df.global . T_cursor : new ( )
addr = zone : find_interactive ( [ [
Searching for process_jobs . Please position the cursor to the right
of at least 10 vacant natural floor tiles . ] ] ,
' int8_t ' ,
function ( idx )
if idx == 0 then
dwarfmode_feed_input ( ' D_LOOK ' )
if not prompt_proceed ( 2 ) then return false end
cursor : assign ( df.global . cursor )
elseif idx == 6 then
print ( ' Please resize the game window. ' )
if not prompt_proceed ( 2 ) then return false end
end
dwarfmode_to_top ( )
dwarfmode_step_frames ( 1 )
if idx % 2 == 0 then
dwarfmode_feed_input (
' D_BUILDING ' ,
' HOTKEY_BUILDING_CONSTRUCTION ' ,
' HOTKEY_BUILDING_CONSTRUCTION_WALL '
)
df.global . cursor : assign ( cursor )
df.global . cursor.x = df.global . cursor.x + ( idx / 2 )
dwarfmode_feed_input ( ' CURSOR_RIGHT ' , ' CURSOR_LEFT ' , ' SELECT ' , ' SELECT ' )
return true , 1
else
return true , 0
end
end ,
20 )
end
if not addr then
local addr = zone : find_menu_cursor ( [ [
local addr = zone : find_menu_cursor ( [ [
Searching for process_jobs . Please do as instructed below : ] ] ,
Searching for process_jobs . Please do as instructed below : ] ] ,
' int8_t ' ,
' int8_t ' ,
@ -1541,6 +1636,7 @@ Searching for process_jobs. Please do as instructed below:]],
{ [ 1 ] = ' designate a building to be constructed, e.g a bed or a wall ' ,
{ [ 1 ] = ' designate a building to be constructed, e.g a bed or a wall ' ,
[ 0 ] = ' step or unpause the game to reset the flag ' }
[ 0 ] = ' step or unpause the game to reset the flag ' }
)
)
end
ms.found_offset ( ' process_jobs ' , addr )
ms.found_offset ( ' process_jobs ' , addr )
end
end
@ -1550,16 +1646,49 @@ end
local function find_process_dig ( )
local function find_process_dig ( )
local zone = get_process_zone ( ) or searcher
local zone = get_process_zone ( ) or searcher
local addr
stop_autosave ( )
stop_autosave ( )
local addr = zone : find_menu_cursor ( [ [
if dwarfmode_to_top ( ) and dfhack.internal . getAddress ( ' cursor ' ) then
local cursor = df.global . T_cursor : new ( )
addr = zone : find_interactive ( [ [
Searching for process_dig . Please position the cursor to the right
of at least 10 unmined , unrevealed tiles . ] ] ,
' int8_t ' ,
function ( idx )
if idx == 0 then
dwarfmode_feed_input ( ' D_LOOK ' )
if not prompt_proceed ( 2 ) then return false end
cursor : assign ( df.global . cursor )
elseif idx == 6 then
print ( ' Please resize the game window. ' )
if not prompt_proceed ( 2 ) then return false end
end
dwarfmode_to_top ( )
dwarfmode_step_frames ( 1 )
if idx % 2 == 0 then
dwarfmode_feed_input ( ' D_DESIGNATE ' , ' DESIGNATE_DIG ' )
df.global . cursor : assign ( cursor )
df.global . cursor.x = df.global . cursor.x + ( idx / 2 )
dwarfmode_feed_input ( ' SELECT ' , ' SELECT ' )
return true , 1
else
return true , 0
end
end ,
20 )
end
if not addr then
addr = zone : find_menu_cursor ( [ [
Searching for process_dig . Please do as instructed below : ] ] ,
Searching for process_dig . Please do as instructed below : ] ] ,
' int8_t ' ,
' int8_t ' ,
{ 1 , 0 } ,
{ 1 , 0 } ,
{ [ 1 ] = ' designate a tile to be mined out ' ,
{ [ 1 ] = ' designate a tile to be mined out ' ,
[ 0 ] = ' step or unpause the game to reset the flag ' }
[ 0 ] = ' step or unpause the game to reset the flag ' }
)
)
end
ms.found_offset ( ' process_dig ' , addr )
ms.found_offset ( ' process_dig ' , addr )
end
end
@ -1671,7 +1800,7 @@ exec_finder(find_gps, 'gps', is_valid_gps)
print ( ' \n Compound globals (need loaded world): \n ' )
print ( ' \n Compound globals (need loaded world): \n ' )
print ( ' \n Please load the save previously processed with prepare-save. ' )
print ( ' \n Please load the save previously processed with prepare-save. ' )
if not utils.prompt_yes_no( ' Proceed? ' , true ) then
if not prompt_proceed( ) then
searcher : reset ( )
searcher : reset ( )
return
return
end
end