Solarus quests  1.5
Quest maker's reference
Enemy

Table of Contents

An enemy is a bad guy that hurts the hero when touching him.

This type of map entity can be declared in the map data file. It can also be created dynamically with map:create_enemy().

Overview

Enemies can exist in various breeds. Each breed corresponds to a model of enemy with its behavior, its sprites and its movements.

The script file enemies/XXXX.lua defines the enemy breed XXXX. This script is executed every time an enemy of that model is created. The corresponding Lua enemy object is passed as parameter of that script. Use the Lua notation "..." to get this parameter and store it into a regular variable.

Here is a basic example of script for the enemy breed "tentacle", a simple model of enemy that just follows the hero.

-- First, we put the parameter into a variable called "enemy".
-- (In Lua, the notation "..." refers to the parameter(s) of the script.)
local enemy = ...

-- Called when the enemy was just created on the map.
function enemy:on_created()

  -- Define the properties of this enemy.
  self:set_life(1)
  self:set_damage(2)
  self:create_sprite("enemies/tentacle")
  self:set_size(16, 16)
  self:set_origin(8, 13)
end

-- Called when the enemy should start or restart its movement
-- (for example if the enemy has just been created or was just hurt).
function enemy:on_restarted()

  -- Create a movement that walks toward the hero.
  local m = sol.movement.create("target")
  m:set_speed(32)
  m:start(self)
end

Such a script is all what you need to define a model of enemy. The engine handles for you the detection of collisions with the hero or his weapons, hurts the hero or the enemy when appropriate, removes the enemy when it gets killed, etc. But you can customize everything using the API described on this page, like what kind of attacks can hurt the enemy. You can also make complex enemies composed of several sprites, and set different behavior to each sprite. This is very useful to program a boss.

Timers are handy to script some repeated behavior on enemies, like performing a particular attack every 5 seconds. Create your timers from the enemy:on_restarted() event. Timers of an enemy are automatically destroyed when the enemy is hurt or immobilized, so that they don't get triggered during these special states. They are also destroyed when you call enemy:restart(). When enemy:on_restarted() is called, you are guaranteed that no timers exist on your enemy. Thus, it is safe to create them there.

Basic enemies often have the same behavior. To avoid duplication of code, you can factorize some code into a generic file and call it from each enemy breed script with require(), sol.main.do_file() or sol.main.load_file().

Methods inherited from map entity

Enemies are particular map entities. Therefore, they inherit all methods from the type map entity.

See Methods of all entity types to know these methods.

Methods of the type enemy

The following methods are specific to enemies.

enemy:get_breed()

Returns the breed (the model) of this enemy.

  • Return value (string): The enemy's breed.

enemy:get_life()

Returns the current life of this enemy.

  • Return value (number): Number of health points of the enemy.

enemy:set_life(life)

Sets the current life of this enemy.

The initial value is 1.

  • life (number): Number of health points to set. A value of 0 or lower kills the enemy.

enemy:add_life(life)

Adds some life to the enemy.

  • life (number): Number of health points to add.
Remarks
Equivalent to enemy:set_life(enemy:get_life() + life)

enemy:remove_life(life)

Removes some life from the enemy.

  • life (number): Number of health points to remove.
Remarks
Equivalent to enemy:set_life(enemy:get_life() - life)

enemy:get_damage()

Returns the number of life points that the enemy removes from the hero when touching him. This number will be divided by the level of resistance ability of the player (his tunic).

  • Return value (number): Damage inflicted to the hero.

enemy:set_damage(damage)

Sets the number of life points that the enemy removes from the hero when touching him. This number will be divided by the tunic level of the player, unless you override this default calculation in hero:on_taking_damage().

The default value is 1.

  • damage (number): Damage inflicted to the hero.

enemy:is_pushed_back_when_hurt()

Returns whether the enemy is pushed away when it is hurt.

  • Return value (boolean): true if the enemy is pushed away when hurt.

enemy:set_pushed_back_when_hurt([pushed_back_when_hurt])

Sets whether the enemy should be pushed away when it is hurt.

The default value is true.

  • pushed_back_when_hurt (boolean, optional): true to make the enemy pushed away when hurt. No value means true.

enemy:get_push_hero_on_sword()

Returns whether the hero is pushed away when he hits this enemy with his sword.

  • Return value (boolean): true if the hero is pushed away when hitting this enemy with his sword.

enemy:set_push_hero_on_sword([push_hero_on_sword])

Sets whether the hero should be pushed away when he hits this enemy with his sword.

The default value is false.

  • push_hero_on_sword (boolean, optional): true to push the hero away when hitting this enemy with his sword. No value means true.

