Hi! I made scripts to replace built-in teletransporters by custom entities (custom teletransporters). This is done using a function when the map has changed, which replaces automatically all built-in teletransporters of the map by the custom ones.
The point of this is that custom teletransporters, unlike the built-in ones, can interrupt teleportation if some condition is satisfied, for instance if the hero is jumping (usually over them). So this allows jumping over teletransporters, which would not be possible otherwise because built-in teleporters cannot be aborted at present. (Remark: I am using a custom jump, not the built-in one.) The scripts are very easy to use.
This is the script for the custom entity teleporter (entities/teleporter.lua):
--[[
Custom entity to teleport the hero to other map. These entities, unlike the built-in
teletransporters, allow to abort the teleportation if some condition is satisfied.
In our case, we abort the teleportation if the hero is jumping over the teleporter.
Important: in all the maps we create usual built-in teletransporters, to ease the creation
of teletransporters in the editor. Then, a scripted function defined in the map metatable
is used at runtime to replace built-in nonscrolling teletransporters with custom teleporters
when the map is loaded. The jumping state of the hero must be a boolean stored in hero.is_jumping.
--]]
local entity = ...
local sound_id, transition_style, destination_map, destination_name
function entity:on_created()
end
function entity:teleport()
if self.on_activated then self:on_activated() end -- Teleporting event.
local hero = self:get_map():get_hero()
-- Repair destination name obtained from side scrolling teletransporters.
if destination_name == "_side" then
local dir = (hero:get_direction()+2)%4
destination_name = "_side" .. dir
end
-- Teleport.
hero:teleport(destination_map, destination_name, transition_style)
end
function entity:set_sound(sound_id) sound_id = sound_id end
function entity:get_sound() return sound_id end
function entity:set_transition(transition) transition_style = transition end
function entity:get_transition() return transition_style end
function entity:set_destination_map(map_id) destination_map = map_id end
function entity:get_destination_map() return destination_map end
function entity:set_destination_name(destination) destination_name = destination end
function entity:get_destination_name() return destination_name end
And this is the main script (scripts/.../custom_teleporters.lua) which defines the replacing function:
--[[
Function to replace built-in teletransporters with custom teleporters.
This is called when the maps are loaded. Custom teleporters, unlike the built-in
teletransporters, allow to abort the teleportation if some condition is satisfied.
In our case, we abort the teleportation if the hero is jumping, so we avoid the use
of the teleporter if the hero is jumping overt it.
Important: in all the maps we create usual built-in teletransporters, to ease the creation
of teletransporters in the editor. Then we replace the non-scrolling ones with custom
teleporters.
---
Use:
1)Load the file from the game manager or other script using.
write sol.main.load_file("scripts/.../custom_teleporters.lua")(game)
2) The function game:customize_teleporters() must be called when loading any map.
This can be done using the event game:on_map_changed(map).
3) Change the value of the variable hero.is_jumping to true/false
when the hero starts/ends jumping, so that the custom teleporters can
know if the hero is jumping or not.
--]]
local game = ...
function game:customize_teleporters()
local map = game:get_map()
-- Replace non-scrolling teletransporters.
for e in map:get_entities("") do
if e:get_type() == "teletransporter" then
-- Get general properties.
local x,y,layer = e:get_position()
local name = e:get_name()
local enabled = e:is_enabled()
local origin_x, origin_y = e:get_origin()
local w, h = e:get_size()
-- Get teletransporter properties.
local on_activated = e.on_activated
local sprite = e:get_sprite()
local animation, animation_set
if sprite then
animation_set = sprite:get_animation_set()
animation = sprite:get_animation()
end
local sound_id = e:get_sound()
local destination_map = e:get_destination_map()
local destination_name = e:get_destination_name()
local transition = e:get_transition()
-- Replace teletransporter with custom entity.
e:remove()
local properties = {name = name, x = x, y = y, layer = layer,
direction = 0, model = "teleporter"}
local t = map:create_custom_entity(properties)
t:set_enabled(enabled)
t:set_origin(origin_x, origin_y)
t:set_size(w, h)
-- Mimic initial properties.
t.on_activated = on_activated -- On activated event.
if animation_set then
local new_sprite = t:create_sprite(animation_set)
new_sprite:set_animation(animation)
end
t:set_sound(sound_id)
t:set_destination_map(destination_map)
t:set_destination_name(destination_name)
t:set_transition(transition)
-- Add teleportation collision test with hero. This requires the hero not to be jumping.
local test = "center"
if transition == "scrolling" then test = "facing" end
t:add_collision_test(test, function(teleporter, other)
if other:get_type() == "hero" then
-- Condition to teleport: hero is not jumping.
if not other.is_jumping then
t:teleport() -- Activate teleportation.
end
end
end)
end
end
end
It's tested and works perfectly. Usage explanations can be found in the comments of these scripts.
I hope someone finds this useful.
EDIT: updated to solve a small problem.
This is my last version of the custom teleporter script, that uses custom entities as teleporters.
--[[
Custom entity to teleport the hero to other map. These entities, unlike the built-in
teletransporters, allow to abort the teleportation if some condition is satisfied.
In our case, we abort the teleportation if the hero is jumping over the teleporter.
Important: in all the maps we create usual built-in teletransporters, to ease the creation
of teletransporters in the editor. Then, a scripted function defined in the map metatable
is used at runtime to replace built-in nonscrolling teletransporters with custom teleporters
when the map is loaded. The jumping state of the hero must be a boolean stored in hero.is_jumping.
--]]
local entity = ...
local map = entity:get_map()
local game = map:get_game()
local hero = map:get_hero()
local sound_id, transition_style, destination_map, destination_name
function entity:on_created()
end
function entity:teleport()
if self.on_activated then self:on_activated() end -- Teleporting event.
-- If there is bad ground under the hero, abort teleportation.
local ground = map:get_ground(self:get_position())
if ground == "hole" or ground == "lava" or
( (not game:has_ability("swim")) and
ground == "deep_water"
or ground == "wall_top_right_water"
or ground == "wall_top_left_water"
or ground == "wall_bottom_right_water"
or ground == "wall_bottom_left_water"
)
then
return
end
-- Repair destination name obtained from side scrolling teletransporters.
if destination_name == "_side" then
--local dir = (hero:get_direction()+2)%4
local x,y,_ = self:get_position()
local w,h = self:get_map():get_size()
local dir = nil
if x < 0 then dir = 0 elseif x >= w then dir = 2
elseif y < 0 then dir = 3 elseif y >= h then dir = 1
end
if dir == nil then
-- A scrolling teleporter must be on the border of the map!
error("Wrong position for custom scrolling teleporter"); return
end
destination_name = "_side" .. dir
end
-- Teleport.
hero:teleport(destination_map, destination_name, transition_style)
end
function entity:set_sound(new_sound_id) sound_id = new_sound_id end
function entity:get_sound() return sound_id end
function entity:set_transition(transition) transition_style = transition end
function entity:get_transition() return transition_style end
function entity:set_destination_map(map_id) destination_map = map_id end
function entity:get_destination_map() return destination_map end
function entity:set_destination_name(destination) destination_name = destination end
function entity:get_destination_name() return destination_name end