Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ This is an addon for Windower4 for FFXI. It allows text commands to teleport usi
### Commands:
The //sw command prefix is only needed if the user is running another addon that is using the command prefix for the warp system you are operating. i.e. //te for temenos. In that case the user would need to use //sw te or /console sw te in a macro instead of just //te until the other addon is unloaded.

#### Menu Commands
| Command | Action |
| --- | --- |
| //sw menu | Toggles the warp menu.

#### Homepoint Commands
| Command | Action |
| --- | --- |
Expand Down Expand Up @@ -179,6 +184,8 @@ Thanks to Lili for researching a better fuzzy matching logic.

Thanks to Staticvoid for researching and implementing the Sortie, Odyssey, Temenos and Apollyon warp systems.

Thanks to Fauxfeld for implementing the UI menu system.

### Updates
#### v0.96
- **Feature**: Homepoints now uses same-zone teleporting feature.
Expand Down Expand Up @@ -267,3 +274,10 @@ Thanks to Staticvoid for researching and implementing the Sortie, Odyssey, Temen
#### v1.0.3
- **Resolved**: Limbus: Some NPC targets are not updated correctly in packets, resolve issue teleporting.
- **Resolved**: Sortie: fixed menu structure (again)

#### v1.0.4
- **Feature**: Added UI menu system.
- **Improvement**: Added click offset and scale for menu buttons.
- **Improvement**: Added page navigation to the menu.
- **Improvement**: Added close button to the menu.
- **Improvement**: Added send mode toggle to the menu.
31 changes: 30 additions & 1 deletion superwarp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Sortie support implementation: Staticvoid
Odyssey support implementation: Staticvoid
Apollyon and Temenos support: Staticvoid
UI menu implementation: Fauxfeld
]]

_addon.name = 'superwarp'
Expand All @@ -61,6 +62,8 @@ require('sendall')
require('fuzzyfind')

maps = require('map/maps')
sw_menu = require('ui/menu')
sw_buttons = require('ui/buttons')

warp_list = T{}
for k, map in pairs(maps) do
Expand Down Expand Up @@ -103,10 +106,20 @@ local defaults = {
simulate_client_lock = false, -- lock the local client during a warp/subcommand, simulating menu behavior.
send_all_order_mode = 'melast', -- order modes: melast, mefirst, alphabetical
chat_log_use = 'log', -- log messages to 'log', 'console', or 'none'. If debug is on, it will always log to the chat log
menu_position = { x = 100, y = 50 }, -- screen position of the warp menu
menu_items_per_page = 15, -- number of items per menu page
menu_button_spacing = 22, -- vertical spacing between menu buttons
menu_button_width = 30, -- character width of menu buttons
click_offset = { x = 0, y = 0 }, -- fixed offset for click/hover detection
click_scale = { x = 1.0, y = 1.05 }, -- scale multiplier for click/hover detection (for DPI/resolution scaling)
}

local settings = config.load(defaults)

-- Apply click offset and scale for menu buttons (handles DPI/resolution scaling)
sw_buttons.set_click_offset(tonumber(settings.click_offset.x) or 0, tonumber(settings.click_offset.y) or 0)
sw_buttons.set_click_scale(tonumber(settings.click_scale.x) or 1.0, tonumber(settings.click_scale.y) or 1.0)

-- bounds checks.
if settings.send_all_delay < 0 then
settings.send_all_delay = 0
Expand Down Expand Up @@ -696,6 +709,9 @@ local function handle_warp(warp, args, fast_retry, retries_remaining)
end

