From 962b4b31f5e0af35633064b83eb6c5c3a2bc4906 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Thu, 30 Jan 2025 14:13:26 -0800 Subject: [PATCH 1/6] Update position.lua * Make it a module * Use argparse * Adventure mode cursor support * Give mod16 offset for cursor * Improve code --- position.lua | 172 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 111 insertions(+), 61 deletions(-) diff --git a/position.lua b/position.lua index de6248f62f..66404dd500 100644 --- a/position.lua +++ b/position.lua @@ -1,20 +1,36 @@ +-- Detailed info about time and place. Can also copy keyboard cursor position. +--@ 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 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 + +function get_active_cursor() --Return active fort/adv cursor or nil + if dfhack.world.isAdventureMode() then + local look = df.global.game.main_interface.adventure.look + if look.open and look.cursor:isValid() then + return look.cursor --Note: This is a df.coord + end + elseif df.global.cursor.x >= 0 then + return df.global.cursor + end + return nil --Not active end -local months = { +local months = +{ 'Granite, in early Spring.', 'Slate, in mid Spring.', 'Felsite, in late Spring.', @@ -29,68 +45,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 = get_active_cursor() + + 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({...})) From 02d87db0f9033d728779febfb4d499f498d638d9 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Thu, 30 Jan 2025 14:19:04 -0800 Subject: [PATCH 2/6] Update position.lua --- position.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/position.lua b/position.lua index 66404dd500..49cf1f3526 100644 --- a/position.lua +++ b/position.lua @@ -1,4 +1,4 @@ --- Detailed info about time and place. Can also copy keyboard cursor position. +-- Report cursor and mouse position, along with other info. --@ module = true local argparse = require('argparse') From c5658cdfe09e29c236976245fc5081e6c3b9c943 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Thu, 30 Jan 2025 14:21:26 -0800 Subject: [PATCH 3/6] Update position.rst --- docs/position.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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. From 11f749b42cf868c405e0a8c0c78a806d95b3c54b Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Thu, 30 Jan 2025 14:24:16 -0800 Subject: [PATCH 4/6] Update changelog.txt --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 6c8f0dd35e..ea40f1ddfe 100644 --- a/changelog.txt +++ b/changelog.txt @@ -34,6 +34,7 @@ Template for new versions: ## Fixes - `advtools`: fix dfhack-added conversation options not appearing in the ask whereabouts conversation tree - `gui/rename`: fix error when changing the language of a unit's name +- `position`: support for adv mode look cursor ## Misc Improvements - `assign-preferences`: new ``--show`` option to display the preferences of the selected unit From c68a310da8424bad015fc17106d9a1f4996bdba0 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 11 Feb 2025 00:10:18 -0800 Subject: [PATCH 5/6] Update position.lua - Use guidm cursor fn --- position.lua | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/position.lua b/position.lua index 49cf1f3526..094211fb29 100644 --- a/position.lua +++ b/position.lua @@ -2,6 +2,7 @@ --@ module = true local argparse = require('argparse') +local guidm = require('gui.dwarfmode') local function parse_args(args) local opts = {} @@ -17,18 +18,6 @@ local function parse_args(args) return opts end -function get_active_cursor() --Return active fort/adv cursor or nil - if dfhack.world.isAdventureMode() then - local look = df.global.game.main_interface.adventure.look - if look.open and look.cursor:isValid() then - return look.cursor --Note: This is a df.coord - end - elseif df.global.cursor.x >= 0 then - return df.global.cursor - end - return nil --Not active -end - local months = { 'Granite, in early Spring.', @@ -129,7 +118,7 @@ if dfhack_flags.module then end function main(opts) - local cursor = get_active_cursor() + local cursor = guidm.getCursorPos() if opts.copy then --Copy keyboard cursor to clipboard if not cursor then From 8555938578d005215afd14c4024ce8a42946ffcc Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Tue, 11 Feb 2025 00:15:21 -0800 Subject: [PATCH 6/6] Update changelog.txt --- changelog.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index f5359e79b1..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 @@ -49,7 +51,6 @@ Template for new versions: ## Fixes - `advtools`: fix dfhack-added conversation options not appearing in the ask whereabouts conversation tree - `gui/rename`: fix error when changing the language of a unit's name -- `position`: support for adv mode look cursor ## Misc Improvements - `assign-preferences`: new ``--show`` option to display the preferences of the selected unit