enemy:get_can_hurt_hero_running()

Returns whether this enemy can hurt the hero even when the hero is running.

  • Return value (boolean): true if the hero can be hurt by this enemy even when running.

enemy:set_can_hurt_hero_running([can_hurt_hero_running])

Sets whether this enemy can hurt the hero even when the hero is running.

The default value is false.

  • can_hurt_hero_running (boolean, optional): true so that the hero can be hurt by this enemy even when running. No value means true.

enemy:get_hurt_style()

Returns the style of sounds and animations to play when this enemy is hurt.

  • Return value (string): "normal", "monster" or "boss".

enemy:set_hurt_style(hurt_style)

Sets the style of sounds and animations to play when this enemy is hurt. The default values is "normal".

  • hurt_style (string): "normal", "monster" or "boss".

enemy:get_can_attack()

Returns whether this enemy can currently attack the hero.

  • Return value (boolean): true if the enemy can currently attack the hero.

enemy:set_can_attack([can_attack])

Sets whether this enemy can currently attack the hero.

When the enemy restarts after being hurt, can_attack is always set to true.

  • can_attack (boolean, optional): true to allow the enemy to attack the hero. No value means true.

enemy:get_minimum_shield_needed()

Returns the level of protection (if any) that stops attacks from this enemy.

If the player has a protection ability greater than or equal to this value, he will stop attacks from this enemy if he is facing the direction of the enemy. The special value of 0 means that attacks cannot be stopped with the protection ability. Returns the required level of protection to stop attacks from this enemy.

  • Return value (number): The level of protection that stops attacks from this enemy. A value of 0 means that the hero cannot stop the attacks.

enemy:set_minimum_shield_needed(minimum_shield_needed)

Sets a level of protection that stops attacks from this enemy.

If the player has a protection ability greater than or equal to this value, he will stop attacks from this enemy if he is facing the direction of the enemy. The special value of 0 means that attacks cannot be stopped with the protection ability. The default value is 0.

  • minimum_shield_needed (number): The level of protection that stops attacks from this enemy. A value of 0 means that the hero cannot stop the attacks.

enemy:get_attack_consequence(attack)

Returns how this enemy reacts when he receives an attack.

Recall that enemies may have several sprites. This attack consequence applies to all sprites of the enemy, unless you override some of them with enemy:set_attack_consequence_sprite().

  • attack (string): Name of an attack against the enemy: "sword", "thrown_item", "explosion", "arrow", "hookshot", "boomerang" or "fire".
  • consequence (number or string): Indicates what happens when this enemy receives the attack. It may be:
    • A positive integer: The enemy is hurt and loses this number of life points. In the particular case of a sword attack, this number will by default be increased by the level of the sword (see enemy:on_hurt_by_sword()).
    • "ignored": Nothing happens. The weapon (if any) traverses the enemy.
    • "protected": The enemy stops the attack. An attack failure sound is played.
    • "immobilized": The enemy is immobilized for a few seconds.
    • "custom": Event enemy:on_custom_attack_received() is called.

enemy:set_attack_consequence(attack, consequence)

Sets how this enemy reacts when he receives an attack.

Recall that enemies may have several sprites. This attack consequence applies to all sprites of the enemy, unless you override some of them with enemy:set_attack_consequence_sprite().

  • attack (string): Name of an attack against the enemy: "sword", "thrown_item", "explosion", "arrow", "hookshot", "boomerang" or "fire".
  • consequence (number or string): Indicates what happens when this enemy receives the attack. The possible values are the same as in enemy:get_attack_consequence().

enemy:get_attack_consequence_sprite(sprite, attack)

Returns how this enemy reacts when one of his sprites receives an attack.

This method returns the same result as enemy:get_attack_consequence(), unless you override the reaction of the enemy for a particular sprite with enemy:set_attack_consequence_sprite().

  • sprite (sprite): A sprite of this enemy.
  • attack (string): Name of an attack against the enemy: "sword", "thrown_item", "explosion", "arrow", "hookshot", "boomerang" or "fire".
  • consequence (number or string): Indicates what happens when this sprite receives the attack. The possible values are the same as in enemy:get_attack_consequence().

enemy:set_attack_consequence_sprite(sprite, attack, consequence)

Sets how this enemy reacts when one of his sprites receives an attack.

This method overrides for a particular sprite the attack consequences defined by enemy:set_attack_consequence().

  • sprite (sprite): A sprite of this enemy.
  • attack (string): Name of an attack against the enemy: "sword", "thrown_item", "explosion", "arrow", "hookshot", "boomerang" or "fire".
  • consequence (number or string): Indicates what happens when this sprite receives the attack. The possible values are the same as in enemy:get_attack_consequence().

