• 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!
  • 2026 staff recruitment is open! Check it out and consider applying!

ModalWindows' Design

Codinablack

Dreamer
Content Editor
Joined
Dec 26, 2013
Messages
2,124
Solutions
14
Reaction score
1,518
Location
USA
GitHub
Codinablack
So I decided to start a discussion on different ways to implement a ModalWindow System that contains many modalwindows. What made me decide to start this discussion was abnormal activity from my ModalWindow System currently in development (Attribute Points System). Anyways, I am still kind of not used to the behavior of modalwindows, but I noticed mine were lagging for no apparent reason, and if I tried to click between many of them too fast it would just not send me my next modalwindow. I thought this was very odd so I investigated.

So what I do understand is that all of my modalwindows are in one file, since they are all to be used together and with nothing else. So I have one creatureevent to register. I also register the creatureevent in login.lua. One thing I found was I was using return way to much and fixed that. I use a predefined function to create every window too. Looks like this...


Code:
function createWindowWithButtons(cid, var, modalWindowId, headerText, bodyText, buttonTable, choiceTable, sendToPlayer, priority)
    var = ModalWindow(modalWindowId, headerText, bodyText)
        for i = 1, #buttonTable do
            var:addButton(buttonTable[i].id, buttonTable[i].text)
            if buttonTable[i].enter then
                var:setDefaultEnterButton(buttonTable[i].id)
            end
            if buttonTable[i].escape then
                var:setDefaultEscapeButton(buttonTable[i].id)
            end
        end
    if choiceTable ~= nil then
        for i = 0, #choiceTable do
            if choiceTable[i] ~= nil then
                var:addChoice(choiceTable[i].id, choiceTable[i].text)
            end
        end
    end
    if not priority then
        var:setPriority(false)
    end
    if sendToPlayer then
        var:sendToPlayer(cid)
    end
end

function createWindowWithText(cid, var, modalWindowId, headerText, bodyText, buttonTable, sendToPlayer, priority)
    var = ModalWindow(modalWindowId, headerText, bodyText)
        for i = 1, #buttonTable do
            var:addButton(buttonTable[i].id, buttonTable[i].text)
                if buttonTable[i].enter then
                    var:setDefaultEnterButton(buttonTable[i].id)
                end
        if buttonTable[i].escape then
            var:setDefaultEscapeButton(buttonTable[i].id)
                end
            end
    if not priority then
        var:setPriority(false)
            end
    if sendToPlayer then
        var:sendToPlayer(cid)
            end
end

Anyways the point of this discussion.

What methods would you use? Would you put each individual window in it's own script? If so, would you then hardcode it all instead of using functions like those above? How would you register the creatureevent? Would you link them all if they were in seperate scripts by registering an event upon creation of the new window? Would you keep them all in one creaturescript? All of these options.... What combination of the options would you feel like would be best to keep everything optimized?

A couple shout-outs to get this started... @forgee @Flatlander @Breed @Summ @Printer @Limos @andu @Ninja
 
Last edited:
Ahah! 41+ Views, and noone wants to jump into this conversation? This is NOT a support thread, more like a discussion on theory of optimization. I have tagged some people, some I have seen online plenty of times since this post... Some of those people have also been tagged in other threads I have made and never replied either... SOOOO, now I know who is blatantly just ignoring me and being assholes... As for the rest of you... What's the problem? Really have nothing to say on the subject? Afraid of being criticized by others? Too controversial of a topic?

Just know, I tagged the people I tagged because of the level of respect I have for their work, and because of that, I value their opinions....

That being said... Since I value your opinion and your work, and got respect for you, but yet can't even get a comment.. These are the things that shake people's faith... Thanks for not letting me down again @otland

@Mark @kornholi

Please destroy this thread... I don't care shit about it anymore....
 
I'm usally putting each modalwindow on their own respective lua. Due to organize stuff :P
 
I'm usally putting each modalwindow on their own respective lua. Due to organize stuff :p

Thank you printer! So now we have one person saying that for organizational purposes he creates each in their own script. Now @Printer what method do you use to register all of the modalwindows and why that method?


@Codinablack How about a ModalWindow System to report MapErrors, Server Bugs and Ideas to the Hoster/God? :)

Kind Regards,
Eldin.

Sorry Eldin, but this is off topic... I think that is a great idea actually and when I find the time I am going to use that idea and develop a system of which you are speaking of..

So @Evan informed me that when you tag someone in an edit it doesn't notify them, must be in the original post.... Now that being said, I would really like to get some people's opinions on best/most effective way to implement a modalwindow system that uses MANY modalwindows... So sorry if you already seen this thread but I'm going to go ahead and tag you guys again....

@forgee @Flatlander @Breed @Summ @Limos @andu @Ninja

Again, I tagged you guys because of the respect I have for you, and that carries on to your opinions...

@Mark Sorry for the post with your name in it above, I know you are busy and don't mean to bother you with such small things (especially when thats what you have moderators for, but I was unaware about the editing a post not notifying anyone they were tagged, so I posted that under the presumption that your moderators had already seen this thread), but your opinion would be HIGHLY appreciated on this topic....
 
Sorry I don't use TFS 1.0 or 1.1, Can't help you here.

True, I forget sometimes (especially since you were the one who convinced me to use it in the first place)

But now thinking about how it works, just as any other creaturevent does, it has to be registered. That being said, if you were to say create an onStatsChange sytem that incorporated many custom "stats" or "attributes" like in the custom stats discussion... Which way would you go about it and why? Would you create each script seperately? Then manually register them all, or would you code it all into one script?

Does anyone know if it would be more work or same if you just created many scripts for the same event vs. one script that handles it all?
 
Not sure I understand what you mean... Do you mean all I need to do is follow his advice? But it's not that simple, I don't want a simple, this way is how you should do it, I want peoples opinions and reasons as to why it should be done way instead of the other... printer only said he did it the way he did simply because of organization...

Or were you simply implying (a joke) that all I need to do is print()?
 
True, I forget sometimes (especially since you were the one who convinced me to use it in the first place)

But now thinking about how it works, just as any other creaturevent does, it has to be registered. That being said, if you were to say create an onStatsChange sytem that incorporated many custom "stats" or "attributes" like in the custom stats discussion... Which way would you go about it and why? Would you create each script seperately? Then manually register them all, or would you code it all into one script?

Does anyone know if it would be more work or same if you just created many scripts for the same event vs. one script that handles it all?
You gotta start structuring your code in an OOP style.. aren't you a little tired of re-writing the same code over and over?
 
I put all my stuff in separate files, unless they're related.

For example, if I have something that has multiple different windows, they'll be in one file, using the same onModalWindow() event.
But if I have another thing that uses modal windows and it's not related to the others, it'll be in a different file. Keeps it organized.

For the registration part, you want to register the event just before sending the modal window to the player.
Then inside the respective onModalWindow() function, you want to unregister it right away.

Just an example script I kind of worked with to create a pick-your-vocation and use custom regen:
https://gist.github.com/EvanMC/755006611bc5b89da2ec
 
I register them when script get executed. Such as if i make like a pokedex system. When they use pokedex, it should send and register the event.
 
Welcome to metatables, I won't go into too much detail but for those of us that are use to an OOP style of coding these mofo's are priceless
Code:
MyMetatable = {}
MyMetatable.__index = MyMetatable

setmetatable(MyMetatable, { -- magic converter from table to super table :)
    __call = function(cls, ...)
        return cls.new(...)
    end,
})
-- constructor
--[[
    local a = MyMetatable(1,2,3)
    local b = MyMetatable()
  
    if a.x == b.x then return true else return false end -- returns false
    -- a.x equals 1 and b.x equals 50
]]
function MyMetatable.new(x, y, z)
    local self = setmetatable({}, MyMetatable)
    self.x = x or 50 -- properties
    self.y = y or 50 --
    self.z = z or 7 --
    return self
end
-- metamethods
function MyMetatable:setXYZ_type1(x, y, z)    
    self.x = x
    self.y = y
    self.z = z
end

  -- metamethods
function MyMetatable:setXYZ_type2(x, y, z)    
    self.x, self.y, self.z = x, y, z
end

  -- metamethods
  -- coordinate:setXYZ_type2(1,2,3,4,5,6,7,8)
  -- will only set 1,2,3
function MyMetatable:setXYZ_type2(...)    
    self.x, self.y, self.z = ...
end

-- metamethods
-- local x, y, z = coordinate:getXYZ()
function MyMetatable:getXYZ()
    return self.x, self.y, self.z
end
-- metamethods
function MyMetatable:update_type1()
    self:setXYZ_type1( self:getXYZ() )
end
-- metamethods
function MyMetatable:update_type2()
    self:setXYZ_type2( self:getXYZ() )
end

-- When return is placed at the end followed by the metatable's name it allows it to be called outside of its file as an object
return MyMetatable

--[[

    How can this be used? I'm glad you asked, by referencing it
    using dofile or require to the path of this file in global.lua at the very top of the page
    dofile("data/lib/MyMetatable.lua") or whatever you name your Metatable or folder you want to save it to
    and then you can access it anywhere

]]
 
I put all my stuff in separate files, unless they're related.

For example, if I have something that has multiple different windows, they'll be in one file, using the same onModalWindow() event.
But if I have another thing that uses modal windows and it's not related to the others, it'll be in a different file. Keeps it organized.

For the registration part, you want to register the event just before sending the modal window to the player.
Then inside the respective onModalWindow() function, you want to unregister it right away.

Just an example script I kind of worked with to create a pick-your-vocation and use custom regen:
https://gist.github.com/EvanMC/755006611bc5b89da2ec
I register them when script get executed. Such as if i make like a pokedex system. When they use pokedex, it should send and register the event.

Ok going off of the gist Evan sent me, and from what printer said... You both register the event in a script before sending the window correct? But then @Evan if you have multiple windows in the same script, wouldn't they fall under the same register?

