Hi !
Have you ever wanted to have those pipes in Crystal Palace of MoS DX move your characters automagically ? Then this script is for you !
--A simple string splitter, found on the Internet.
--Used for extracting parameters in the sensor name.
--You might want to use your own version to avoid possible license issues
local function string_split(source, delimiters)
local elements = {}
local pattern = '([^'..delimiters..']+)'
string.gsub(source, pattern, function(value)
elements[#elements + 1] = value
end)
return elements
end
--A simple yet powerful pipe system like in A link to the Past Turtle Rock
--Usage : Place a series of sensors on the map, then name them as this :
--pipe_<path_id>_<path_index>
--Warning : you MUST set the indexes to a continuous way (1,2,3,...) or else you will be stuck in the middle of the movement.
--Notice : While it requires nothing but requiring this script in the main file to run, you might want to use en event register like in Christopho's projects
--as it overwrites the sensors' on_activated event
local sensor_meta=sol.main.get_metatable("sensor")
function sensor_meta:on_activated()
local name=self:get_name()
local map=self:get_map()
local hero=map:get_hero()
if name~=nil then
local type=string_split(name,"_")
if type[1]=="pipe" then
--We are now in the pipe, either on en end or in the middle of it.
if not sensor_meta.pipe_active then
--Actually entering the pipe
length=map:get_entities_count("pipe_"..type[2])
hero:freeze()
hero:set_visible(false)
--detecting whether we are going in the increasing index order or not
local reversed=(tonumber(type[3])==length)
local next
if reversed then
next=length-1
else
next=2
end
--Saving settings in the metatable for later usage
sensor_meta.pipe_next=next
sensor_meta.pipe_is_reversed=reversed
sensor_meta.pipe_length=length
sensor_meta.pipe_active=true
else
--Already in the pipe and continuing the movement
if sensor_meta.pipe_is_reversed then
sensor_meta.pipe_next=sensor_meta.pipe_next-1
else
sensor_meta.pipe_next=sensor_meta.pipe_next+1
end
end
--Actually start the movement
if sensor_meta.pipe_next==0 or sensor_meta.pipe_next==sensor_meta.pipe_length+1 then
--We are about to finish the move : make the hero walk out of the pipe
local movement=sol.movement.create("path")
local dir=sensor_meta.pipe_outDir or 0
local path={dir,dir}
movement:set_path(path)
hero:set_visible(true)
hero:set_direction(dir/2)
hero:set_animation("walking")
movement:start(hero,function()
hero:unfreeze()
sensor_meta.pipe_active=false
end)
else
--making the quick auto move in the pipe (and bonk in the corners)
--Feel free to change this sound to your own !
sol.audio.play_sound("bomb")
local movement=sol.movement.create("target")
local target="pipe_"..type[2].."_"..sensor_meta.pipe_next
movement:set_target(map:get_entity(target))
movement:set_speed(192)
movement:start(hero)
--Saving the movement direction for when we will leave the pipe
sensor_meta.pipe_outDir=2*movement:get_direction4()
end
end
end
--And that(s all folks !
end
Note: if you find a simpler way, don't hesitate to tell me, i'll be happy to rework my code as a challenge !
Enjoy !
edit : correction of misnamed function call originally using another file.
edit #2 : correction of movement:set_garget :
It used map:get_entities(target)(1), now it uses map:set_entity(target) since now you should have ensured all sensors have a unique ID.
edit #3 : fixed a possible issue when you try to make a pipe with only 1 sensor.
+ fixed comments indentation, removed some typo and removed remaining debug prints.