diff --git a/changelog.txt b/changelog.txt index d2c106622e..4965da0d76 100644 --- a/changelog.txt +++ b/changelog.txt @@ -35,12 +35,14 @@ Template for new versions: - `advtools`: new ``advtools.fastcombat`` overlay (enabled by default) allows you to skip combat animations and the announcement "More" button by mashing the movement keys ## Fixes +- `position`: support for adv mode look cursor ## Misc Improvements - `hide-tutorials`: handle tutorial popups for adventure mode - `hide-tutorials`: new ``reset`` command that will re-enable popups in the current game (in case you hid them all and now want them back) - `gui/notify`: moody dwarf notification turns red when they can't reach workshop or items - `gui/confirm`: in the delete manager order confirmation dialog, show a description of which order you have selected to delete +- `position`: display both adventurer and site pos simultaneously. Display map block pos+offset of selected tile. ## Removed diff --git a/docs/position.rst b/docs/position.rst index 9d06d39618..56be5993c7 100644 --- a/docs/position.rst +++ b/docs/position.rst @@ -8,7 +8,7 @@ position This tool reports the current date, clock time, month, season, and historical era. It also reports the keyboard cursor position (or just the z-level if no active cursor), window size, and mouse location on the screen. If a site is -loaded, it prints the world coordinates of the site. If not, it prints the world +loaded, it prints the world coordinates of the site. It also prints the world coordinates of the adventurer (if applicable). Can also be used to copy the current keyboard cursor position for later use. diff --git a/position.lua b/position.lua index de6248f62f..094211fb29 100644 --- a/position.lua +++ b/position.lua @@ -1,20 +1,25 @@ +-- Report cursor and mouse position, along with other info. +--@ module = true -local cursor = df.global.cursor -local args = {...} -if #args > 0 then --Copy keyboard cursor to clipboard - if #args > 1 then - qerror('Too many arguments!') - elseif args[1] ~= '-c' and args[1] ~= '--copy' then - qerror('Invalid argument "'..args[1]..'"!') - elseif cursor.x < 0 then - qerror('No keyboard cursor!') +local argparse = require('argparse') +local guidm = require('gui.dwarfmode') + +local function parse_args(args) + local opts = {} + local positionals = argparse.processArgsGetopt(args, + { + {'c', 'copy', handler=function() opts.copy = true end}, + }) + + if #positionals > 0 then + qerror('Too many positionals!') end - dfhack.internal.setClipboardTextCp437(('%d,%d,%d'):format(cursor.x, cursor.y, cursor.z)) - return + return opts end -local months = { +local months = +{ 'Granite, in early Spring.', 'Slate, in mid Spring.', 'Felsite, in late Spring.', @@ -29,68 +34,102 @@ local months = { 'Obsidian, in late Winter.', } ---Fortress mode counts 1200 ticks per day and 403200 per year ---Adventurer mode counts 86400 ticks to a day and 29030400 ticks per year ---Twelve months per year, 28 days to every month, 336 days per year +function print_time_info() + --Fortress mode counts 1200 ticks per day and 403200 per year + --Adventurer mode counts 86400 ticks to a day and 29030400 ticks per year + --Twelve months per year, 28 days to every month, 336 days per year + local julian_day = df.global.cur_year_tick // 1200 + 1 + local month = julian_day // 28 + 1 --days and months are 1-indexed + local day = julian_day % 28 -local julian_day = df.global.cur_year_tick // 1200 + 1 -local month = julian_day // 28 + 1 --days and months are 1-indexed -local day = julian_day % 28 + local time_of_day = df.global.cur_year_tick_advmode // 336 + local second = time_of_day % 60 + local minute = time_of_day // 60 % 60 + local hour = time_of_day // 3600 % 24 -local time_of_day = df.global.cur_year_tick_advmode // 336 -local second = time_of_day % 60 -local minute = time_of_day // 60 % 60 -local hour = time_of_day // 3600 % 24 + print('Time:') + print((' The time is %02d:%02d:%02d'):format(hour, minute, second)) + print((' The date is %03d-%02d-%02d'):format(df.global.cur_year, month, day)) + print(' It is the month of '..months[month]) -print('Time:') -print((' The time is %02d:%02d:%02d'):format(hour, minute, second)) -print((' The date is %03d-%02d-%02d'):format(df.global.cur_year, month, day)) -print(' It is the month of '..months[month]) + local eras = df.global.world.history.eras + if #eras > 0 then + print(' It is the '..eras[#eras-1].title.name..'.') + end +end -local eras = df.global.world.history.eras -if #eras > 0 then - print(' It is the '..eras[#eras-1].title.name..'.') +function get_adv_region_pos() --Regional coords + if not dfhack.world.getAdventurer() then --Army exists when unit doesn't + local army = df.army.find(df.global.adventure.player_army_id) + if army then + return army.pos.x//48, army.pos.y//48 + end + end + local wd = df.global.world.world_data + return wd.midmap_data.adv_region_x, wd.midmap_data.adv_region_y end -print('Place:') -print(' The z-level is z='..df.global.window_z) +local function print_world_info() + local wd = df.global.world.world_data + local site = dfhack.world.getCurrentSite() + if site then + print((' The current site is at x=%d, y=%d on the %dx%d world map.'): + format(site.pos.x, site.pos.y, wd.world_width, wd.world_height)) + end -if cursor.x < 0 then - print(' The keyboard cursor is inactive.') -else - print(' The keyboard cursor is at x='..cursor.x..', y='..cursor.y) + if dfhack.world.isAdventureMode() then + local x, y = get_adv_region_pos() + print((' The adventurer is at x=%d, y=%d on the %dx%d world map.'): + format(x, y, wd.world_width, wd.world_height)) + end end -local x, y = dfhack.screen.getWindowSize() -print(' The window is '..x..' tiles wide and '..y..' tiles high.') +function print_place_info(cursor) + print('Place:') + print(' The z-level is z='..df.global.window_z) -x, y = dfhack.screen.getMousePos() -if x then - print(' The mouse is at x='..x..', y='..y..' within the window.') - local pos = dfhack.gui.getMousePos() - if pos then - print(' The mouse is over map tile x='..pos.x..', y='..pos.y) + if cursor then + local x, y = cursor.x, cursor.y + print((' The keyboard cursor is at x=%d, y=%d (%d+%d, %d+%d)'): + format(x, y, x//16*16, x%16, y//16*16, y%16)) + else + print(' The keyboard cursor is inactive.') end -else - print(' The mouse is not in the DF window.') -end -local wd = df.global.world.world_data -local site = dfhack.world.getCurrentSite() -if site then - print((' The current site is at x=%d, y=%d on the %dx%d world map.'): - format(site.pos.x, site.pos.y, wd.world_width, wd.world_height)) -elseif dfhack.world.isAdventureMode() then - x, y = -1, -1 - for _,army in ipairs(df.global.world.armies.all) do - if army.flags.player then - x, y = army.pos.x // 48, army.pos.y // 48 - break + local x, y = dfhack.screen.getWindowSize() + print(' The window is '..x..' tiles wide and '..y..' tiles high.') + + x, y = dfhack.screen.getMousePos() + if x then + print(' The mouse is at x='..x..', y='..y..' within the window.') + local pos = dfhack.gui.getMousePos() + if pos then + print(' The mouse is over map tile x='..pos.x..', y='..pos.y) end + else + print(' The mouse is not in the DF window.') end - if x < 0 then - x, y = wd.midmap_data.adv_region_x, wd.midmap_data.adv_region_y + + print_world_info() +end + +if dfhack_flags.module then + return +end + +function main(opts) + local cursor = guidm.getCursorPos() + + if opts.copy then --Copy keyboard cursor to clipboard + if not cursor then + qerror('No keyboard cursor!') + end + dfhack.internal.setClipboardTextCp437(('%d,%d,%d'):format(cursor.x, cursor.y, cursor.z)) + return --Don't print anything end - print((' The adventurer is at x=%d, y=%d on the %dx%d world map.'): - format(x, y, wd.world_width, wd.world_height)) + + print_time_info() + print_place_info(cursor) end + +main(parse_args({...}))