local function received_warp_command(cmd, args)
if sw_menu.is_visible() then
sw_menu.close()
end
if current_activity ~= nil then
log('Superwarp is currently busy. To cancel the last request try "//sw cancel"')
else
Expand Down Expand Up @@ -726,6 +742,13 @@ windower.register_event('addon command', function(...)
windower.send_ipc_message('reset')
end

elseif cmd == 'menu' then
if sw_menu.is_visible() then
sw_menu.close()
else
sw_menu.open(maps, received_warp_command, settings)
end

elseif cmd == 'debug' then
settings.debug = not settings.debug
log('Debug is now '..tostring(settings.debug))
Expand All @@ -747,7 +770,7 @@ windower.register_event('addon command', function(...)
local map = maps[key]
log(map.help_text)
end
log('|Superwarp|\ncancel - Cancels pending warp command.\nreset - Attemps to clear menu lock.')
log('|Superwarp|\ncancel - Cancels pending warp command.\nreset - Attemps to clear menu lock.\nmenu - Toggle clickable warp destination menu.')
end
end)

Expand Down Expand Up @@ -989,6 +1012,9 @@ windower.register_event('outgoing chunk',function(id,data,modified,injected,bloc
end)
windower.register_event('zone change',function(id,data,modified,injected,blocked)
state.client_lock = false
if sw_menu.is_visible() then
sw_menu.close()
end
if expecting_zone then
handle_on_arrival:schedule(math.max(0, settings.command_delay_on_arrival))
end
Expand All @@ -1012,6 +1038,9 @@ windower.register_event('outgoing chunk',function(id,data,modified,injected,bloc
end)

windower.register_event('unload', function()
if sw_menu.is_visible() then
sw_menu.close()
end
if windower.ffxi.get_info().logged_in then
reset(true)
end
Expand Down
119 changes: 119 additions & 0 deletions ui/buttons.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
-- Button UI module for superwarp, adapted from blu addon by Anissa of Cerberus
local texts = require('texts')

local buttons = {}
local buttonlist = {}

-- Store offset and scale in the buttons table so it's accessible everywhere
buttons.click_offset_x = 0
buttons.click_offset_y = 0
buttons.click_scale_x = 1.0
buttons.click_scale_y = 1.0

-- Set click offset for adjusting hover/click detection (fixed offset)
function buttons.set_click_offset(x, y)
buttons.click_offset_x = tonumber(x) or 0
buttons.click_offset_y = tonumber(y) or 0
end

-- Set click scale for adjusting hover/click detection (for DPI/resolution scaling)
function buttons.set_click_scale(x, y)
buttons.click_scale_x = tonumber(x) or 1.0
buttons.click_scale_y = tonumber(y) or 1.0
end

function buttons.new(label, settings)
label = label or ""
settings = settings or {}

settings.flags = settings.flags or {}
settings.flags.draggable = false

local button = {}

button.left_click = settings.left_click
button.hover_on = settings.hover_on
button.hover_off = settings.hover_off

button.text = texts.new(label, settings)
button.destroy = function() buttons.destroy(button) end

setmetatable(button, {
__index = function(t, k)
if t.text[k] ~= nil then
return function(...)
return t.text[k](t.text, ...)
end
end
end
})

buttonlist[#buttonlist + 1] = button
return button
end

function buttons.destroy(me)
for k, v in pairs(buttonlist) do
if v == me then
buttonlist[k] = nil
end
end
me.text.destroy(me.text)
end

local mousemoved = true
local ignorerelease = false

windower.register_event('mouse', function(eventtype, x, y, delta, blocked)
if blocked then
return
end

-- Apply click scale and offset to coordinates
-- Scale first, then offset: adj = (mouse * scale) + offset
local adj_x = (x * buttons.click_scale_x) + buttons.click_offset_x
local adj_y = (y * buttons.click_scale_y) + buttons.click_offset_y

-- Mouse move
if eventtype == 0 then
mousemoved = true

for _, button in pairs(buttonlist) do
if type(button.hover_on) == "function" and type(button.hover_off) == "function" then
if button.text:hover(adj_x, adj_y) then
button:hover_on()
else
button:hover_off()
end
end
end

-- Mouse left click
elseif eventtype == 1 then
mousemoved = false
for _, button in pairs(buttonlist) do
if button.text:hover(adj_x, adj_y) and button.text:visible() then
ignorerelease = true
return true
end
end
ignorerelease = false

-- Mouse left release
elseif eventtype == 2 then
for _, button in pairs(buttonlist) do
if button.text:hover(adj_x, adj_y) and button.text:visible() and not mousemoved and type(button.left_click) == "function" then
button:left_click()
return true
end
end

if ignorerelease then
return true
end
end

return false
end)

return buttons
Loading