If you are developing a quest with Solarus, you will definitely be interested in lots of new features of Solarus 1.2. But the most important one is probably custom entities!
Assume that you want to block the entrance of a dungeon with a big rock. To create your big rock on your map, you have to choose the type of map entity that best fits your needs. But each type of entity (non-playing character, enemy, door, destructible, dynamic tile, etc.) implements some built-in behavior that you don’t want for this particular need. Each type of entity corresponds to a common use case that is not necessarily yours in this situation. Sometimes, you can hijack an entity to avoid its built-in behavior: for example, you can implement the rock as a non-playing character that does not talk. Or you can make an enemy that does not hurt the hero. This is weird at best.
Another example is creating weapons that are not included in the engine. The engine implements a bow with arrows, the boomerang and the hookshot, similarly to Zelda: A Link to the Past. But how to create the hammer? More difficult: how to create the stakes that can be pushed using the hammer? How to shoot ice when using the ice rod?
Custom entities are the answer to these challenges. Custom entities are a new type of map entity introduced in Solarus 1.2.
Their main feature is to have no special feature! Indeed, they are fully scripted. Your script can define the size, the sprite (if any), the movement (if any) and the exact obstacle and collision rules. You can set callbacks to be executed when a collision is detected with another entity. In short, they are very powerful.
Lots of other built-in entity types could even be reimplemented as custom entities. Yet, we keep them because they are commonly used in games.
Let’s see how we could implement our big rock to block the entrance of a dungeon. From the editor, create on your map a custom entity called “rock_entrance”, set its size, for example 32x32, and its sprite to “entities/rock_entrance”. Indeed, common properties like the size and the sprite can be set from the editor. This is also possible from the Lua script of your map, but using the editor to create entities is easier. Then, edit the map script to define the other properties:
-- Don't allow other entities to traverse the rock. rock_entrance:set_traversable_by(false) -- Destroy the rock if there is an explosion. rock_entrance:add_collision_test("overlapping", function(rock_entrance, other) if other:get_type() == "explosion" then -- The rock explodes. sol.audio.play_sound("secret") rock_entrance:remove() end end)
This is a basic example of custom entity. To implement the hammer and hammer stakes, you will need two custom entities: the hammer itself (created dynamically when the player uses the item) and the hammer stakes. The hammer will test collisions with enemies and with hammer stakes. Hammer stakes will become traversable (and their sprite animation will change) when they collide with the hammer.
An interesting fact is that there will a lot of hammer stakes in your quest, and they will appear on different maps. In other words, you need a reusable custom entity. To solve this problem, we provide models: each custom entity can have an optional model. A model the name of a Lua script that will be applied to all custom entities that refer to it. Actually, this works exactly like the breed of enemies. You can have several enemies ruled by the same enemy script. Similarly, if you need multiple instances of identical custom entities, you can use a model.