I'm trying to force the player to get moved into a room after a separator has finished scrolling towards South.
function sub_separator_h:on_activated(3)
-- slide down.
local hero = self:get_game():get_hero()
sol.audio.play_sound("explosion")
-- Create movement.
local dir = 3
hero:freeze()
local m = sol.movement.create("straight")
m:set_speed(90)
m:set_angle(dir*math.pi/2)
m:set_max_distance(32)
m:start(hero)
function m:on_obstacle_reached()
hero:unfreeze()
end
function m:on_finished()
hero:unfreeze()
end
end
But it causes this error:
QuoteError: Failed to load script 'maps/testlevel': [string "maps/testlevel.lua"]:41: <name> or '...' expected near '3'
Line 41 is the beginning of the script here. The documentation for Separators suggests "on_activated(direction4)" only needs a number referring to the proper direction (in this case South), but I don't know how to write it so it won't throw this error.
The "direction4" parameter has to be a variable, not a value. (The value is stored in that variable when the engine automatically calls the event.) That is why you get the error.
Like Diarandor said, direction4 is a variable, here is how to use it. (This was typed before Diarandor's post had appeared.)
The function of separators "on_activated(direction4)" The information in the brackets are defined when they are called and should be stored in a variable like so:
function generic_separator:on_activated(direction4)
if direction4 == 3 then
-- Your code here
end
end
The reason this works is because when the engine calls this function, it stores the argument that you may need for a script in the variable.
However, one cannot have what they want the call back to be done like so,
function generic_separator:on_activated(3)
--Your code here
end
This does not work as putting the number three in the variable slot will produce an error as that slot is not for defining what you want that information to be, but rather for a variable that may change.
Sorry, I was too quick. :-X
But you explained it much better. :)
I've integrated my door slider into separator_manager.lua so that it can be used in dungeons.
But something unexpected is happening. With this addition, enemies prefixed with auto_enemy are no longer reset. They're simply erased. Strangely, everything else is reset just fine.
-- This script restores entities when there are separators in a map.
-- When taking separators prefixed by "auto_separator", the following entities are restored:
-- - Enemies prefixed by "auto_enemy".
-- - Destructibles prefixed by "auto_destructible".
-- - Blocks prefixed by "auto_block".
--
-- Usage from a map script:
-- local separator_manager = require("maps/lib/separator_manager.lua")
-- separator_manager:manage_map(map)
-- If you prefer, you can also enable it automatically on all maps from game:on_map_changed().
local separator_manager = {}
function separator_manager:manage_map(map)
local enemy_places = {}
local destructible_places = {}
local game = map:get_game()
local zelda = map:get_entity("zelda")
-- Function called when a separator was just taken.
local function separator_on_activated(separator)
local hero = map:get_hero()
-- Enemies.
for _, enemy_place in ipairs(enemy_places) do
local enemy = enemy_place.enemy
-- First remove any enemy.
if enemy:exists() then
enemy:remove()
end
-- Re-create enemies in the new active region.
if enemy:is_in_same_region(hero) then
local old_enemy = enemy_place.enemy
local enemy = map:create_enemy({
x = enemy_place.x,
y = enemy_place.y,
layer = enemy_place.layer,
breed = enemy_place.breed,
direction = enemy_place.direction,
name = enemy_place.name,
})
enemy:set_treasure(unpack(enemy_place.treasure))
enemy.on_dead = old_enemy.on_dead -- For door_manager.
enemy_place.enemy = enemy
end
end
-- Blocks.
for block in map:get_entities("auto_block") do
-- Reset blocks in regions no longer visible.
if not block:is_in_same_region(hero) then
block:reset()
end
end
end
-- Function called when a separator is being taken.
local function separator_on_activating(separator)
local hero = map:get_hero()
-- Enemies.
if not map.used_separator then
-- First separator: remove enemies from other regions like on_activated() does.
-- Because on_activated() was not called when the map started.
for _, enemy_place in ipairs(enemy_places) do
local enemy = enemy_place.enemy
if enemy:exists() and not enemy:is_in_same_region(hero) then
enemy:remove()
end
end
end
-- Destructibles.
for _, destructible_place in ipairs(destructible_places) do
local destructible = destructible_place.destructible
if not destructible:exists() then
-- Re-create destructibles in all regions except the active one.
if not destructible:is_in_same_region(hero) then
local destructible = map:create_destructible({
x = destructible_place.x,
y = destructible_place.y,
layer = destructible_place.layer,
name = destructible_place.name,
sprite = destructible_place.sprite,
destruction_sound = destructible_place.destruction_sound,
weight = destructible_place.weight,
can_be_cut = destructible_place.can_be_cut,
can_explode = destructible_place.can_explode,
can_regenerate = destructible_place.can_regenerate,
damage_on_enemies = destructible_place.damage_on_enemies,
ground = destructible_place.ground,
})
-- We don't recreate the treasure.
destructible_place.destructible = destructible
end
end
end
end
for separator in map:get_entities("auto_separator") do
separator.on_activating = separator_on_activating
separator.on_activated = separator_on_activated
--door slider
function separator:on_activated(direction4)
if direction4 == 0 then
local hero = self:get_game():get_hero()
local heroanim = hero:get_animation()
hero:set_animation(heroanim)
local dir = 0
hero:freeze()
local m2 = sol.movement.create("straight")
m2:set_speed(90)
m2:set_angle(dir*math.pi/2)
m2:set_max_distance(32)
m2:start(hero)
hero:set_animation(heroanim)
function m2:on_obstacle_reached()
hero:unfreeze()
end
function m2:on_finished()
hero:unfreeze()
end
end
if direction4 == 1 then
local hero = self:get_game():get_hero()
local heroanim = hero:get_animation()
hero:set_animation(heroanim)
local dir = 1
hero:freeze()
local m2 = sol.movement.create("straight")
m2:set_speed(90)
m2:set_angle(dir*math.pi/2)
m2:set_max_distance(24)
m2:start(hero)
hero:set_animation(heroanim)
function m2:on_obstacle_reached()
hero:unfreeze()
end
function m2:on_finished()
hero:unfreeze()
end
end
if direction4 == 2 then
local hero = self:get_game():get_hero()
local heroanim = hero:get_animation()
hero:set_animation(heroanim)
local dir = 2
hero:freeze()
local m2 = sol.movement.create("straight")
m2:set_speed(90)
m2:set_angle(dir*math.pi/2)
m2:set_max_distance(32)
m2:start(hero)
hero:set_animation(heroanim)
function m2:on_obstacle_reached()
hero:unfreeze()
end
function m2:on_finished()
hero:unfreeze()
end
end
if direction4 == 3 then
local hero = self:get_game():get_hero()
local heroanim = hero:get_animation()
hero:set_animation(heroanim)
local dir = 3
hero:freeze()
local m = sol.movement.create("straight")
m:set_speed(500)
m:set_angle(dir*math.pi/2)
m:set_max_distance(32)
m:start(hero)
hero:set_animation(heroanim)
function m:on_obstacle_reached()
hero:unfreeze()
end
function m:on_finished()
local dir = 3
local m2 = sol.movement.create("straight")
m2:set_speed(90)
m2:set_angle(dir*math.pi/2)
m2:set_max_distance(16)
m2:start(hero)
hero:set_animation(heroanim)
function m2:on_obstacle_reached()
hero:unfreeze()
end
function m2:on_finished()
hero:unfreeze()
end
end
end
end
end
for separator in map:get_entities("sub_separator") do
--door slider
function separator:on_activated(direction4)
if direction4 == 0 then
local hero = self:get_game():get_hero()
local heroanim = hero:get_animation()
hero:set_animation(heroanim)
local dir = 0
hero:freeze()
local m2 = sol.movement.create("straight")
m2:set_speed(90)
m2:set_angle(dir*math.pi/2)
m2:set_max_distance(32)
m2:start(hero)
hero:set_animation(heroanim)
function m2:on_obstacle_reached()
hero:unfreeze()
end
function m2:on_finished()
hero:unfreeze()
end
end
if direction4 == 1 then
local hero = self:get_game():get_hero()
local heroanim = hero:get_animation()
hero:set_animation(heroanim)
local dir = 1
hero:freeze()
local m2 = sol.movement.create("straight")
m2:set_speed(90)
m2:set_angle(dir*math.pi/2)
m2:set_max_distance(24)
m2:start(hero)
hero:set_animation(heroanim)
function m2:on_obstacle_reached()
hero:unfreeze()
end
function m2:on_finished()
hero:unfreeze()
end
end
if direction4 == 2 then
local hero = self:get_game():get_hero()
local heroanim = hero:get_animation()
hero:set_animation(heroanim)
local dir = 2
hero:freeze()
local m2 = sol.movement.create("straight")
m2:set_speed(90)
m2:set_angle(dir*math.pi/2)
m2:set_max_distance(32)
m2:start(hero)
hero:set_animation(heroanim)
function m2:on_obstacle_reached()
hero:unfreeze()
end
function m2:on_finished()
hero:unfreeze()
end
end
if direction4 == 3 then
local hero = self:get_game():get_hero()
local heroanim = hero:get_animation()
hero:set_animation(heroanim)
local dir = 3
hero:freeze()
local m = sol.movement.create("straight")
m:set_speed(500)
m:set_angle(dir*math.pi/2)
m:set_max_distance(32)
m:start(hero)
hero:set_animation(heroanim)
function m:on_obstacle_reached()
hero:unfreeze()
end
function m:on_finished()
local dir = 3
local m2 = sol.movement.create("straight")
m2:set_speed(90)
m2:set_angle(dir*math.pi/2)
m2:set_max_distance(16)
m2:start(hero)
hero:set_animation(heroanim)
function m2:on_obstacle_reached()
hero:unfreeze()
end
function m2:on_finished()
hero:unfreeze()
end
end
end
end
end
-- Store the position and properties of enemies.
for enemy in map:get_entities("auto_enemy") do
local x, y, layer = enemy:get_position()
enemy_places[#enemy_places + 1] = {
x = x,
y = y,
layer = layer,
breed = enemy:get_breed(),
direction = enemy:get_sprite():get_direction(),
name = enemy:get_name(),
treasure = { enemy:get_treasure() },
enemy = enemy,
}
end
local function get_destructible_sprite_name(destructible)
-- TODO the engine should have a destructible:get_sprite() method.
-- As a temporary workaround we use the one of custom entity, fortunately
-- it happens to work for all types of entities.
local sprite = sol.main.get_metatable("custom_entity").get_sprite(destructible)
return sprite ~= nil and sprite:get_animation_set() or ""
end
-- Store the position and properties of destructibles.
for destructible in map:get_entities("auto_destructible") do
local x, y, layer = destructible:get_position()
destructible_places[#destructible_places + 1] = {
x = x,
y = y,
layer = layer,
name = destructible:get_name(),
treasure = { destructible:get_treasure() },
sprite = get_destructible_sprite_name(destructible),
destruction_sound = destructible:get_destruction_sound(),
weight = destructible:get_weight(),
can_be_cut = destructible:get_can_be_cut(),
can_explode = destructible:get_can_explode(),
can_regenerate = destructible:get_can_regenerate(),
damage_on_enemies = destructible:get_damage_on_enemies(),
ground = destructible:get_modified_ground(),
destructible = destructible,
}
end
end
return separator_manager