I already talked about the multi_events.lua script in another topic, but let's share it in this forum because most scripts to be shared by the community will need it. Indeed, scripts that use it can be more self-contained, and therefore easier to share, which is the goal of this forum.

Scripts that I will share it on this forum, as well as the ones you can already find in the Zelda OLB Solarus Edition project, almost always use this feature.

So what is it?

This multi_events.lua script allows to register several functions to a single event, for example game:on_started().

Motivation

You often have a lot of scripts: the dialog box, the HUD, the pause menu, the camera manager, etc., and all these components need to do some stuff in the same event, for example they all need to perform some initialization in game:on_started(). One way to do it is to define the game:on_started() event in your game_manager.lua script, and from there, call the initialization code of each component (the dialog box, the HUD, the pause menu, the camera manager, etc). You can guess the problem: whenever you create a new component that also needs to do something in game:on_started(), you need to modify your game_manager.lua script again. This is because game:on_started() can be defined only once (or it would overwrite the previous definition). And then when you want to share your nice new feature on this forum, you need to tell people how to modifiy they game_manager.lua script. Not as easy as just copying a Lua script file. This is only an exemple, the same is true for a lot of other events (not only game:on_started()).

As an example, our previous games all have this issue. Here is the game:on_started() event from Zelda ROTH SE:

Code: Lua

function game:on_started()

dungeon_manager:create(game)

equipment_manager:create(game)

dialog_box = dialog_box_manager:create(game)

hud = hud_manager:create(game)

pause_menu = pause_manager:create(game)

camera = camera_manager:create(game)

-- Initialize the hero.

local hero = game:get_hero()

game:stop_rabbit()-- In case the game was saved as a rabbit.

update_walking_speed()

-- Measure the time played.

run_chronometer(game)

end

As described above, we initialize all components. Components are usually defined in their own separate Lua scripts of course, but there is still this central initialization code needed. It is a bit delicate to share one of these features with you (like for example, the transformation of Link into a rabbit), because you would have not only to copy the rabbit.lua script, but also this initialization code. And actually even more, because in fact, rabbit.lua also needs to do stuff in game:on_game_over_started() and in hero:on_state_changed()… Very easy to miss things and to introduce bugs when you want the feature in your project.

So, it would be great if there was a way to define multiple functions to be called when a single event occurs, right? This is precisely what multi_events.lua script does. By using a different syntax, you can register several functions to the same event. Which means that in our examples above, you no longer need to modifiy existing scripts every time you import a script from some other project! Well, you still need to require() the script somewhere, but that's it.

Now in Zelda OLB SE, one of our new projects, the game_manager.lua script no longer defines game:on_started() at all. Instead, every component (dungeons, equipment, dialog box, HUD, pause menu, camera, rabbit manager, chronometer, etc.) registers its own stuff to be done in game:on_started(). The game manager remains unchanged when features are added or removed from the project. The whole rabbit code is contained in a single script now (and actually I will share it on this forum very soon).

So, this is extremely useful to make scripts as much independent and self-contained as possible. Basically, they become much easier to share.

How to use it?

- Copy the multi_events.lua script below to your project, into the scripts/ folder.- Just require("scripts/multi_events.lua") at some point in your project (like from main.lua).- In your scripts for all events, you now have the choice between two approaches: the traditional one or the multi-functions one, using object:register_event(event_name, callback).

Examples:

Code: Lua

-- The traditional way still works:

function my_sprite:on_animation_finished()

-- blah blah

end

Code: Lua

local map =...

require("multi_events")

-- This approach allows to register several functions to the same event:

Both approaches should be equivalent I think. It is a matter of taste. To me, the and+or version is a bit less readable. It makes one additional test. Also, when defining a recursive algorithm it is nice to show explicitly the an initial value, which is often an empty list, or in this particular case, an empty function. Like in functional programming.But again, this is equivalent, there is no real problem with your suggestion.