enemy:set_default_attack_consequences()

Restores the default attack consequences for this enemy and its sprites.

enemy:set_default_attack_consequences_sprite(sprite)

Restores the default attack consequences for a particular sprite of this enemy.

  • sprite (sprite): A sprite of this enemy.

enemy:set_invincible()

Makes this enemy ignore all attacks.

Equivalent to calling lua_api_enemy_set_attack_consequence(attack, "ignored") for each attack.

enemy:set_invincible_sprite(sprite)

Makes a sprite of this enemy ignore all attacks.

Equivalent to calling lua_api_enemy_set_attack_consequence_sprite(sprite, attack, "ignored") for each attack.

  • sprite (sprite): A sprite of this enemy.

enemy:has_layer_independent_collisions()

Returns whether this enemy can detect collisions with entities even if they are not on the same layer.

By default, enemies can only have collisions with entities on the same layer.

  • Return value (boolean): true if this enemy can detect collisions even with entities on other layers.

enemy:set_layer_independent_collisions([independent])

Sets whether this enemy can detect collisions with entities even if they are not on the same layer.

By default, enemies can only have collisions with entities on the same layer. If you set this property to true, this enemy will be able to hurt the hero even from a different layer.

  • independent (boolean, optional): true to make this enemy detect collisions even with entities on other layers. No value means true.

enemy:get_treasure()

Returns the pickable treasure that will drop this enemy when killed.

  • Return value 1 (string): Name of an equipment item. nil means no item dropped (in this case, other return values are nil too).
  • Return value 2 (number): Variant of this equipment item (1 means the first variant).
  • Return value 3 (string): Name of the boolean value that stores in the savegame whether the treasure dropped is found. nil means that the treasure is not saved.

enemy:set_treasure([item_name, [variant, [savegame_variable]]])

Sets the pickable treasure that will drop this enemy when killed.

  • item_name (string, optional): Name of an equipment item. nil or no value means no item.
  • variant (number, optional): Variant of this equipment item (1 means the first variant). The default value is 1.
  • savegame_variable (string, optional): Name of the boolean value that stores in the savegame whether the treasure dropped is found. nil or no value means that the treasure is not saved.

enemy:is_traversable()

Returns whether this enemy can be traversed by other entities.

  • Return value (boolean): true if this enemy is traversable.

enemy:set_traversable([traversable])

Sets whether this enemy can be traversed by other entities.

By default, the enemy is traversable. For example, if you want to prevent the hero to pass without killing the enemy, you can use this function to make the enemy become an obstacle. But make sure that the enemy's sprite is greater than its bounding box, otherwise, the enemy cannot touch the hero (and hurt him) anymore.

  • traversable (boolean, optional): true to make this enemy traversable. No value means true.

enemy:get_obstacle_behavior()

Returns how the enemy behaves with obstacles.

  • Return value (string): "normal", "flying" or "swimming".

enemy:set_obstacle_behavior(obstacle_behavior)

Sets how this enemy should behave with obstacles. The default value is "normal". "swimming" allow the enemy to traverse water. "flying" allows the enemy to traverse holes, water and lava.

  • obstacle_behavior (string): "normal", "flying" or "swimming".

enemy:set_size(width, height)

Sets the size of the bounding box of this enemy.

The default value is 16x16 pixels. This is the effective size used to detect obstacles when moving, but the sprite of the enemy may be larger, especially for a boss.

  • width (number): Width of the enemy in pixels.
  • height (number): Height of the enemy in pixels.
Remarks
Collisions with the hero are pixel-precise and use the sprite of the enemy, not his bounding box. Therefore, this function has no influence on collisions with the hero, but only on the detection of obstacles of the map when the enemy moves.

enemy:set_origin(origin_x, origin_y)

Sets the origin point of this enemy, relative to the upper left corner of its bounding box.

This origin point property allows entities of different sizes to have comparable reference points that can be used by the engine. Indeed, when two enemies overlap, the engine needs to determine which one has to be displayed first (it is always the one with the lowest Y coordinate). Sometimes, the engine also needs to compute an angle between two entities, for example to push away an enemy that was just hit. Using the upper left corner of their bounding box would not give the correct angle (unless both entities had the same size).

The origin point is also the point of synchronization of an entity with its sprites (because again, an entity that has a given size may have sprites with different sizes).

The default values is 8,13 and is usually okay for enemies of size 16x16. See entity:get_origin() for more explanations about the origin point.

  • origin_x (number): X coordinate of the origin point in pixels, relative to the upper left corner of the enemy's bounding box.
  • origin_y (number): Y coordinate of the origin point in pixels, relative to the upper left corner of the enemy's bounding box.

enemy:restart()

Restarts this enemy.

This plays animation "walking" on its sprites, destroys any timer of the enemy and calls the event enemy:on_restarted().

This function has no effect if the enemy is dying.

enemy:hurt(life_points)

Hurts this enemy if he is currently vulnerable.

If the enemy is vulnerable, the hurting animation and sound start and the given number of life points are removed.

Nothing happens if the enemy is currently invulnerable (for example because he is already being hurt).

  • life_points (number): Number of life points to remove from the enemy.
Remarks
If you just want to silently remove some life, call enemy:remove_life() instead.

enemy:immobilize()

Immobilizes this enemy for a while if possible.

After a few seconds, the enemy shakes and then restarts.

enemy:create_sprite(animation_set_id, [sprite_name])

Creates a sprite for this enemy.

  • animation_set_id (string): Animation set to use for the sprite.
  • sprite_name (string, optional): An optional name to identify the created sprite. Only useful for entities with multiple sprites (see entity:get_sprite()).
  • Return value (sprite): The sprite created.
Remarks
If you don't create a sprite, your enemy will be invisible.

enemy:remove_sprite([sprite])

Removes and destroys a sprite of this enemy.

The sprite must have been created before by enemy:create_sprite().

  • sprite (sprite): The sprite to remove. The default value is the first sprite that was created.

enemy:create_enemy(properties)

Creates another enemy on the map, specifying its coordinates as relative to the current enemy.

This function is similar to map:create_enemy() but the coordinates are relative to the current enemy, and the layer is the one of the current enemy by default.

  • properties (table): A table that describes all properties of the enemy to create. Its key-value pairs must be:
    • name (string, optional): Name identifying the entity. If the name is already used by another entity, a suffix (of the form "_2", "_3", etc.) will be automatically appended to keep entity names unique. No value means no name.
    • layer (number, optional): The layer, between map:get_min_layer() and map:get_max_layer(). No value means the same layer as the current enemy.
    • x (number, optional): X coordinate on the map, relative to the current enemy. The default value is 0.
    • y (number, optional): Y coordinate on the map, relative to the current enemy. The default value is 0.
    • direction (number, optional): Initial direction of the enemy, between 0 (East) and 3 (South). The default value is 3.
    • breed (string): Model of enemy to create.
    • savegame_variable (string, optional): Name of the boolean value that stores in the savegame whether this enemy is dead. No value means that the enemy is not saved. If the enemy is saved and was already killed, then no enemy is created. Instead, its pickable treasure is created if it is a saved one.
    • treasure_name (string, optional): Kind of pickable treasure to drop when the enemy is killed (the name of an equipment item). If this value is not set, or corresponds to a non obtainable item, then the enemy won't drop anything.
    • treasure_variant (number, optional): Variant of the treasure (because some equipment items may have several variants). The default value is 1 (the first variant).
    • treasure_savegame_variable (string, optional): Name of the boolean value that stores in the savegame whether the pickable treasure of this enemy was obtained. No value means that the state of the treasure is not saved. If the treasure is saved and the player already has it, then the enemy won't drop anything.
  • Return value (enemy or pickable treasure): The enemy created, except when it is a saved enemy that is already dead. In this case, if the enemy dropped a saved treasure that is not obtained yet, this pickable treasure is created and returned. Otherwise, nil is returned.

Events inherited from map entity

Events are callback methods automatically called by the engine if you define them.

Enemies are particular map entities. Therefore, they inherit all events from the type map entity.

See Events of all entity types to know these events.

Events of the type enemy

The following events are specific to enemies.

enemy:on_update()

Called at each cycle while this enemy is alive.

Remarks
As this function is called at each cycle, it is recommended to use other solutions when possible, like timers and other events.

enemy:on_suspended(suspended)

Called when the map has just been suspended or resumed.

The map is suspended by the engine in a few cases, like when the game is paused or when the camera is being moved by a script. When this happens, all map entities stop moving and most sprites stop their animation.

  • suspended (boolean): true if the map was just suspended, false if it was resumed.

enemy:on_created()

called when this enemy has just been created on the map.

enemy:on_enabled()

called when this enemy has just been enabled.

enemy:on_disabled()

called when this enemy has just been disabled.

enemy:on_restarted()

Called when this enemy should start or restart its movement and timers because something happened. For example, the enemy has just been created, or it was just hurt or immobilized, or you called enemy:restart(). If your enemy should move, this is the right place to create its movement.

