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.
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.
Code (lua) Select
-- 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