Non Sequitur
Well-Known Member
Reasoning
The current way we can implement modal windows is quite cumbersome in my opinion, having to create it somewhere, register an event, add buttons in some weird order to make it work and having to take account of window ids, button ids, choice ids in a complete different file than the one you've created the modal window. That is not optimal so I've created this helper library to help with that.
What you can do with it
You can use this example in a talkaction and test it for yourself (check the output on your server console). Other than what is shown in the above code, you can also use modalWindow:addButtons(...) and modalWindow:addChoices(...) to add multiple buttons/choices at once.
Installing
That's it. Later today I will post a !rank talkaction I've made using this library.
EDIT: Here it is.
The current way we can implement modal windows is quite cumbersome in my opinion, having to create it somewhere, register an event, add buttons in some weird order to make it work and having to take account of window ids, button ids, choice ids in a complete different file than the one you've created the modal window. That is not optimal so I've created this helper library to help with that.
What you can do with it
LUA:
-- The helper lib is used by passing a table value to the ModalWindow function
local window = ModalWindow {
title = 'Title',
message = 'Please, choose the lowest number and press [Ok]'
}
local lowestChoice
for i = 1, 5 do
local value = math.random(1, 100)
-- modalWindow:addChoice() returns the choice object that will be passed to the callbacks
local choice = window:addChoice(value)
-- This way we can pass extra information to the callback
choice.value = value
if not lowestChoice or lowestChoice.value > value then
lowestChoice = choice
end
end
lowestChoice.correct = true
-- Add a button with a specific callback
window:addButton('Ok',
function(button, choice)
if choice.correct then
print('Player selected the correct option.')
else
print('Player selected the incorrect option.')
end
end
)
-- Set this button as the default enter button
window:setDefaultEnterButton('Ok')
-- Add a button without a specific callback
window:addButton('Close')
window:setDefaultEscapeButton('Close')
-- If a button without a specific callback is pressed, this fucntion will be called
window:setDefaultCallback(
function(button, choice)
print('Default callback, button pressed: ' .. button.text .. ' player choice: ' .. choice.text)
end
)
window:sendToPlayer(player)
You can use this example in a talkaction and test it for yourself (check the output on your server console). Other than what is shown in the above code, you can also use modalWindow:addButtons(...) and modalWindow:addChoices(...) to add multiple buttons/choices at once.
Installing
- In data/lib/lib.lua
LUA:
dofile('data/lib/modalwindow.lua')
- Create the file data/lib/modalwindow.lua
LUA:
if not modalWindows then modalWindows = { modalWindowConstructor = ModalWindow, nextFreeId = 500, windows = {} } end local MT = {} MT.__index = MT function ModalWindow(...) local args = {...} if type(args[1]) == 'table' then local self = setmetatable(args[1], MT) local id = modalWindows.nextFreeId self.id = id self.buttons = {} self.choices = {} self.players = {} self.created = false modalWindows.nextFreeId = id + 1 table.insert(modalWindows.windows, self) return self end return modalWindows.modalWindowConstructor(...) end function MT:setDefaultCallback(callback) self.defaultCallback = callback end function MT:addButton(text, callback) local button = {text = tostring(text), callback = callback} table.insert(self.buttons, button) return button end function MT:addButtons(...) for _, text in ipairs({...}) do table.insert(self.buttons, {text = tostring(text)}) end end function MT:addChoice(text) local choice = {text = tostring(text)} table.insert(self.choices, choice) return choice end function MT:addChoices(...) for _, text in ipairs({...}) do table.insert(self.choices, {text = tostring(text)}) end end function MT:setDefaultEnterButton(text) self.defaultEnterButton = text end function MT:setDefaultEscapeButton(text) self.defaultEscapeButton = text end function MT:setTitle(title) self.title = tostring(title) end function MT:setMessage(message) self.message = tostring(message) end local buttonOrder = { [4] = {3, 4, 2, 1}, [3] = {2, 3, 1}, [2] = {1, 2}, [1] = {1} } function MT:create() local modalWindow = modalWindows.modalWindowConstructor(self.id, self.title, self.message) local order = buttonOrder[math.min(#self.buttons, 4)] if order then for _, i in ipairs(order) do local button = self.buttons[i] modalWindow:addButton(i, button.text) button.id = i if button.text == self.defaultEnterButton then modalWindow:setDefaultEnterButton(i) elseif button.text == self.defaultEscapeButton then modalWindow:setDefaultEscapeButton(i) end end end for _, choice in ipairs(self.choices) do modalWindow:addChoice(_, choice.text) choice.id = _ end self.modalWindow = modalWindow end function MT:sendToPlayer(player) if not self.modalWindow then self:create() end player:registerEvent('ModalWindowHelper') self.players[player:getId()] = true return self.modalWindow:sendToPlayer(player) end
- In data/creaturescripts/creaturescripts.xml
XML:
<event type="modalwindow" name="ModalWindowHelper" script="modalwindowhelper.lua" />
- Create the file data/creaturescripts/scripts/modalwindowhelper.lua
LUA:
function onModalWindow(player, modalWindowId, buttonId, choiceId) local modalWindow for _, window in ipairs(modalWindows.windows) do if window.id == modalWindowId then modalWindow = window break end end if not modalWindow then return true end local playerId = player:getId() if not modalWindow.players[playerId] then return true end modalWindow.players[playerId] = nil local choice = modalWindow.choices[choiceId] for _, button in ipairs(modalWindow.buttons) do if button.id == buttonId then local callback = button.callback or modalWindow.defaultCallback if callback then callback(button, choice) break end end end return true end
That's it. Later today I will post a !rank talkaction I've made using this library.
EDIT: Here it is.
Last edited by a moderator: