find-offsets: automate several more scans and aid in cursor positioning

- ui_menu_width (and ui_area_map_width)
- ui_workshop_job_cursor
- process_jobs
- process_dig

Also attempt to maintain cursor position between ui_building_in_assign and
ui_building_in_resize scans
develop
lethosor 2016-03-25 22:12:25 -04:00
parent b8bbf5f545
commit b888dbf25e
1 changed files with 162 additions and 33 deletions

@ -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('\nPlease ensure the mouse cursor is not over the game window.') print('\nPlease 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('\nCompound globals (need loaded world):\n') print('\nCompound globals (need loaded world):\n')
print('\nPlease load the save previously processed with prepare-save.') print('\nPlease 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