Timers associated to the enemy were automatically destroyed. Thus, you should also recreate them from this event.

enemy:on_pre_draw()

Called just before the enemy is drawn on the map. You may display additional things below the enemy.

enemy:on_post_draw()

Called just after the enemy is drawn on the map. You may display additional things above the enemy.

enemy:on_collision_enemy(other_enemy, other_sprite, my_sprite)

Called when a sprite of this enemy overlaps another enemy's sprite.

  • other_enemy (enemy): Another enemy.
  • other_sprite (sprite): A sprite of that other enemy.
  • my_sprite (sprite): A sprite of the current enemy.

enemy:on_custom_attack_received(attack, sprite)

Called when this enemy receives an attack with a custom effect.

This function is called if you have set consequence of the attack to "custom". You have to define what happens, for example hurting the enemy, making a special reaction, etc.

  • attack (string): The attack that was received: "sword", "thrown_item", "explosion", "arrow", "hookshot", "boomerang" or "fire".
  • sprite (sprite): The sprite of this enemy that receives the attack, or nil if the attack does not come from a pixel-precise collision.

enemy:on_hurt_by_sword(hero, enemy_sprite)

Called when this enemy is successfully hurt by the sword of the hero.

You should define this event to customize the damage inflicted by the sword.

This event can only be called if the reaction to the "sword" attack is hurting the enemy.

At this point, the enemy is in the state of being hurt. His hurting animation and sound have just started. This is a good time to remove some life points with enemy:remove_life().

By default, if you don't define this event, the enemy loses a number of life points computed as his reaction to sword attacks multiplied by the sword ability level of the hero, and doubled during a spin attack.

  • hero (hero): The hero who used the sword.
  • enemy_sprite (sprite): The sprite of this enemy that was hit. You may use this information if your enemy has several sprites with different behaviors.

enemy:on_hurt(attack)

Called when this enemy is successfully hurt by any attack.

This event can only be called if the reaction to the attack is hurting the enemy.

At this point, the enemy is in the state of being hurt. His hurting animation and sound have just started and he has just lost some life.

  • attack (string): The attack that was received: "sword", "thrown_item", "explosion", "arrow", "hookshot", "boomerang" or "fire".
Remarks
In the case of a "sword" attack, this event is called right after enemy:on_hurt_by_sword().

enemy:on_dying()

Called when the enemy's life comes to 0.

When the life comes to 0, the movement of the enemy is stopped, its timers are stopped too, the dying animation starts and a sound is played. The details of the dying animation and the sound played depend on the hurt style property. If the hurt style is "enemy" or "monster", any sprite you created on the enemy is automatically removed and replaced by the sprite "enemies/enemy_killed". If the hurt style is "boss", your sprites continue to exist and to play animation "hurt", while explosions appear on the enemy.

In both cases, the enemy will be removed from the map when the dying animation ends.

Remarks
This event is called right after enemy:on_hurt().

enemy:on_dead()

Called when the enemy's dying animation is finished.

At this point, the enemy no longer exists on the map. In other words, enemy:exists() returns false, trying to get the enemy from its name returns nil, and functions like map:get_entities(prefix) won't find this enemy.

This means that you can safely use map:has_entities(prefix) from enemy:on_dead() to detect when all enemies with a common prefix are dead.

enemy:on_immobilized()

Called when the enemy is immobilized.

enemy:on_attacking_hero(hero, enemy_sprite)

Called when the hero is successfully touched by this enemy.

This event is not called if the hero was protected by his shield, or if he currently cannot be hurt for some reason, like when he is already being hurt, when he is temporarily invincible, or when he is in a special state like brandishing a treasure.

Your script can define this event to customize what bad things happen to the hero. If you define this event, the engine does absolutely nothing and lets you handle this.

If you don't define this event, the hero is hurt with the predefined behavior as follows. The hero goes to the state "hurt" where is pushed away from the enemy. He loses some life depending on the enemy's damage property, and on the hero's tunic and on hero:on_taking_damage() if defined. Then, he recovers and his sprites blink for a while. During this short period, he is temporarily invincible.

  • hero (hero): The hero being attacked.
  • enemy_sprite (sprite): The sprite of the enemy that caused the collision with the hero. You may use this information if your enemy has several sprites with different behaviors.
Remarks
If you call hero:start_hurt(), you will obtain something equivalent to the default behavior. But if you don't, keep in mind that if the hero can still be hurt after your call, this event will continue to be called while there is a collision with the enemy. To avoid this, see for example hero:set_invincible() to make the hero temporarily invincible.