Welcome back.
Now we have a couple different types of checkpoint actors.
We have our typical checkpoint which saves progress when we reach it.
We also have a beacon which doesn't save progress, but it is a saved actor in a sense that it implements
the save interface and has a boolean marked with save game and it's you property.
So even though it doesn't really cause us to save any progress, it will be saved.
Now, in addition to these actors, I'd like another type of actor that's sort of related to these.
I wanted to share some of their behaviors.
I would like it to be highlight able.
I would like to be able to click on it and move to a specified location on that actor.
But once I reach that location on the actor, I want to transition levels.
I want to go to a new map.
So for that reason, I'm going to take our checkpoint class and subclass it into another class.
And this one I'd like to subclass in C plus.
Plus.
We've seen that the checkpoint class is versatile enough to be able to subclass it and blueprint, and
that's indeed what we did with our beacon.
I'd like to subclass it in C plus plus and add a couple new things.
So we're going to create a new C plus plus class.
I'm going to go into the checkpoint folder and base this on our checkpoint C plus plus class.
And I can call this class Map entrance.
Now these are going to be used to transition from one map to another and even back to a previous map.
And while we may have map entrances and map exits, a map exit is really just another map entrance,
isn't it?
It's going to take you to another map.
So really, exits and entrances are all just entrances.
So we'll call them all map entrances.
And this will take us from one map to another.
Let's click on Create Class.
And we can go ahead and close down the engine and go to our new map entrance class.
I'll go ahead and close all tabs for now and open up checkpoint map entrance dot h and open the cpp
file.
Now what does our map entrance need that our checkpoint does not have?
Well, for one it needs to know what map we'd like to travel to.
That's one thing, and another is it's going to override what happens when we overlap with its overlap
volume.
If we open checkpoint dot h, we'll see that we have an en sphere overlap.
And we had the foresight to mark it virtual just in case future subclasses wanted to override and provide
their own functionality for it.
Now.
In addition, we have a couple of highlight interface functions.
We have highlight actor implementation Unhighlight actor.
These are blueprint native events, which means we can have part of their implementation in C plus plus
and part in blueprint.
And that may be the case for what we want.
We also have a set move to location.
Now set move to location sets out destination at least in checkpoint to the location of the scene component.
Move to component.
That's the behavior that I still want to have in my map entrance, so I don't think we need to override
that function.
We can override the highlight functions though.
Let's see what they're doing here in checkpoint.
If we go to checkpoint, we see that we're checking B is reached before setting render custom depth.
Now in the case of my map entrance, if I've already reached a map entrance and I go to another map,
then say come back to that previous map, I really don't care if I've reached it, I still want to be
able to highlight it.
So in our case, we're going to want to remove that check be reached as I don't care if we've reached
it or not.
I want to highlight it regardless.
So we'll go ahead and implement highlight actor and Unhighlight actor.
We don't actually need to overwrite Unhighlight actor, do we?
At least not in C plus plus if we don't want to, but we should override highlight actor to remove that
if B reached check.
So I'm going to take just all of this since I want these comments to and paste them here in a public
section in my map entrance.
But I'm going to remove all except for highlight actor.
That's the only one that I want to override, and I'm going to generate this definition.
And all I want to do is steal this checkpoint mesh set render custom depth to true from checkpoint.
I'm going to put that right here.
The only difference is we're no longer checking that boolean.
So that's good.
Now we need to think about what map entrance needs that checkpoint doesn't have.
And I can think of two things.
One is the map that I'd like to travel to.
Once we reach this map entrance, we can call that destination map, and this can be a t soft object
pointer of type Uworld and we can set this in our blueprint.
We can call this destination map.
And we can give this a u property with edit.
I'd like it edit anywhere so we can set this on instances in the world.
Another one I can think of is an F name for the player start tag that we would like to spawn in at in
the other world, so this can be our destination player start tag.
We can make this edit anywhere as well.
So that way when we reach a map entrance and we travel to the destination map, we can spawn in at a
specific player start.
And that can be really anywhere we choose on this particular blueprint.
So with that, the last thing here in C plus plus perhaps is our overlap function.
We're going to want to override on sphere overlap.
That's going to be in the protected section.
So we'll go ahead and copy all of this and paste it here.
We'll create a protected section here.
But we can't have you function on an override.
That quality of being a U function is just inherited.
Now writer says light bulb add the override specifier.
All right thanks writer.
We'll go ahead and add that.
And we'll generate the definition writers asking if I want to wrap the long line.
Sure.
Go ahead.
And finally we can generate the definition.
And we don't want to call super do we.
Because super is going to let's see what it does.
It's going to set breach to true.
It's going to save the world state and it's going to execute, save progress and handle glow effects.
Now when I reach a map entrance, saving the world state is a good idea for saving the player.
Progress is also a good idea.
Notice that this involves saving the player start tag as well.
But the thing is, I don't necessarily want to save the player start tag of this particular checkpoint.
I want to save the player start tag of the checkpoint we're going to in the other level.
So we are going to want our own implementation of this, but it's going to be almost the same.
We can copy this if statement and come back to map entrance and we can replace super.
We don't want to call super outright, but what we can do is a modified version of this.
I'm going to include player interface.
We're going to check if the other player implements it.
Now, if you want to save be reached, that's fine.
We're not using it to prevent highlighting anymore.
But remember, if we set be reached to true, what does the checkpoint do?
Well, it implements load actor implementation, which calls handle glow effects.
So as soon as this actor is loaded in.
If be reached is true.
Well, the glow effects are started off immediately.
We may not want that with map entrances.
In fact, I personally don't.
But all we really need to do is override the load actor implementation and decide what we do with it.
So we have a choice.
We either don't set breech to true, or we override load actor implementation and simply don't do anything
in it if we don't want to.
Since reaching a particular map entrance is something we may want to know.
I'm going to go ahead and leave it and just override load actor implementation.
Let's go and find that it's on the Save Actor interface.
It also overrides should load transform, but the checkpoint sets this to false.
It returns false anyway.
So that's the behavior I want.
I don't need to override it to have that same behavior.
But in the map entrance.
We can go ahead and override load actor implementation to provide the behavior we want.
And I just want to do nothing.
So I'm going to go ahead and generate the definition.
And just put a comment.
So it's clear that we meant for this function to do nothing.
We're going to say do nothing when loading a map entrance.
Now back in on sphere overlap.
Do we want to save the world state?
We do.
However, we're going to keep in mind later that we may wish to save additional information about the
map we're traveling to, because in the HUD, we're showing the map that a given player is in, and
we're going to need to save whatever that map is if we're changing that and loading back into it.
So that's something we have to keep in mind here.
We are going to include or a game mode base.
And we're going to include you gameplay statics as well.
But we might want to put a to do here.
Save the world we are going to or I should say travel.
Traveling to.
Because this almost sounds like a Yoda phrase save the world we are going to, right?
We're not going to save the world.
We're traveling to a world we want to save.
But other than that, when we execute save progress here in a map entrance, I want to execute save
progress passing in our destination player start tag instead of our player start tag and of course save
world state could have an overload that takes in perhaps the name of the new world that we'd like to
travel to and then otherwise does everything the same.
So let's take a look at our game mode base.
We have saved world state.
Let's see what that's doing.
So save World State is going to save all the actors in the world, right?
It also gets our save slot data.
And once we have this save game object, if we did pass in, say, a world string, we could overwrite
a world string that maybe we're saving as the world that we're in right now.
The save game object load screen save game does have the map name, but this is not the actual asset
name.
This is the name of the map that we see in the HUD in the beginning in the load screen, we could have
another one for the map asset name as well.
We could say F string map asset name here.
And if we never set it we can set its value to default map asset name.
So we know that it's unset and save world state could take in an optional F string.
We could pass it in const f string reference, and we can give it a default value of f string the empty
string.
And if it's the empty string, we can do nothing.
We'll call this in World Asset Name.
Actually, let's call this destination.
Map.
Asset name.
So it's an optional input parameter.
Let's add that right here to save World State and we'll check first thing.
If this is an empty string, we'll do this.
Once we have the save game, we'll say right here.
If destination map asset name.
And we'll just say if it's not equal to the empty string.
And let's be explicit here.
Let's put quotes with an empty actual string here.
So we know that its literal value is double quotes with nothing in there.
If it's not the empty string, then we can save that destination map asset name.
This means we're changing to a new world.
We can say save game map asset name equals destination map asset name.
And we can also set that map name, which is the user facing text we see in our HUD.
But what I'd like is an easy to use function that can get the user facing name from our asset name.
So let's make a function that can easily do that.
We're going to put it right next to our maps t array.
We're going to say f string.
We'll call this get map name from map asset name.
And we'll take in a const f string reference called map asset name.
Now this function is going to loop over our maps.
It's going to save for.
And I'm going to use auto ref map.
In maps, and I'm going to check if map dot value.
That's going to be the map itself.
And we're going to use two soft object path dot get asset name.
That's how we get the asset name from a soft object pointer.
And we're going to see if that's equal to map asset name.
If it is, well then.
Now we know which map name to return.
We return map dot key as those keys are the user facing text.
Otherwise we return an empty f string.
So now we have the ability to get that map name from the asset name.
We can go back to save world State, and we can take our save game and set the map name now.
And we can use get map name from map asset name passing in destination map asset name.
Now we get the red squiggles because we're calling a Non-const function here and save world state is
const.
Well, we can make this a function with const get map name from map asset name can get the const qualifier
here, and we can add the const qualifier on the definition as well.
And that'll fix that.
So now that we're saving our world state with a destination map asset name and a map name, now whenever
we save the world with a name passed in, that's not the empty string.
We'll go ahead and save that.
And we can do that in our map entrance here.
So what we can do is call save world state.
And we can pass in the name of our destination map.
That's going to be the name of this map, the T soft object pointer.
So what we can do is pass that one in.
We can say destination map dot two soft object path dot get asset name.
Now the only way this all works is if our game mode has that map in its list of maps, so that we can
load that name up in the HUD when we're in the load screen.
But now that we're saving this world, we don't need the todo anymore.
We're saving the progress with the destination player start tag.
We don't need to handle glow effects, so I'm going to remove that function call.
And with that we now have the skeleton of a map entrance.
We just need to make a blueprint based on it.
So let's hit the debug button.
All right, so just to test out our map entrance, I'm going to want another map, a map to travel to.
So I'm going to go to my maps folder and take my dungeon and duplicate this and make a dungeon two dungeon
underscore two I'm going to open dungeon two I'm going to save all before doing so.
And in dungeon two, I'm going to make some changes here.
I'm thinking I just want to clear things out.
So I'm going to delete some geometry.
I'm going to delete just about everything here.
Actually, I'm going to not delete those beacons because we're going to want to test out our saving
capabilities so everything else can go except for some beacons.
So let's move this beacon over here.
Like so.
And let's move this checkpoint up.
A little bit and to the right.
Okay.
Now, as for player start tags, I'm going to take this player start and change its tag to dungeon two
player start one.
Like so.
And this checkpoint can have its player start tag.
Change to dungeon two.
Checkpoint one.
And then this one way back in the corner can be dungeon to checkpoint two, just so that their name
differently.
And I'm not going to give player start tags to the beacons.
So now we have a dungeon two.
I'm going to save all.
And the first thing I need to do is go to blueprints game or a game mode and go to its maps and add
one of the maps to it.
I'm going to add dungeon two to it and call this second dungeon.
We're going to compile and save, and I'm going to go back to the first dungeon.
And here in the first dungeon.
I can add a dungeon entrance that leads to the second.
So we need a dungeon entrance.
Let's go to blueprints.
I'll put this in the checkpoint folder and make a new blueprint class based on map entrance.
We'll select that and we'll call this BP underscore map entrance.
And just to give it some geometry to work with.
For now, I'm going to take its checkpoint mesh.
I'm going to set the static mesh.
I'm going to search for stare and use SM stares.
Now I do need to see where it is in relation to the capsule.
It's right here.
So I'm going to go to perspective right.
And just move this mesh down.
Looks like that was a little low.
We'll go down to here.
Like so.
And I'm going to make this checkpoint mesh.
A little bit farther out.
From the actual capsule.
And with that I can move my sphere and my move two component.
Now my move two component is going to be where I want my sphere to be actually.
So I'd like to be able to move one of them and have them both move.
So I'm going to close the editor.
And in the map entrance, I'm going to make a constructor where I can attach my sphere to the move two
component.
So really quickly let's make a constructor.
And that means we're going to need an object initializer.
We can copy that const f object initializer from the checkpoint constructor.
And we can generate the constructor here.
And remember, we also need to call super with the object initializer as well.
So we'll do that in the map entrance constructor as well.
And all I want to do in this constructor is take my sphere and call, set up attachment and pass in
my move to component.
Now, of course, this means sphere needs to be accessible.
So in checkpoint we can move that out of the private section.
I'm just going to delete the private section altogether.
Now with that we can compile and launch in our sphere should be attached to our move to component.
And we'll only need to move the move to component.
Okay, so we're back and back in my map entrance.
In the viewport.
I can now move my move two component and the sphere will move with it.
So I'm going to go to Top Perspective View.
I'm going to move this right here to the middle and forward.
I'd like this on the top step.
And I'm going to go to Right View and move it up and then back to perspective to sort of see what it
looks like.
We'll do that.
And then I'm going to take my sphere and increase its radius really nice and big.
So we can reach that radius easily perhaps like this.
About like that.
And we can go ahead and take the mesh and move.
Everything over to the center there.
We'll have to do our move to component as well.
There we go.
Okay.
We'll compile and save that.
And if we bring one in.
Perhaps right here.
And hit the end key on the keyboard to move it down.
We can even move it down a little bit more.
Of course that gives us the bad sys icon here.
So we'll go ahead and.
Just tweak this really slightly.
Just grabbing my mesh here.
And moving it.
Up.
And then we'll take the whole actor.
We'll actually move the whole actor up first.
So it's a good spot and then move that mesh back down.
So something like that.
And then of course.
Readjusting our move to component as well.
Okay.
So with that let's just press P.
And just make sure that we have our nav mesh.
We may have to move things around a bit.
If the nav mesh doesn't go up to the top of the stairs, it looks like in my case it does.
And with that, I can take my map entrance and search for destination and we can set our destination
map.
We'll set it to dungeon two and our destination player start tag.
That's going to be dungeon two.
Player start one.
Like that.
And now we should be set up to travel to that dungeon.
But we never actually travel to that dungeon.
How are we going to do that?
Well, what we can do is in map entrance and on sphere overlap.
After we've gone and saved all the stuff we wanted to save, we can then open that level.
We can travel to that map.
So let's get gameplay statics and call open level by soft object pointer.
We need a world context object that can be this.
And the soft object pointer is destination map.
And with that we'll be traveling to that world.
So again one last compile.
And then we can test out traveling to another level.
Okay.
So let's give this a shot.
First of all, we should go to maps and open the load menu.
So that way we have a valid slot that we're using.
I'm going to go ahead and delete both slots here and create a new game with S as the name.
And right there I can see that the hover functionality works.
And if I want to save the world state, I want to prove that something has been saved.
So I'm going to get this beacon here, I'm going to reach it.
And then I'm going to click on the stairs.
We're going to run up to the top.
And we've traveled to this world.
Now how are we going to know that that beacon on that other map has been saved if we can't get back
to it?
Well, we can put a map entrance here that goes back to it.
That's cool.
If we press stop and press play again, notice that our map level says Second dungeon because we saved
that.
So that looks great.
And if we select the slot and press play we go to that level that we saved at.
We also saved that player start as well.
If we reach a beacon here or not, a beacon, but a checkpoint and leave and come back.
We should start at that checkpoint.
And if we save a beacon here.
Well, we have to actually reach a checkpoint to save that progress.
But when we do.
We come in at that checkpoint and that beacon is already reached.
Okay, so to get back from one level to the other, we need a map entrance so we can go into dungeon
two and we can place a map entrance here.
So we'll go to our checkpoint folder, bring it in a map entrance, hit end to bring it down.
But we need to configure this.
Where do we want to go.
Right.
So let's search for destination and we'll put in our first dungeon.
And for the player start tag.
Why don't we just come in at.
Dungeon one, checkpoint one.
So using these consistent naming conventions for the player start tags makes it quite easy to just know
if you want to spawn in at that first checkpoint.
There you go.
Okay, so let's save all.
Let's press play.
Actually, let's not press play.
Let's load in an actual game from the load menu.
And now we should see a dungeon entrance.
Now the cool thing is if I just click on it.
Then we come back in and I went to this checkpoint here.
Right?
Was that the one I designated?
I don't remember now.
Let me see.
I'm going to go to dungeon two.
Dungeon one, checkpoint one?
Yeah, that's the one.
That is the first checkpoint.
If I wanted to start at the player start one, I'd have to use this tag.
This one doesn't have a tag.
We might as well give it one though.
We can say dungeon one player start one.
And that way, if we wanted to start at that one, we could we can go to dungeon two and take this map
entrance, set its destination player, start tag to dungeon one.
Player start player start one.
All right.
We'll go back to the load menu.
Test these things out really quick.
So we're saved there.
We can go to the second dungeon.
Now we've reached both checkpoints here.
We haven't reached this other beacon that's way over here.
Now, this isn't a fade actor, so it's not going to fade out of the way.
Let's reach that beacon.
So everything in this second dungeon has been reached.
Now we can go into the dungeon entrance, which takes us back here.
And why don't we just reach everything here?
Let's go ahead and reach this one.
So we've saved our progress at that point.
Let's see if I can even make it.
I think I can make it to this beacon.
And I don't know if I can make it to I can I can make it to this checkpoint.
All right.
We've reached everything in all levels.
And now the only way to save is to transition to other levels.
But now we see that everything.
There's that glowing beacon over there.
Everything has been reached.
In this one and everything in this level has been reached.
I loaded in at this beacon actually, so I might have a typo in the destination player start tag here.
No, I don't have it set, so I might have changed its player start tag instead of its destination.
That's fine.
Let's set this to dungeon one player, start one, save that.
So now that should bring us back.
To that first player start in dungeon one.
So let's test that theory.
Okay going straight back to the other level and we're at player start one.
Okay.
So we have a transitioning system a system to transition from one level to the next.
As long as we have those levels in our map on the game mode, we'll see them in the load screen as well.
So this gives us the opportunity to create multiple levels strung together.
You can even have a dungeon entrance on some completely different map.
That's like an outdoor map, and you can make some stairs that go down.
In fact, that's what we're going to make is a staircase that goes down because a staircase up to nothing
doesn't make sense.
I would like a staircase going down into the ground.
So we're going to be working on making that in the next couple of videos and really making something
that looks really nice.
But we have the makings of a really nice level transition system that looks great.
So really making something we can be proud of here.
Excellent.
Excellent job.
I'll see you in the next video.