• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

[TFS 1.2] Modal Window Helper Lib

Maybe it would be better to don't use this lib, then

This modal window is supposed to have two functions: get inside a player queue or checking your own info.
It would be something like that:
If the player wants to simply join a queue, he will just select this first option and enter the queue.
This should be easy, if there were not the problem I will describe below.
FPDWjxz.png
(1)

If the player wants to check it's info, he will receive this:
m8bGoUq.png
(2)

The main problem is the userdata is changed whenever a new player opens the modal window, for every player with it opened.
If I have this window opened, like you can see at (2)
And the character Test Character 1, opens it, it will update Gamemaster's info to Test Character 1's info.

Evil Hero said, as you can see in his post, that I needed to keep a "save" for each player that uses the modal window.
I've tried, actually, inserting the player's info inside a global table, where I would access it whenever I needed.
But since the userdata gets replaced, it changes from every other windows opened.

x_x
It's totally fine to use this lib to do what you want. You don't have to "save" anything using it. Could you create a support thread tho? Don't feel like spamming the thread with support related stuff.
 
I get this error
1f87ad7d6a32e4ecf63afc9bcec519e4.png


the addon doll it's alreayd in my backpack, i get that everytime :/ i have tfs 1.3
 
I get this error
1f87ad7d6a32e4ecf63afc9bcec519e4.png


the addon doll it's alreayd in my backpack, i get that everytime :/ i have tfs 1.3
I assume you are using my script? did you change the addon doll ID in the script?
 
I assume you are using my script? did you change the addon doll ID in the script?
damn i just realized im not posting in the addon doll thread im sorry D:
and no i didn't see that part sorry, thank you works perfect now :D
 
Is there anyway to get this to work with the /town command?
like when you do /town it shows in the widnow the list of avaible towns you can teleport to? also make it so that the player can tp the same as the admin/gm

** Using tfs 1.2 Malucoos newest otx server.

thanks for reading and sorry for the inconvienience. :)
thanks in advance.
--dredds
 
Are you using TFS 1.2 for client version 8.6? Because Modal Windows do not exist in older client versions before 9.7~ I believe.
yep i have learn that now. trying to get otclient going but will probably give up because you need to compile
 
yep i have learn that now. trying to get otclient going but will probably give up because you need to compile
Why give up because you need to compile? Compiling is not hard.. You legit load the files and press compile... if you are looking at starting a server for yourself and some friends and jsut want to play sure dont worry about it, but if you are looking at hosting a server for others to play then i would suggest attempting to learn the basic's at least so when a problem occurs (and yes it will happen) you will at least know how to handle it. Dont just give up because its 'to hard' its really not. I believe in you!
 
1630754880479.png

1. It has problems with text height when there are multiple lanes.
Both button, and <hr> are in incorrect positions I would say. Container height is also not scaled.
Any fixes for that? (I am using TFS 1.3 ofc)

2. Is there any way to add an image the the modal?
 
Haven't test it yet, but I wonder if this gonna work on TFS 1.4?
tfs version doesn't matter, the main requirement is tibia client VERSION 9.6 AND ABOVE, older clients doesn't have this feature, unless you use OTClient ONLY and modify it to support it.

can I make a modal windows with images with that?
yes you can, but again, only with OTC and you have to modify it by yourself or pay someone for this job
 
[Error - CreatureEvent::configureEvent] Invalid type for creature event: ModalWindowHelper
[Warning - BaseEvents::loadFromXml] Failed to configure event


got these msgs at console
 
Which TFS? That's how it looks in your XML?
XML:
<event type="modalwindow" name="ModalWindowHelper" script="modalwindowhelper.lua" />
and you registered it in login.lua like this?
Lua:
player:registerEvent("ModalWindowHelper")
 
Which TFS? That's how it looks in your XML?
XML:
<event type="modalwindow" name="ModalWindowHelper" script="modalwindowhelper.lua" />
and you registered it in login.lua like this?
Lua:
player:registerEvent("ModalWindowHelper")
Thanks for answering.
Yep, everything is looking like you show, my tfs is 1.2 (nostalrius by Ezzz)
 
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
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
The end

That's it. Later today I will post a !rank talkaction I've made using this library.

EDIT: Here it is.
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)

where it goes
 
Back
Top