Does anyone know if having all the multiple windows in one file would slow it down?

Also what about the question I asked before, if you have multiple scripts for one creatureevent (example onHealthChange), like say a reflection system, an absorption system, and a resistance system... Which would be wiser? Putting all that into one onHealthChange? Or creating seperate scripts for each system? What is the performance cost of either choice if any?

Do you guys use your methods strictly for organizational means?
 
Does anyone know if having all the multiple windows in one file would slow it down?
Having multiple windows under one onModalWindow() shouldn't affect the performance.
Which would be wiser? Putting all that into one onHealthChange? Or creating seperate scripts for each system? What is the performance cost of either choice if any?
Put the systems into separate scripts if it makes the code easier to read and maintain (It's up to your coding abilities). You should benchmark your scripts if you're worried about performance costs.

I put my stuff into separate files, unless they're related. I like to keep it organized. :p
 
I have all my modal window callbacks defined in the respective system file to keep things organized. I define the callback as System.modalWindowCallback( ... ) and then I call it from the file in creaturescripts that is actually registered to the event.
With multiple windows you could save yourself a few if - elseif's by separating them into their own files but it would have to be a very large number of windows to have any significant impact. Just make sure you don't do any complex operations before you have determined that you need to (i.e correct window and button pressed).

You will want to unregister the event when you are not sending a new window. If you send a new window right away you want to keep the event registered.
After a quick look at @Evan's gist, he unregister the event every time onModalWindow() runs, and register it again if he need it. In the end I doubt either way makes much of a difference. As @Ninja said benchmark the scripts if you're really concerned.
Code:
local t = os.clock()
-- code
print(os.clock() - t)

Absorbtion, reflection and resistance sounds like they would run at the same point in onHealthChange(), so I would put them in the same script to avoid doing the same checks 3 times in separate scripts. I would consider them related too, so I would keep them together anyway.
 
Having multiple windows under one onModalWindow() shouldn't affect the performance.

Put the systems into separate scripts if it makes the code easier to read and maintain (It's up to your coding ability). You should benchmark your scripts if you're worried about performance costs.

I put my stuff into separate files, unless they're related. I like to keep it organized. :p

Thank you!


I have all my modal window callbacks defined in the respective system file to keep things organized. I define the callback as System.modalWindowCallback( ... ) and then I call it from the file in creaturescripts that is actually registered to the event.
With multiple windows you could save yourself a few if - elseif's by separating them into their own files but it would have to be a very large number of windows to have any significant impact. Just make sure you don't do any complex operations before you have determined that you need to (i.e correct window and button pressed).

You will want to unregister the event when you are not sending a new window. If you send a new window right away you want to keep the event registered.
After a quick look at @Evan's gist, he unregister the event every time onModalWindow() runs, and register it again if he need it. In the end I doubt either way makes much of a difference. As @Ninja said benchmark the scripts if you're really concerned.
Code:
local t = os.clock()
-- code
print(os.clock() - t)

Absorbtion, reflection and resistance sounds like they would run at the same point in onHealthChange(), so I would put them in the same script to avoid doing the same checks 3 times in separate scripts. I would consider them related too, so I would keep them together anyway.

Forgee, dude you be way advanced with your methods... I am still noobie with all the callbacks, I know I use them daily in lua, just still noobish with it.... See I was having problems when trying to click too quickly between the windows, it would literally just drop the window. I have to slow it down it down it would work fine. I suppose now looking back it's probably a problem with my methods of registering. I have 36 modalwindows all part of the same system right now... Thanks for that code for testing benchmarks, never thought of that...

Thank you everyone! So it seems this way... Lua is so fast it really doesn't matter? The performance difference is very minute, and that apparently some of the best scripters all agree that organization is best!

What about the functions I posted? I seem to have a problem reading a storage value when going back to a window, but when initially going to the window it reads the storage value fine, when I go back it reads -1. Do you guys think that could be because of the functions? I don't see anything wrong with them..

So would you guys rather use a function for creation of the windows (to save time and lines) or would you prefer hardcoding it yourself?

Thanks again for everyone who has posted with their opinions. It will take a good amount of time for me to be able to rewrite the system into individual files, but I'm going to do that, and keep the original, then I will post the performance benchmarks, like I said 36 windows, so it will take some time... Is anyone interested in the results of the benchmarks?
 
It's not that optimization doesn't matter but number camparison (if modalWindowID == 0x01 then) is such a quick job it doesn't hurt performance to keep them together for organization. When you're dealing with more complex tasks optimization plays a larger role. For example in nested loops optimization can make a huge difference.

I'm not sure what function you are referring too. The only ones I see are those you use to create modal windows and they don't refer to storage values at all.

I "hardcode" my windows, I don't feel like it's less work setting up tables and passing them to a function, I can just ass well create the window and add the buttons and choices directly. I suppose if the windows are static it may be quicker but I almost always pass some data that gets processed to determine how the window gets constructed.

I would be very interested to see a before and after on your benchmark results. Of course along with what differes betwen the scripts.
 
Back
Top