What permissions do you give others to modify and/or maintain your submission?
Modify: ASK ME - Maintain: IN MY ABSENCE - Others must ask me for permission before modifying my submission or use it in their own work, and I reserve the right to say no for any reason. However, if I can no longer be contacted, I give permission for my entire submission to be maintained by others.

The script that powers ChronoShift Zone. Time Travel is a mechanic that allows players to move between two different versions of your level, labeled as Past and Future respectively.

You are able to pack this script into your levels as long as you credit me, same as if it was normally reusable. Instead of trying to modify the script to your own ends, I encourage you to instead make a Pull Request in the project's GitHub page (press More Information on the sidebar) if you need a different behaviour to happen or new features.

If you need to interface with it or change something, but you can do it using a companion script that works alongside Time Travel, then use a companion script and lock this functionality to your level instead (use a level header for this). You don't need my permission to use companion scripts (as long as you credit me for the original mechanic, of course.)

Oh, and the code is licenced using GPL v2. Go nuts if you want to make your own version or port it (credit me though, it's in the rules).

The requirements for Time Travel to work are:
  • Two copies of the same level, Past (where players will originally appear) and Future (where players will travel to). Use of the MobjScale level header is encouraged to make this work.
  • Set the required level header parameters (see below) for the teleport offset, minimap boundaries, sky number, skybox ID, and music that will play in the future version of the map.
  • For the Future version of the level, you must give all Boss Waypoints the [4] Special flag.
  • Create a minimap for the Future version of the level. A normal minimap lump name would be MAP??R, whereas for Future minimaps it will be MAP??RI.
  • And naturally, pack all of the Lua scripts, graphics and sound effects from the Time Travel .pk3 to your level.

Look at KRL_TimeTravel_ExampleMap_v1.pk3 for an example level with the mechanic working.

Level Headers

Level HeaderDescription
Lua.TT_2ndMapXYOffsetTakes two comma-delimited numbers for the X and Y offset for the Future version of the level (for example. 16640,0). This offset will be used for time travel teleports and echo positioning. This should be as accurate as possible so the time travelling looks seamless!

The best way to obtain this value is by using Zone Builder's Draw Rectangle Tool, clicking somewhere in the Past version of the level (preferably the corner of a room, for example), and then place your cursor on the equivalent part of the level in the Future version of the map. The width and height of this rectangle will be the offset you set in this header.
Lua.MMLib_LLBounds & Lua.MMLib_URBoundsTakes two comma-delimited numbers that define the lower left position and the upper right position of the Past level's boundaries (for example, -30848,16512 and -15616,31872 respectively). This is used for the minimap boundaries.

In the lower right of Zone Builder's interface, wherever you place your cursor will show you the absolute position it would be in the level. Place your cursor on the lower left position and the upper right position of the level's boundaries, including the empty space, note it, and put it as these level headers.
Lua.TT_2ndMapSkyNumTakes a sky number (for example. 8482). This is the sky texture that will be used when the player is in the future version of the level.
Lua.TT_2ndMapSkyBoxIDTakes a skybox ID number (for example, 1). This is the Skybox ID to be used for the Future version of the level.
Lua.musname_futureOptional. This is the music lump that will play when the player is on the Future version of the level.

An example SOC with all the level headers set would look like this:
Sonic Object Configuration (SOC):
Level 1
LevelName = Time Travel Test
SubTitle = travelma
TypeOfLevel = Race
NumLaps = 7
SkyNum = 88
Music = KMAP01
RecordAttack = true
NoVisitNeeded = true
Lua.TT_2ndMapXYOffset = 25600,25600
Lua.MMLib_LLBounds = -31872,-31872
Lua.MMLib_URBounds = -26496,-26496
Lua.TT_2ndMapSkyNum = 1018
Lua.TT_2ndMapSkyBoxID = 1
Lua.musname_future = FMAP01


Set up the Starposts and Boss Waypoints the same exact way in both versions of the level, on the same exact equivalent positions. For the Future version of the level, the Boss Waypoints MUST have the [4] Special flag set.

Use kartdebugcheckpoint to debug checkpoints in both the Past and Future versions of the level. If Time Traveling gives you completely different PREV and NEXT values between Past and Future (or the Future checkpoints give you a 0 in both values), then you have set them up wrong! Make sure that a player can't get an inherently better position just by being on a different timeline.


The minimap for the Future version of the level should be named MAP??RI, and the Past minimap should be MAP??R, the same way as normal minimaps are named (?? reflects your map number). I recommend an inverted color version of the same minimap as the Past version with the appropriate layout changes reflected unto it.

In case you already made both the Past and Future versions of the level, but have no minimap, then temporarily remove the Future version of the level in Zone Builder, save the changes, then Save Map Image in SLADE. Do the minimap process as one would normally do it, then Undo the Future level removal in Zone Builder.


Adding music to the future version of the level (using Lua.musname_future) is optional, but adds a tremendous amount of charm to it. When a player time travels, the position of the music will be preserved (in order words, a song being 10 seconds into it in the Past will be 10 seconds into it in the Future).

Make sure that the BPM (beats per minute) between both the Past and the Future songs are the same, otherwise it will not sound seamless at all. The duration between both songs can vary, but their difference in length should not be obvious! You still need to loop point both songs as per usual.

You can make BPM changes to songs using Audacity.


Keep the following guidelines in mind when you make a Time Travel-capable map:
  • Allow the player to intuit changes to the layout from both timelines.
    • For example, in ChronoShift, glass is always broken in the Future, and layout changes are denoted by different obvious flats used and warning tapes in unmissable yellows.
    • Players who teleport into walls will be crushed, up to a certain leniency to account for slopes. Give the player the information that they may teleport into a wall by using FoFs, different flats, map elements, etc..
  • Give players reasons to Time Travel.
    • Each version of the map could provide different cuts, or different routes. Your creativity is key here.
    • Give players reasons to be on different timelines at any given time.
  • Avoid mandatory Time Travel.
    • Because players can't time travel while holding an item, both Past and Future layouts should be finishable by themselves.
    • No worries if one layout is slower than the other, this just encourages players to use their items so they may take the better route.
  • Time Travel should be seamless.
    • Check, double check, and triple check that the offset you provided in Lua.TT_2ndMapXYOffset is accurate. If not, it immediately breaks the illusion and just looks like a shoddy teleport from place to place. Use the Draw Rectangle Tool in Zone Builder to make sure you have the correct offsets.
    • The best way to check is simply by standing still at a place in your level and simply Time Travel. Make sure all important layout elements stay the same.
  • Past and Future need to be visually, noticeably different.
    • Use different colors for each layout, or even different visuals altogether.
    • The idea here is that the player should never confuse the Past and Future versions of the level as they play through them.
  • You still need to make a level.
    • Time Travel as a mechanic is not a substitute for good level design, good visual design or a good layout.
    • Time Travel can serve to accentuate an already good layout or design by giving players two versions to play with.
  • Build with Time Travelling in mind.
    • Don't retrofit it into your already existing levels, if you have them.
    • Time Travelling should always be providing choices and be an engaging mechanic. Don't use it just to provide cuts or as visual dressing.
  • Give players an introductory setpiece to Time Travel
    • You can use the intro cutscene to show things changing around the player, as an antepiece of sorts.
    • An early setpiece into the level should change the level layout noticeably. For example, in ChronoShift, a setpiece early into the level involves glass bridges and warning-taped pipes. Time traveling here swaps the playable ground into ramps created by the pipes or the bridges respectively. Make sure to have a checkpoint just before this so players don't get overly punished.

And of course, for an example on all this gets tied together, play ChronoShift Zone from the ChronoShift Track Pack.


Seemingly making two levels in one sounds overwhelming, but don't worry! Here's some pointers on how to accomplish this.
  • MobjScale your map (to half, for example). Unless you know for a fact how big the layout will be, so you can fit both Past and Future versions, this is a safe choice.
  • At a minimum, start by creating a layout, adding item sets, checkpoint it(!), and then drive around it and make sure it works and is finishable.
    • If you don't think you'll change the layout anymore, it can be a good idea to save a map image from SLADE as well at this point and do the Past minimap.
  • Get the lowest left and upper right points of the level to set the minimap boundaries into the Lua.MMLib_LLBounds and Lua.MMLib_URBounds level headers respectively. Check the Level Header section for details.
  • Select the entire level in Zone Builder, copy it and then paste it, either above it or onto its sides. Then use the Draw Rectangle Tool and, for example, use one of the corners of the Finish Line (like the upper right one) and move your cursor to the equivalent corner. The displayed width and height will be the X and Y offset you set in Lua.TT_2ndMapXYOffset.
  • With the Future version of the layout, do the following:
    • Make sure all tag-related elements in your level, like slopes and FoFs, still work in your level.
    • Select all Boss Waypoints in the Future version of your level. The best way to do this in Zone Builder is through Edit > View Thing Types, check Hide Unused Things, click on Boss Waypoint, then CTRL+Drag around the entirety of the Past version of the level - this should deselect all Past Boss Waypoints. Then right click a Boss Waypoint in the Future version on the select and check [4] Special, these will mark these Boss Waypoints to be used for the Future version of the level.
    • Set Lua.TT_2ndMapSkyNum and Lua.TT_2ndMapSkyBoxID for your sky texture and skybox ID respectively.
  • Drive around again, now with Time Travel enabled in your level. Make sure that Time Travelling looks seamless and that the checkpoints aren't broken (use kartdebugcheckpoint On).
  • Now do all changes you want to do in the Future version of your level! Destroy things around or make them prettier, add or remove things, do what you want as long as the base layout is the same.
  • When you're done, make the Future version of the minimap. Make sure it uses inverted colors compared to the Past version.
    • You can do this using the Past version as a base, and reflecting the relevant layout changes.
    • Or you can do this by deleting the Past version in Zone Builder temporarily, saving this change, using `Save Map File` in SLADE, then redo the minimap.

Congratulations, you made a Time Travel-capable level!

Closing Words


  • JugadorXEI: All of the programming.
  • Mr.Logan: All the graphics in the addon.
  • Diggle: For the initial layouts that helped solidify how levels with Time Travel should work.
  • minenice: For xItemLib, which is used as a dependency.
  • cotomili: Bird.
  • Sonic Team, Valve Software and Respawn Entertainment for the SFX.
  • Special thanks to everyone who helped us test, like, three different layouts of ChronoShift at the time.

Breaking the absolute limits with this addon has been a lot of fun. Good luck breaking them as well!

Have fun!
First release
Last update
5.00 star(s) 2 ratings

More resources from JugadorXEI

Share this resource

Latest updates

  1. 1.1.2

    Fixed a missing validation check on waypoints processing. Fixed a missing validation check with...
  2. 1.1.1

    Fixed waypoints and items processing halting if player joins mid-game. Fixed a Lua warning...
  3. 1.1.0

    Removed XItemLib as a dependency for Time Travel - a base-game fix is applied for item odds...

Latest reviews

I was blown away when I discovered paragliders and I'm now blown away by time travel (And no I don't have a chronoshift bias). I can't give much feedback regarding performance but LD wise it has TONS of potential.
Upvote 0
wow this is such a cool mechanic someone should make a map out of it (play chronoshift)
Upvote 0