-
Notifications
You must be signed in to change notification settings - Fork 32
Seamless transitions
By default, the merged map transitions respawn all players when a new section is reached. This keeps entity logic simple, but can be jarring for people who are in the middle of some puzzle or battle. Seamless transitions create the illusion that map sections are physically connected into one big map, and let players transition into new sections at their own pace.
Seamless transitions are made with relative teleports. These types of teleports move players into new areas relative to where they touched the teleport trigger. This means if you touch the trigger on the left side of a hallway, you'll end up in the left side of that hallway in the next level (assuming both maps have that same hallway). In perfect conditions, you won't even notice that you were teleported.
Not all maps can/should have seamless transitions. Many maps in sven series spawn you in completely different areas, making relative teleports more complicated to set up, and more likely to get people stuck inside walls/objects. A series might also have too many entities to perform well with relative teleports. saving_the_second_amendment
has so many monsters that if you tried to setup a merged version with teleports, the map would be unplayable due to lag. If you notice performance problems, then stick with the default level transitions, or only use relative teleports between sections with fewer monsters/entities.
In this example, I'm merging of1a1
and of1a2
. These maps are good candidates for seamless transitions because each map has an identical hallway where the level transition takes place. There aren't many monsters/entities in these maps so I'm not worried about lag either. I've merged the maps with the following command, and I'm opening the merged map in the 3D viewer.
bspguy merge test -maps "of1a1, of1a2"
The first step is to find where the level transitions are. Usually there will be a trigger_once at the end of a map, which triggers bspguy_mapchange
, although that's not guaranteed.
In the of1a1
section of the map, I have the trigger_once, so I'm going to repurpose that to be a teleport. If you didn't have an existing level-transition entity to use, you could create a new solid entity from the top menu bar (Create -> BSP Model). I want to use the existing entity because it's already sized to fit the hallway
This part may be tricky depending on the area shared between both maps. You want to find a corner or something you can align an entity with. The goal is to mark identical spots in both maps. Alignment has to be done by eye, but grid snapping helps make this easier.
There are some boxes surrounding the trigger, so I'll scale the brush to touch those. These boxes will be my reference point in the next map as well. To scale the model:
- Open the Transformation widget (press
Ctrl+M
, or right click the entity and selectTransform
) - Set
3D Axes
toScale
- Drag the colored bars to resize the model
Relative teleports use the origin of the trigger to calculate teleport positions. We could leave the model origin where it is now, but it's easier to see what's going on if we move the origin to the center of the model. To do that:
- Set
Target
toOrigin
in the Transformation widget - Look for green cube that just appeared. Many models have their origin at coordinates [0,0,0] so it might far from where you're looking now.
- Right-click the cube and select
Center
. The origin should now be at the center of the trigger. - (Optional) Right-click the cube again and select
Align
->Bottom
. I like having the teleport origins on the ground.
Create a copy of this entity and move into the exact same position in the next map. To do this:
- Copy the entity (
Ctrl+C
or right click the entity and selectCopy
) - Paste the entity (
Ctrl+V
or right click an empty space inside the map and selectPaste
) - Grab the copied entity and move it to start of the the next map (
G
or right click the entity and selectGrab
). - Ungrab the entity once it's roughly where you want it (Press
G
again or right click ->Ungrab
). - In the Transformation widget, set
Target
toObject
and set3D Axes
toMove
- Fine tune the position of the trigger with the colored bars or number inputs so that it touches the boxes at the exact same points.
We've got 2 solid entities aligned identically in both maps. These will later become trigger_teleport
ents, but first let's create the teleport destinations. Their positions must match the teleport origins.
-
Copy
the entity Paste at original origin
- Open the keyvalue editor (
Alt+Enter
or right click the entity and selectProperties
) - Switch to the
Raw Edit
tab and delete themodel
key. This converts the solid entity to a point entity. - Change class to
info_teleport_destination
(click the class button at the top or edit the key manually). - Repeat steps 1-5 for the trigger in the other map
Now time to update the keyvalues to make these teleports functional.
First, convert the triggers to relative teleports and link them to their destinations:
- Change the class of both triggers to
trigger_teleport
- Switch to the
Flags
tab in the Keyvalue Editor and enable the following flags for both triggers:Relative Teleport
Keep Angles
Keep Velocity
- Switch to the
Attributes
tab and set theName
of both teleport triggers tobspguy_nodelete
. This prevents the bspguy map script from deleting these entities (anything with abspguy
prefix will do). - Set the
Name
of theinfo_teleport_destination
in of1a1 to something likebspguy_tele_of1a1
. - Set the
Name
of theinfo_teleport_destination
in of1a2 to something likebspguy_tele_of1a2
(thebspguy
prefix is mandatory). - Set the
Target
of thetrigger_teleport
in of1a1 tobspguy_tele_of1a2
(or whatever name you used). - Set the
Target
of thetrigger_teleport
in of1a2 tobspguy_tele_of1a1
(or whatever name you used). - Set the
Teleport Cooldown Delay
of eachtrigger_teleport
andinfo_teleport_destination
to0.01
so multiple players can teleport at the same time.
Next, add a trigger to tell the bspguy map script to load the entities in the next level. Without this, the of1a2 section will be empty when you enter it.
- Select the
info_teleport_destination
in of1a2. - Set the
Target
tobspguy_mapload
. - In the
Flags
tab, enableTrigger on arrival
. - In the
Raw Edit
tab, add a new keyvalue named$s_next_map
with a value ofof1a2
. This tells the bspguy map script which map section to load.
and that's it for the keyvalue edits.
Next, we need to adjust the trigger_teleport
brushes so that they don't overlap the same areas. Otherwise, you'll teleport back to of1a1 immediately after teleporting to of1a2. Before you do this, duplicate the trigger model so that you can edit each trigger individually (right click entity -> Duplicate BSP model
).
The trigger_teleport
ents should be placed after the info_teleport_destination
ents, from the perspective of you running down the hallway to the next/previous section. Leave some room in the middle so that players can never be touching both triggers at the same time. Use the info_teleport_destination
entities for reference (they're the same size as a player).
Be careful not to move the brushes while Target
is set to Object
and 3D Axes
is set to Move
. This will move the origins of the triggers and ruin the seamless transition. If you do this by accident, copy/paste the origins of the info_teleport_destination
entities to realign the trigger_teleport
entities.
Scale
the model (Target
= Object
and 3D Axes
= Scale
) or edit the model vertices (Target
= Vertex
and 3D Axes
= Move
) to move the brushes. These actions don't affect the origin of the model.
Test it out! With some luck, you might be finished.
At this point the teleports should be working. In my case, I get stuck on one of the walls if I'm touching it during the transition. This can happen if the hallways are slightly different sizes, or just due to the inaccuracy of the collision system. Assuming the hallways are the same size, you can fix this wall sticking by slightly moving the info_teleport_destination
entities. In the Transform widget, set Grid snap
to 0
so you can move the entities by fractions of a unit. I was able to fix the sticking by moving the teleport destination 0.2 units away from the wall. Be careful not to overdo it or else you'll just get stuck inside the opposite wall.
You might notice that the lighting changes a bit in the new section. If the faces are the same size in both sections then you can copy lightmaps from the first map to the second. That feature is WIP though so chances are it just looks worse if yo do that. Make a backup of the map before experimenting. There's no undo button yet!
Lastly, Remember to add mp_telefrag 0
to the map CFG or else players will be gibbed when teleporting on top of others.
This might be easier to understand if you watch me do it.
Note: Ignore the part where I check the "Fire on Enter" flags. I thought that caused the teleport to have no cooldown, but it doesn't. Instead, set the Teleport Cooldown Delay
to 0.01 for each trigger_teleport
and info_teleport_destination
entity.