From 3a522768a2d16d9cd3a0bfcf53f1c877450d4bdd Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Wed, 3 Oct 2012 19:07:04 +0400 Subject: [PATCH] Implement feed-based finders for the remaining applicable globals. --- scripts/devel/find-offsets.lua | 373 +++++++++++++++++++++++++++------ 1 file changed, 304 insertions(+), 69 deletions(-) diff --git a/scripts/devel/find-offsets.lua b/scripts/devel/find-offsets.lua index 45f59e154..2f7f1287c 100644 --- a/scripts/devel/find-offsets.lua +++ b/scripts/devel/find-offsets.lua @@ -180,6 +180,21 @@ local function dwarfmode_feed_input(...) end end +local function dwarfmode_step_frames(count) + local screen = screen_dwarfmode() + if not df.isvalid(screen) then + qerror('could not retrieve dwarfmode screen') + end + + for i = 1,(count or 1) do + gui.simulateInput(screen, 'D_ONESTEP') + if screen.keyRepeat ~= 1 then + qerror('Could not step one frame: . did not work') + end + screen:logic() + end +end + local function dwarfmode_to_top() if not can_feed() then return false @@ -241,9 +256,33 @@ local function feed_list_choice(count,upkey,downkey) end else print(' Please select the first list item.') - if not utils.prompt_yes_no(' Proceed?') then + if not utils.prompt_yes_no(' Proceed?', true) then + return false + end + return true, 0 + end + end +end + +local function feed_menu_bool(enter_seq, exit_seq) + return function(idx) + if idx == 0 then + if not utils.prompt_yes_no(' Proceed?', true) then + return false + end + return true, 0 + end + if idx == 5 then + print(' Please resize the game window.') + if not utils.prompt_yes_no(' Proceed?', true) then return false end + end + if idx%2 == 1 then + dwarfmode_feed_input(table.unpack(enter_seq)) + return true, 1 + else + dwarfmode_feed_input(table.unpack(exit_seq)) return true, 0 end end @@ -880,14 +919,32 @@ local function building_item_list_count() end local function find_ui_building_item_cursor() - local addr = searcher:find_menu_cursor([[ + local addr + + if dwarfmode_to_top() then + dwarfmode_feed_input('D_BUILDITEM') + + addr = searcher:find_interactive([[ +Auto-searching for ui_building_item_cursor. Please highlight a +workshop, trade depot or other building with at least 5 contained +items, and select as instructed:]], + 'int32_t', + feed_list_choice(building_item_list_count), + 20 + ) + end + + if not addr then + addr = searcher:find_menu_cursor([[ Searching for ui_building_item_cursor. Please activate the 't' mode, find a cluttered workshop, trade depot, or other building with many contained items, and select as instructed:]], - 'int32_t', - list_index_choices(building_item_list_count), - ordinal_names - ) + 'int32_t', + list_index_choices(building_item_list_count), + ordinal_names + ) + end + ms.found_offset('ui_building_item_cursor', addr) end @@ -896,17 +953,37 @@ end -- local function find_ui_workshop_in_add() - local addr = searcher:find_menu_cursor([[ + local addr + + if dwarfmode_to_top() then + dwarfmode_feed_input('D_BUILDJOB') + + addr = searcher:find_interactive([[ +Auto-searching for ui_workshop_in_add. Please select a +workshop, e.g. Carpenters or Masons.]], + 'int8_t', + feed_menu_bool( + { 'BUILDJOB_CANCEL', 'BUILDJOB_ADD' }, + { 'SELECT', 'SELECT', 'SELECT', 'SELECT', 'SELECT' } + ), + 20 + ) + end + + if not addr then + addr = searcher:find_menu_cursor([[ Searching for ui_workshop_in_add. Please activate the 'q' mode, find a workshop without jobs (or delete jobs), and do as instructed below. NOTE: If not done after first 3-4 steps, resize the game window.]], - 'int8_t', - { 1, 0 }, - { [1] = 'enter the add job menu', - [0] = 'add job, thus exiting the menu' } - ) + 'int8_t', + { 1, 0 }, + { [1] = 'enter the add job menu', + [0] = 'add job, thus exiting the menu' } + ) + end + ms.found_offset('ui_workshop_in_add', addr) end @@ -919,13 +996,30 @@ local function workshop_job_list_count() end local function find_ui_workshop_job_cursor() - local addr = searcher:find_menu_cursor([[ + local addr + + if dwarfmode_to_top() then + dwarfmode_feed_input('D_BUILDJOB') + + addr = searcher:find_interactive([[ +Auto-searching for ui_workshop_job_cursor. Please highlight a +workshop with at least 5 contained jobs, and select as instructed:]], + 'int32_t', + feed_list_choice(workshop_job_list_count), + 20 + ) + end + + if not addr then + addr = searcher:find_menu_cursor([[ Searching for ui_workshop_job_cursor. Please activate the 'q' mode, find a workshop with many jobs, and select as instructed:]], - 'int32_t', - list_index_choices(workshop_job_list_count), - ordinal_names - ) + 'int32_t', + list_index_choices(workshop_job_list_count), + ordinal_names + ) + end + ms.found_offset('ui_workshop_job_cursor', addr) end @@ -934,17 +1028,39 @@ end -- local function find_ui_building_in_assign() - local addr = searcher:find_menu_cursor([[ + local addr + + if dwarfmode_to_top() then + dwarfmode_feed_input('D_BUILDJOB') + + addr = searcher:find_interactive([[ +Auto-searching for ui_building_in_assign. Please select a room, +i.e. a bedroom, tomb, office, dining room or statue garden.]], + 'int8_t', + feed_menu_bool( + { { 'BUILDJOB_STATUE_ASSIGN', 'BUILDJOB_COFFIN_ASSIGN', + 'BUILDJOB_CHAIR_ASSIGN', 'BUILDJOB_TABLE_ASSIGN', + 'BUILDJOB_BED_ASSIGN' } }, + { 'LEAVESCREEN' } + ), + 20 + ) + end + + if not addr then + addr = searcher:find_menu_cursor([[ Searching for ui_building_in_assign. Please activate the 'q' mode, select a room building (e.g. a bedroom) and do as instructed below. NOTE: If not done after first 3-4 steps, resize the game window.]], - 'int8_t', - { 1, 0 }, - { [1] = 'enter the Assign owner menu', - [0] = 'press Esc to exit assign' } - ) + 'int8_t', + { 1, 0 }, + { [1] = 'enter the Assign owner menu', + [0] = 'press Esc to exit assign' } + ) + end + ms.found_offset('ui_building_in_assign', addr) end @@ -953,17 +1069,39 @@ end -- local function find_ui_building_in_resize() - local addr = searcher:find_menu_cursor([[ + local addr + + if dwarfmode_to_top() then + dwarfmode_feed_input('D_BUILDJOB') + + addr = searcher:find_interactive([[ +Auto-searching for ui_building_in_resize. Please select a room, +i.e. a bedroom, tomb, office, dining room or statue garden.]], + 'int8_t', + feed_menu_bool( + { { 'BUILDJOB_STATUE_SIZE', 'BUILDJOB_COFFIN_SIZE', + 'BUILDJOB_CHAIR_SIZE', 'BUILDJOB_TABLE_SIZE', + 'BUILDJOB_BED_SIZE' } }, + { 'LEAVESCREEN' } + ), + 20 + ) + end + + if not addr then + addr = searcher:find_menu_cursor([[ Searching for ui_building_in_resize. Please activate the 'q' mode, select a room building (e.g. a bedroom) and do as instructed below. NOTE: If not done after first 3-4 steps, resize the game window.]], - 'int8_t', - { 1, 0 }, - { [1] = 'enter the Resize room mode', - [0] = 'press Esc to exit resize' } - ) + 'int8_t', + { 1, 0 }, + { [1] = 'enter the Resize room mode', + [0] = 'press Esc to exit resize' } + ) + end + ms.found_offset('ui_building_in_resize', addr) end @@ -971,13 +1109,40 @@ end -- window_x -- +local function feed_window_xyz(dec,inc,step) + return function(idx) + if idx == 0 then + for i = 1,30 do dwarfmode_feed_input(dec) end + else + dwarfmode_feed_input(inc) + end + return true, nil, step + end +end + local function find_window_x() - local addr = searcher:find_counter([[ + local addr + + if dwarfmode_to_top() then + addr = searcher:find_interactive( + 'Auto-searching for window_x.', + 'int32_t', + feed_window_xyz('CURSOR_LEFT_FAST', 'CURSOR_RIGHT', 10), + 20 + ) + + dwarfmode_feed_input('D_HOTKEY1') + end + + if not addr then + addr = searcher:find_counter([[ Searching for window_x. Please exit to main dwarfmode menu, scroll to the LEFT edge, then do as instructed:]], - 'int32_t', 10, - 'Please press Right to scroll right one step.' - ) + 'int32_t', 10, + 'Please press Right to scroll right one step.' + ) + end + ms.found_offset('window_x', addr) end @@ -986,12 +1151,28 @@ end -- local function find_window_y() - local addr = searcher:find_counter([[ + local addr + + if dwarfmode_to_top() then + addr = searcher:find_interactive( + 'Auto-searching for window_y.', + 'int32_t', + feed_window_xyz('CURSOR_UP_FAST', 'CURSOR_DOWN', 10), + 20 + ) + + dwarfmode_feed_input('D_HOTKEY1') + end + + if not addr then + addr = searcher:find_counter([[ Searching for window_y. Please exit to main dwarfmode menu, scroll to the TOP edge, then do as instructed:]], - 'int32_t', 10, - 'Please press Down to scroll down one step.' - ) + 'int32_t', 10, + 'Please press Down to scroll down one step.' + ) + end + ms.found_offset('window_y', addr) end @@ -1000,14 +1181,30 @@ end -- local function find_window_z() - local addr = searcher:find_counter([[ + local addr + + if dwarfmode_to_top() then + addr = searcher:find_interactive( + 'Auto-searching for window_z.', + 'int32_t', + feed_window_xyz('CURSOR_UP_Z', 'CURSOR_DOWN_Z', -1), + 30 + ) + + dwarfmode_feed_input('D_HOTKEY1') + end + + if not addr then + addr = searcher:find_counter([[ Searching for window_z. Please exit to main dwarfmode menu, scroll to a Z level near surface, then do as instructed below. NOTE: If not done after first 3-4 steps, resize the game window.]], - 'int32_t', -1, - "Please press '>' to scroll one Z level down." - ) + 'int32_t', -1, + "Please press '>' to scroll one Z level down." + ) + end + ms.found_offset('window_z', addr) end @@ -1056,6 +1253,27 @@ function stop_autosave() end end +function step_n_frames(cnt, feed) + local world = df.global.world + local ctick = world.frame_counter + + if feed then + print(" Auto-stepping "..cnt.." frames.") + dwarfmode_step_frames(cnt) + return world.frame_counter-ctick + end + + local more = '' + while world.frame_counter-ctick < cnt do + print(" Please step the game "..(cnt-world.frame_counter+ctick)..more.." frames.") + more = ' more' + if not utils.prompt_yes_no(' Proceed?', true) then + return nil + end + end + return world.frame_counter-ctick +end + local function find_cur_year_tick() local zone if os_type == 'windows' then @@ -1070,12 +1288,21 @@ local function find_cur_year_tick() stop_autosave() - local addr = zone:find_counter([[ -Searching for cur_year_tick. Please exit to main dwarfmode -menu, then do as instructed below:]], - 'int32_t', 1, - "Please press '.' to step the game one frame." + local feed = dwarfmode_to_top() + local addr = zone:find_interactive( + 'Searching for cur_year_tick.', + 'int32_t', + function(idx) + if idx > 0 then + if not step_n_frames(1, feed) then + return false + end + end + return true, nil, 1 + end, + 20 ) + ms.found_offset('cur_year_tick', addr) end @@ -1083,20 +1310,6 @@ end -- cur_season_tick -- -function step_n_frames(cnt) - local world = df.global.world - local ctick = world.frame_counter - local more = '' - while world.frame_counter-ctick < cnt do - print(" Please step the game "..(cnt-world.frame_counter+ctick)..more.." frames.") - more = ' more' - if not utils.prompt_yes_no(' Done?', true) then - return nil - end - end - return world.frame_counter-ctick -end - local function find_cur_season_tick() if not (is_known 'cur_year_tick') then dfhack.printerr('Cannot search for cur_season_tick - prerequisites missing.') @@ -1105,13 +1318,14 @@ local function find_cur_season_tick() stop_autosave() + local feed = dwarfmode_to_top() local addr = searcher:find_interactive([[ Searching for cur_season_tick. Please exit to main dwarfmode menu, then do as instructed below:]], 'int32_t', function(ccursor) if ccursor > 0 then - if not step_n_frames(10) then + if not step_n_frames(10, feed) then return false end end @@ -1133,6 +1347,7 @@ local function find_cur_season() stop_autosave() + local feed = dwarfmode_to_top() local addr = searcher:find_interactive([[ Searching for cur_season. Please exit to main dwarfmode menu, then do as instructed below:]], @@ -1142,7 +1357,7 @@ menu, then do as instructed below:]], local cst = df.global.cur_season_tick df.global.cur_season_tick = 10079 df.global.cur_year_tick = df.global.cur_year_tick + (10079-cst)*10 - if not step_n_frames(10) then + if not step_n_frames(10, feed) then return false end end @@ -1203,7 +1418,7 @@ end -- local function find_pause_state() - local zone + local zone, addr if os_type == 'linux' or os_type == 'darwin' then zone = zoomed_searcher('ui_look_cursor', 32) elseif os_type == 'windows' then @@ -1213,13 +1428,33 @@ local function find_pause_state() stop_autosave() - local addr = zone:find_menu_cursor([[ + if dwarfmode_to_top() then + addr = zone:find_interactive( + 'Auto-searching for pause_state', + 'int8_t', + function(idx) + if idx%2 == 0 then + dwarfmode_feed_input('D_ONESTEP') + return true, 0 + else + screen_dwarfmode():logic() + return true, 1 + end + end, + 20 + ) + end + + if not addr then + addr = zone:find_menu_cursor([[ Searching for pause_state. Please do as instructed below:]], - 'int8_t', - { 1, 0 }, - { [1] = 'PAUSE the game', - [0] = 'UNPAUSE the game' } - ) + 'int8_t', + { 1, 0 }, + { [1] = 'PAUSE the game', + [0] = 'UNPAUSE the game' } + ) + end + ms.found_offset('pause_state', addr) end