Welcome back.
Now we have a checkpoint and it looks great, but that's all it does is look good.
We want it to act.
We want it to do something for us rather than just glow.
So I'm going to go ahead and close the static mesh, close the material instance.
And I'm actually done with the blueprint as well.
We can go ahead and close that.
And what I want to do when I overlap with this is I want to save my progress.
So how are we going to save our progress?
Well, we can look in C plus plus at our checkpoint CP in our on sphere overlap when we're handling
glow effects.
I also want to save progress, and I want this checkpoint to somehow inform us what its player start
tag is, and that allows us to save that player start tag.
Now that's not the only thing we want to save.
We want to save our player's progress.
We want to save what abilities we have, what our attribute values are.
All of that good stuff too.
So I think it would be a good idea to have some kind of interface function to save our progress.
And that way on sphere overlap can check for the interface and just tell the thing that overlapped.
Hey, save your progress.
For that reason, I'm going to use the player interface because the player interface is the interface
for the human controlled player.
So here in interaction, we can open player interface and we can add a new function for saving our progress.
We'll go down to the bottom to do it.
It's going to be void.
And I'd like this function to be called save Progress.
Now save progress could take an fname for that player start tag.
That way whoever implements it will know to save that tag as the checkpoint.
So let's go ahead and make a const f name reference called player start tag.
We could even call it checkpoint tag.
As this will be from a checkpoint.
Now this can be a blueprint native event blueprint callable.
I'd like to do that.
And then we can override the implementation.
And then we can just execute the static function, save progress anywhere.
It's a lot more versatile that way.
So I'm going to override this in our character.
So we'll go ahead and go to character or a character to the player interface function list which is
steadily growing.
We're going to override the virtual void function save progress implementation.
Let's go ahead and generate that definition.
We're going to delete what was there and how can we implement save progress.
Well to save our progress we're going to probably want to access the game mode.
The game mode has ways to retrieve the save object associated with the current slot, and slot index.
So really we're going to need the game mode.
So we're going to say Aiora game mode base or a game mode.
And we'll cast to a or a game mode base.
The result of you gameplay statics get game mode.
Now I do need to include that header first.
And we'll call get game mode.
Passing in a world context object will pass in this.
Now, if the game mode is valid, we're going to want to get our save game object.
But we also need to know what our save slot and save slot name are, which we're going to want to get
from the game instance.
So we're also going to get a you or a game instance called or a game instance.
And we'll cast to that class you or a game instance the result of or a game mode get game instance.
Now that we have that, we can check that as well.
We can say and or a game instance.
Now what are we going to do here?
Well, if we already have some data saved, we don't want to just clobber over it.
I'd like to load up that data and then we can save additional things to that data.
Now let's see what our game mode is already capable of by opening our game folder in the private and
go to our game mode base.
The reason I'm coming here is because we have a get save slot data function, which takes a slot name
and a slot index, and if that save game exists, then we load it up and go ahead and cast it to load
screen save game and return it.
Now if it doesn't exist, we create one and return that.
So get save slot data is a nice function we can use and we can pass in our game instance and slot index.
But that means here in our character, we have to get our game instance and get that load slot name
and get that load slot index and pass it in to get to our game mode function.
And that's a lot of steps that really we could just make one function that can do all that for us.
And I like that function to be on our game mode, something that can just retrieve our load screen,
save data.
Let's go ahead and create a public function on the game mode that can do that.
So up here with our other functions, I'm going to make a function that returns a you load screen save
game.
That way we don't even have to cast over there in our character class.
And I'm going to call this retrieve in game save data.
No input parameters.
It's going to do all that lookup for us.
And what is it going to do.
Well it's going to get the game instance.
We can copy one of these lines down here where we're doing that.
And it's going to get the slot name and the slot index.
So let's make some const local variables const f string called in game load slot name.
And we'll get our game instance and get our slot name from that load slot name.
Let's also make a const int 32 called in Game load slot Index.
Get our aura game instance.
Get the load slot index.
Now that we have those, we can call our get save slot data, which is right here.
Get save slot data.
We're just going to call that and return the results.
So return get save slot data.
We'll pass in end game load slot name and in game load slot index.
Now this function is a lot easier.
And we can go back to our aura character and just use that.
So we don't even need our game instance.
In that case we can go ahead and just remove that now.
And after checking our game mode we can create a new load screen save game.
We'll call this save Data and we'll get our aura game mode and just call retrieve in game save data.
And now we have it.
And if this returns null for some reason, we'll just return.
If it's an equal to null pointer, we'll return right here.
And after this we have our save data.
We can save stuff to it.
And we're loading it up.
So it has all of this stuff in it that's been saved previously.
Now all we need to do is just save things to it.
And what am I going to save to it?
Well, for starters, we can try our checkpoint tag so we can take our save data.
Which is an incomplete type, we can go ahead and include the definition for you load screen save game,
and we can take our player start tag and set it to checkpoint tag that we've passed in.
So now our save data has that and we can go ahead and save.
Now yes, we do have a lot of other things we want to save.
We're just getting the system in place.
We're getting it started.
Once it's all in place then we can add more things to save.
But for now we just want to save.
So how are we going to save?
Well, I'd like a function on the game mode that we can just pass in our save object, and the game
mode will handle the rest.
So let's add that function to the game mode base just under retrieve.
In Game Save data, let's make a void function called save in game, we'll call it progress Data.
And this can take in a u load screen save game called save Object.
So let's generate this one.
And this will handle saving for us.
So in save in game progress data we're going to get the game instance first.
We're going to get the load slot name and the load slot index.
We'll copy that from retrieve endgame slot data and we'll call you Gameplay Statics.
Save game to slot and we'll pass in our save object.
Our slot name that's in game load slot name and the slot index that's in game load slot index.
And while we're here, we can go ahead and save that checkpoint tag to our game instance.
Since we have it here, we can take our game instance.
Set the player start tag because we have it on our save object.
That's the player start tag on it.
So now the game instance at least knows that last player start tag we were at, just in case.
It needs to know that.
So save in game progress.
Data is a nice function.
We can just pass in a save object to, and we'll do that from our aura character save progress implementation.
After we've saved our player start tag, we're going to take our aura game mode and save in game progress
data passing in our save data.
So now that we have this interface function, we can save our data from the checkpoint as soon as we've
overlapped and we no longer need to check for the player tag, we can just check to see if the other
actor implements the interface so other actor implements.
We have to check the U version U player interface.
If it does, we can take I player interface and call execute save progress.
And this requires a u object that's the other actor and the checkpoint tag.
Now we're in the checkpoint.
The checkpoint has a player start tag.
We just have to remember to set that for any given player start.
So as long as we set that and it's not none, we'll save that player.
Start tag.
Okay.
So when we overlap we're going to execute save progress now on the character because it implements that
we're going to retrieve in game save data, save the checkpoint tag to it and save the data.
Now retrieve in game save data is going to get the load slot name and load slot index from the game
instance.
Right now.
When are we setting that on the game instance?
Well, we're actually not.
If we go back to our ViewModel MVVM load screen to load data, we'll see that we are retrieving the
player start tag and storing it in our load slot.
But then when we go and press play, where's that play button pressed?
Here it is.
All we're saving to the game instance is that player start tag.
We're not actually saving its slot name and slot index, so we can save that here as soon as we press
play.
So we're going to take our game instance and set load slot.
We'll start with name and we can get that from selected slot.
That's going to be the load slot name.
And then we'll take our A game instance.
Load slot index, and we'll get that from the selected slot as well.
Selected slot.
Slot index.
And with that now when we press play, our aura game instance will know the slot name and slot index
that we need to load in along with the player start tag.
So we'll start at the player start tag.
And when we reach the checkpoint, we'll execute save progress and we'll save to the correct one.
For that matter, we'll actually have a real slot to save to.
Let's go ahead and test this out.
And we have to remember that our checkpoint needs to have its player start tag set.
All right, so we're back.
I'm in the dungeon.
I'm going to give this player start a name, and it looks like it's.
A little above the ground.
So here's the player start tag.
I'm just going to call this dungeon one checkpoint.
One.
It doesn't matter what we call it, as long as it has a name.
So I'm going to go ahead and save that and go back to maps to Load menu.
And I'm just going to clear my save games.
So we start fresh.
I'm going to make a new one, give it a name select it and press play.
Now here's the default player start.
So that's where I expect to start.
But now if I go to this checkpoint now, I expect my progress to be saved.
And if I exit and go back to the load menu and press play and select the slot and press play again.
Now I'm here at this checkpoint, which is what I expected.
And the cool thing about this is I can have multiple checkpoints.
If I go back to the dungeon map, I can go over here and put another checkpoint.
So I'm going to go into checkpoint, bring out a checkpoint blueprint here.
I can hit the end key to bring it down.
And I'll call this one.
Give it a player start tag of dungeon one, checkpoint two.
And if I reach this then I should save that progress.
I'm going to save all.
Go back to maps, load menu, press play, select my slot and load in.
I'm at this checkpoint, but I'd like to go over here and save my progress at this checkpoint.
There it loaded up.
Now I can exit.
Go back to load menu and select that slot and press play.
Okay.
Let's go back to the dungeon.
Okay.
For some reason this player start tag wasn't set.
So I need to take this player start tag.
I'll give it dungeon one.
Checkpoint two.
Oh I see.
Okay, here's what happened.
And this may be something that happens to you from time to time.
If you enter something here and you open up the content drawer with control space.
Control space will undo things that you have done in details panels.
Just so you know, that is something to be aware of.
So I have to take this and set it back to dungeon one, checkpoint two, and then just open the content
browser with the mouse.
That way it won't reset this.
So that's what ended up happening.
And it's kind of a subtle pain.
But it happened.
Now that that's the case, now that it has dungeon one, checkpoint two, we can go back and test this
again.
I'm just going to delete this slot.
And try again.
I'm going to give it a name.
New slot.
Select it.
Press play.
Okay, I start here.
That's good.
I'll go to this checkpoint and leave.
Go back to the load menu.
Select that slot, press play and I'm here.
Great.
Now I can save my progress at this one.
Over here.
Okay, I reached it.
I'm going to exit.
Come back into the load menu.
Load this slot and we're over here.
So we're now successfully saving our location at checkpoints.
We're actually just saving the checkpoint tag.
But now this is great because whenever we load into a game, we're loading up that checkpoint from our
disk, and then we'll load in at that specific player start.
If there's a player, start with that player start tag.
So this is awesome because now we have a system in place where we can save and load things, not just
the player start tag, but once we go into or a character and save progress implementation, we can
save all kinds of things here, and then we can choose a point at which we can load in our progress
and we'll get to all that.
But there's still a couple things I want to handle with our checkpoint.
One of them is when I press play and load into a game.
The checkpoint that I've already reached is now reachable again, so if I hover over it now, I've just
saved my spot there.
But there's this one here, which is earlier on in the level, and I can even go back and hover over
that one, and that's going to overwrite my player start tag.
And now if I start loading in again, well, now I'm back here because that's the last one I reached.
What I need is for my level to know which checkpoints have already been reached, and make them already
activated, and disable their collision at the beginning so we can't go and reach them again.
Those should tell us, just based on them being already all glowy, that we've already reached them,
right?
So the level needs a concept of loading the world state, and there needs to be a list of actors that
need to be loaded in differently depending on what we're loading, what our world state is.
So that's one of the things we'll do next.
But before we get into saving World State, I'd like to make sure that we can save Ora's stats, the
attributes, the abilities and the experience points, things like that.
We're going to devise a system to save Ora's progress before we get into saving the world state, and
then we'll move on to level transitioning, transitioning to new levels, and loading in world state
by level.
So lots of exciting things coming.
I'll see you soon.