WEBVTT

00:07.080 --> 00:08.310
Welcome back.

00:08.310 --> 00:13.290
Now we have a checkpoint and it looks great, but that's all it does is look good.

00:13.290 --> 00:15.150
We want it to act.

00:15.150 --> 00:19.020
We want it to do something for us rather than just glow.

00:19.290 --> 00:23.760
So I'm going to go ahead and close the static mesh, close the material instance.

00:23.760 --> 00:26.760
And I'm actually done with the blueprint as well.

00:26.760 --> 00:28.800
We can go ahead and close that.

00:29.570 --> 00:35.090
And what I want to do when I overlap with this is I want to save my progress.

00:35.090 --> 00:38.000
So how are we going to save our progress?

00:38.000 --> 00:45.080
Well, we can look in C plus plus at our checkpoint CP in our on sphere overlap when we're handling

00:45.080 --> 00:46.280
glow effects.

00:46.580 --> 00:55.580
I also want to save progress, and I want this checkpoint to somehow inform us what its player start

00:55.580 --> 01:00.050
tag is, and that allows us to save that player start tag.

01:00.350 --> 01:02.870
Now that's not the only thing we want to save.

01:02.870 --> 01:04.640
We want to save our player's progress.

01:04.640 --> 01:09.740
We want to save what abilities we have, what our attribute values are.

01:09.740 --> 01:11.720
All of that good stuff too.

01:11.720 --> 01:18.470
So I think it would be a good idea to have some kind of interface function to save our progress.

01:18.470 --> 01:24.020
And that way on sphere overlap can check for the interface and just tell the thing that overlapped.

01:24.020 --> 01:25.760
Hey, save your progress.

01:25.760 --> 01:31.040
For that reason, I'm going to use the player interface because the player interface is the interface

01:31.040 --> 01:32.930
for the human controlled player.

01:32.930 --> 01:39.530
So here in interaction, we can open player interface and we can add a new function for saving our progress.

01:39.920 --> 01:41.780
We'll go down to the bottom to do it.

01:41.780 --> 01:43.100
It's going to be void.

01:43.100 --> 01:47.180
And I'd like this function to be called save Progress.

01:47.720 --> 01:51.920
Now save progress could take an fname for that player start tag.

01:51.920 --> 01:57.110
That way whoever implements it will know to save that tag as the checkpoint.

01:57.110 --> 02:04.160
So let's go ahead and make a const f name reference called player start tag.

02:04.160 --> 02:06.380
We could even call it checkpoint tag.

02:07.880 --> 02:09.890
As this will be from a checkpoint.

02:09.920 --> 02:13.730
Now this can be a blueprint native event blueprint callable.

02:13.730 --> 02:15.050
I'd like to do that.

02:15.470 --> 02:18.110
And then we can override the implementation.

02:18.110 --> 02:22.790
And then we can just execute the static function, save progress anywhere.

02:22.790 --> 02:24.620
It's a lot more versatile that way.

02:25.160 --> 02:28.580
So I'm going to override this in our character.

02:28.580 --> 02:36.020
So we'll go ahead and go to character or a character to the player interface function list which is

02:36.020 --> 02:37.220
steadily growing.

02:37.640 --> 02:44.690
We're going to override the virtual void function save progress implementation.

02:44.690 --> 02:47.600
Let's go ahead and generate that definition.

02:47.990 --> 02:54.020
We're going to delete what was there and how can we implement save progress.

02:54.350 --> 03:00.740
Well to save our progress we're going to probably want to access the game mode.

03:01.190 --> 03:08.630
The game mode has ways to retrieve the save object associated with the current slot, and slot index.

03:08.810 --> 03:11.870
So really we're going to need the game mode.

03:12.200 --> 03:18.260
So we're going to say Aiora game mode base or a game mode.

03:20.540 --> 03:24.950
And we'll cast to a or a game mode base.

03:25.190 --> 03:30.410
The result of you gameplay statics get game mode.

03:30.950 --> 03:34.010
Now I do need to include that header first.

03:36.540 --> 03:39.000
And we'll call get game mode.

03:40.640 --> 03:44.000
Passing in a world context object will pass in this.

03:44.390 --> 03:52.580
Now, if the game mode is valid, we're going to want to get our save game object.

03:52.580 --> 03:59.780
But we also need to know what our save slot and save slot name are, which we're going to want to get

03:59.780 --> 04:01.160
from the game instance.

04:01.160 --> 04:06.560
So we're also going to get a you or a game instance called or a game instance.

04:08.030 --> 04:17.720
And we'll cast to that class you or a game instance the result of or a game mode get game instance.

04:19.090 --> 04:22.000
Now that we have that, we can check that as well.

04:22.990 --> 04:25.390
We can say and or a game instance.

04:26.950 --> 04:28.840
Now what are we going to do here?

04:28.840 --> 04:33.700
Well, if we already have some data saved, we don't want to just clobber over it.

04:33.700 --> 04:39.760
I'd like to load up that data and then we can save additional things to that data.

04:40.090 --> 04:46.510
Now let's see what our game mode is already capable of by opening our game folder in the private and

04:46.510 --> 04:48.280
go to our game mode base.

04:48.700 --> 04:55.720
The reason I'm coming here is because we have a get save slot data function, which takes a slot name

04:55.720 --> 05:03.580
and a slot index, and if that save game exists, then we load it up and go ahead and cast it to load

05:03.580 --> 05:05.320
screen save game and return it.

05:05.320 --> 05:08.530
Now if it doesn't exist, we create one and return that.

05:09.040 --> 05:17.200
So get save slot data is a nice function we can use and we can pass in our game instance and slot index.

05:17.320 --> 05:25.390
But that means here in our character, we have to get our game instance and get that load slot name

05:25.390 --> 05:30.550
and get that load slot index and pass it in to get to our game mode function.

05:30.550 --> 05:36.550
And that's a lot of steps that really we could just make one function that can do all that for us.

05:36.790 --> 05:43.150
And I like that function to be on our game mode, something that can just retrieve our load screen,

05:43.150 --> 05:44.230
save data.

05:44.230 --> 05:48.850
Let's go ahead and create a public function on the game mode that can do that.

05:49.180 --> 05:54.760
So up here with our other functions, I'm going to make a function that returns a you load screen save

05:54.760 --> 05:55.600
game.

05:55.600 --> 05:59.650
That way we don't even have to cast over there in our character class.

05:59.650 --> 06:04.960
And I'm going to call this retrieve in game save data.

06:06.010 --> 06:07.540
No input parameters.

06:07.540 --> 06:09.760
It's going to do all that lookup for us.

06:10.300 --> 06:12.730
And what is it going to do.

06:12.730 --> 06:14.860
Well it's going to get the game instance.

06:14.860 --> 06:18.070
We can copy one of these lines down here where we're doing that.

06:18.580 --> 06:22.750
And it's going to get the slot name and the slot index.

06:22.750 --> 06:30.310
So let's make some const local variables const f string called in game load slot name.

06:30.700 --> 06:35.890
And we'll get our game instance and get our slot name from that load slot name.

06:35.890 --> 06:41.950
Let's also make a const int 32 called in Game load slot Index.

06:42.460 --> 06:44.290
Get our aura game instance.

06:44.590 --> 06:46.420
Get the load slot index.

06:47.100 --> 06:53.370
Now that we have those, we can call our get save slot data, which is right here.

06:53.400 --> 06:54.720
Get save slot data.

06:54.720 --> 06:57.630
We're just going to call that and return the results.

06:57.630 --> 07:00.540
So return get save slot data.

07:00.540 --> 07:07.740
We'll pass in end game load slot name and in game load slot index.

07:07.740 --> 07:10.440
Now this function is a lot easier.

07:10.770 --> 07:14.370
And we can go back to our aura character and just use that.

07:14.370 --> 07:16.290
So we don't even need our game instance.

07:16.290 --> 07:19.950
In that case we can go ahead and just remove that now.

07:20.970 --> 07:27.930
And after checking our game mode we can create a new load screen save game.

07:27.930 --> 07:36.930
We'll call this save Data and we'll get our aura game mode and just call retrieve in game save data.

07:37.320 --> 07:38.640
And now we have it.

07:38.640 --> 07:43.170
And if this returns null for some reason, we'll just return.

07:43.170 --> 07:48.030
If it's an equal to null pointer, we'll return right here.

07:48.960 --> 07:51.120
And after this we have our save data.

07:51.120 --> 07:52.740
We can save stuff to it.

07:52.740 --> 07:54.150
And we're loading it up.

07:54.150 --> 07:58.170
So it has all of this stuff in it that's been saved previously.

07:58.170 --> 08:01.890
Now all we need to do is just save things to it.

08:01.890 --> 08:03.960
And what am I going to save to it?

08:03.960 --> 08:09.450
Well, for starters, we can try our checkpoint tag so we can take our save data.

08:11.420 --> 08:18.350
Which is an incomplete type, we can go ahead and include the definition for you load screen save game,

08:19.880 --> 08:26.720
and we can take our player start tag and set it to checkpoint tag that we've passed in.

08:27.290 --> 08:32.840
So now our save data has that and we can go ahead and save.

08:33.110 --> 08:36.080
Now yes, we do have a lot of other things we want to save.

08:36.080 --> 08:38.360
We're just getting the system in place.

08:38.360 --> 08:39.740
We're getting it started.

08:39.740 --> 08:42.830
Once it's all in place then we can add more things to save.

08:42.830 --> 08:45.680
But for now we just want to save.

08:45.680 --> 08:48.080
So how are we going to save?

08:48.080 --> 08:54.800
Well, I'd like a function on the game mode that we can just pass in our save object, and the game

08:54.800 --> 08:56.360
mode will handle the rest.

08:56.960 --> 09:00.980
So let's add that function to the game mode base just under retrieve.

09:00.980 --> 09:08.030
In Game Save data, let's make a void function called save in game, we'll call it progress Data.

09:09.910 --> 09:16.240
And this can take in a u load screen save game called save Object.

09:18.020 --> 09:19.970
So let's generate this one.

09:21.090 --> 09:24.030
And this will handle saving for us.

09:24.030 --> 09:28.320
So in save in game progress data we're going to get the game instance first.

09:31.320 --> 09:36.390
We're going to get the load slot name and the load slot index.

09:36.600 --> 09:43.680
We'll copy that from retrieve endgame slot data and we'll call you Gameplay Statics.

09:45.630 --> 09:51.330
Save game to slot and we'll pass in our save object.

09:52.590 --> 10:00.360
Our slot name that's in game load slot name and the slot index that's in game load slot index.

10:00.360 --> 10:06.000
And while we're here, we can go ahead and save that checkpoint tag to our game instance.

10:06.000 --> 10:10.200
Since we have it here, we can take our game instance.

10:12.400 --> 10:17.710
Set the player start tag because we have it on our save object.

10:18.800 --> 10:20.570
That's the player start tag on it.

10:20.570 --> 10:27.110
So now the game instance at least knows that last player start tag we were at, just in case.

10:27.110 --> 10:28.340
It needs to know that.

10:28.700 --> 10:30.230
So save in game progress.

10:30.230 --> 10:31.820
Data is a nice function.

10:31.820 --> 10:38.060
We can just pass in a save object to, and we'll do that from our aura character save progress implementation.

10:38.060 --> 10:45.680
After we've saved our player start tag, we're going to take our aura game mode and save in game progress

10:45.680 --> 10:48.410
data passing in our save data.

10:49.460 --> 10:55.550
So now that we have this interface function, we can save our data from the checkpoint as soon as we've

10:55.550 --> 11:00.650
overlapped and we no longer need to check for the player tag, we can just check to see if the other

11:00.650 --> 11:05.900
actor implements the interface so other actor implements.

11:07.840 --> 11:11.590
We have to check the U version U player interface.

11:13.700 --> 11:21.650
If it does, we can take I player interface and call execute save progress.

11:21.650 --> 11:29.150
And this requires a u object that's the other actor and the checkpoint tag.

11:29.150 --> 11:30.890
Now we're in the checkpoint.

11:30.890 --> 11:34.400
The checkpoint has a player start tag.

11:34.910 --> 11:38.930
We just have to remember to set that for any given player start.

11:39.790 --> 11:43.870
So as long as we set that and it's not none, we'll save that player.

11:43.870 --> 11:44.740
Start tag.

11:45.160 --> 11:45.670
Okay.

11:45.670 --> 11:52.720
So when we overlap we're going to execute save progress now on the character because it implements that

11:52.720 --> 11:59.380
we're going to retrieve in game save data, save the checkpoint tag to it and save the data.

11:59.740 --> 12:07.450
Now retrieve in game save data is going to get the load slot name and load slot index from the game

12:07.450 --> 12:07.870
instance.

12:07.870 --> 12:09.430
Right now.

12:09.430 --> 12:12.070
When are we setting that on the game instance?

12:12.070 --> 12:13.810
Well, we're actually not.

12:13.810 --> 12:22.570
If we go back to our ViewModel MVVM load screen to load data, we'll see that we are retrieving the

12:22.570 --> 12:25.630
player start tag and storing it in our load slot.

12:25.630 --> 12:29.410
But then when we go and press play, where's that play button pressed?

12:29.410 --> 12:30.220
Here it is.

12:30.220 --> 12:33.850
All we're saving to the game instance is that player start tag.

12:33.850 --> 12:40.600
We're not actually saving its slot name and slot index, so we can save that here as soon as we press

12:40.600 --> 12:41.170
play.

12:41.410 --> 12:46.810
So we're going to take our game instance and set load slot.

12:46.810 --> 12:50.920
We'll start with name and we can get that from selected slot.

12:52.350 --> 12:54.390
That's going to be the load slot name.

12:54.900 --> 12:56.970
And then we'll take our A game instance.

12:57.930 --> 13:02.640
Load slot index, and we'll get that from the selected slot as well.

13:02.670 --> 13:04.020
Selected slot.

13:04.020 --> 13:05.400
Slot index.

13:05.670 --> 13:12.090
And with that now when we press play, our aura game instance will know the slot name and slot index

13:12.090 --> 13:16.050
that we need to load in along with the player start tag.

13:16.050 --> 13:17.730
So we'll start at the player start tag.

13:17.730 --> 13:24.180
And when we reach the checkpoint, we'll execute save progress and we'll save to the correct one.

13:24.300 --> 13:28.410
For that matter, we'll actually have a real slot to save to.

13:28.620 --> 13:30.390
Let's go ahead and test this out.

13:30.390 --> 13:35.460
And we have to remember that our checkpoint needs to have its player start tag set.

13:39.170 --> 13:41.120
All right, so we're back.

13:41.120 --> 13:42.320
I'm in the dungeon.

13:42.320 --> 13:47.630
I'm going to give this player start a name, and it looks like it's.

13:48.500 --> 13:50.330
A little above the ground.

13:53.220 --> 13:55.320
So here's the player start tag.

13:55.320 --> 14:00.840
I'm just going to call this dungeon one checkpoint.

14:03.660 --> 14:04.530
One.

14:04.920 --> 14:08.550
It doesn't matter what we call it, as long as it has a name.

14:09.060 --> 14:15.030
So I'm going to go ahead and save that and go back to maps to Load menu.

14:15.030 --> 14:18.540
And I'm just going to clear my save games.

14:18.930 --> 14:20.370
So we start fresh.

14:20.550 --> 14:24.780
I'm going to make a new one, give it a name select it and press play.

14:24.810 --> 14:27.510
Now here's the default player start.

14:27.510 --> 14:30.300
So that's where I expect to start.

14:30.300 --> 14:35.730
But now if I go to this checkpoint now, I expect my progress to be saved.

14:35.730 --> 14:42.060
And if I exit and go back to the load menu and press play and select the slot and press play again.

14:42.360 --> 14:46.860
Now I'm here at this checkpoint, which is what I expected.

14:46.860 --> 14:50.220
And the cool thing about this is I can have multiple checkpoints.

14:50.220 --> 14:55.260
If I go back to the dungeon map, I can go over here and put another checkpoint.

14:56.320 --> 15:01.270
So I'm going to go into checkpoint, bring out a checkpoint blueprint here.

15:01.690 --> 15:05.200
I can hit the end key to bring it down.

15:05.200 --> 15:06.760
And I'll call this one.

15:06.760 --> 15:11.410
Give it a player start tag of dungeon one, checkpoint two.

15:12.310 --> 15:15.760
And if I reach this then I should save that progress.

15:15.760 --> 15:16.960
I'm going to save all.

15:16.990 --> 15:23.290
Go back to maps, load menu, press play, select my slot and load in.

15:23.290 --> 15:29.350
I'm at this checkpoint, but I'd like to go over here and save my progress at this checkpoint.

15:29.950 --> 15:31.150
There it loaded up.

15:31.150 --> 15:32.710
Now I can exit.

15:34.040 --> 15:38.540
Go back to load menu and select that slot and press play.

15:38.960 --> 15:40.340
Okay.

15:43.010 --> 15:44.600
Let's go back to the dungeon.

15:45.320 --> 15:45.800
Okay.

15:45.800 --> 15:49.490
For some reason this player start tag wasn't set.

15:50.000 --> 15:52.610
So I need to take this player start tag.

15:52.910 --> 15:54.620
I'll give it dungeon one.

15:54.620 --> 15:56.630
Checkpoint two.

15:58.840 --> 15:59.950
Oh I see.

15:59.980 --> 16:01.870
Okay, here's what happened.

16:01.870 --> 16:05.710
And this may be something that happens to you from time to time.

16:05.710 --> 16:12.610
If you enter something here and you open up the content drawer with control space.

16:13.380 --> 16:17.850
Control space will undo things that you have done in details panels.

16:17.850 --> 16:20.430
Just so you know, that is something to be aware of.

16:20.820 --> 16:27.420
So I have to take this and set it back to dungeon one, checkpoint two, and then just open the content

16:27.420 --> 16:28.530
browser with the mouse.

16:28.530 --> 16:30.480
That way it won't reset this.

16:30.480 --> 16:32.580
So that's what ended up happening.

16:32.580 --> 16:35.190
And it's kind of a subtle pain.

16:35.190 --> 16:36.480
But it happened.

16:36.510 --> 16:42.840
Now that that's the case, now that it has dungeon one, checkpoint two, we can go back and test this

16:42.840 --> 16:43.500
again.

16:43.500 --> 16:45.930
I'm just going to delete this slot.

16:47.140 --> 16:48.490
And try again.

16:48.490 --> 16:49.870
I'm going to give it a name.

16:50.500 --> 16:51.370
New slot.

16:51.370 --> 16:51.910
Select it.

16:51.910 --> 16:52.720
Press play.

16:52.720 --> 16:53.650
Okay, I start here.

16:53.650 --> 16:54.430
That's good.

16:54.430 --> 16:56.890
I'll go to this checkpoint and leave.

16:57.470 --> 16:59.120
Go back to the load menu.

16:59.390 --> 17:02.330
Select that slot, press play and I'm here.

17:02.360 --> 17:02.990
Great.

17:03.020 --> 17:05.750
Now I can save my progress at this one.

17:05.750 --> 17:06.560
Over here.

17:08.200 --> 17:09.250
Okay, I reached it.

17:09.250 --> 17:10.660
I'm going to exit.

17:11.020 --> 17:13.120
Come back into the load menu.

17:13.540 --> 17:16.420
Load this slot and we're over here.

17:16.870 --> 17:21.190
So we're now successfully saving our location at checkpoints.

17:21.190 --> 17:24.070
We're actually just saving the checkpoint tag.

17:24.070 --> 17:31.480
But now this is great because whenever we load into a game, we're loading up that checkpoint from our

17:31.480 --> 17:36.490
disk, and then we'll load in at that specific player start.

17:36.490 --> 17:39.820
If there's a player, start with that player start tag.

17:40.330 --> 17:46.990
So this is awesome because now we have a system in place where we can save and load things, not just

17:46.990 --> 17:54.580
the player start tag, but once we go into or a character and save progress implementation, we can

17:54.580 --> 18:02.020
save all kinds of things here, and then we can choose a point at which we can load in our progress

18:02.020 --> 18:03.250
and we'll get to all that.

18:03.250 --> 18:07.690
But there's still a couple things I want to handle with our checkpoint.

18:08.200 --> 18:13.330
One of them is when I press play and load into a game.

18:13.660 --> 18:20.770
The checkpoint that I've already reached is now reachable again, so if I hover over it now, I've just

18:20.770 --> 18:21.940
saved my spot there.

18:21.940 --> 18:27.400
But there's this one here, which is earlier on in the level, and I can even go back and hover over

18:27.400 --> 18:30.970
that one, and that's going to overwrite my player start tag.

18:30.970 --> 18:36.280
And now if I start loading in again, well, now I'm back here because that's the last one I reached.

18:37.300 --> 18:42.940
What I need is for my level to know which checkpoints have already been reached, and make them already

18:42.940 --> 18:48.970
activated, and disable their collision at the beginning so we can't go and reach them again.

18:49.000 --> 18:55.210
Those should tell us, just based on them being already all glowy, that we've already reached them,

18:55.210 --> 18:55.900
right?

18:56.170 --> 19:03.490
So the level needs a concept of loading the world state, and there needs to be a list of actors that

19:03.490 --> 19:11.080
need to be loaded in differently depending on what we're loading, what our world state is.

19:12.820 --> 19:15.370
So that's one of the things we'll do next.

19:15.370 --> 19:22.090
But before we get into saving World State, I'd like to make sure that we can save Ora's stats, the

19:22.090 --> 19:27.820
attributes, the abilities and the experience points, things like that.

19:27.820 --> 19:34.660
We're going to devise a system to save Ora's progress before we get into saving the world state, and

19:34.660 --> 19:41.200
then we'll move on to level transitioning, transitioning to new levels, and loading in world state

19:41.200 --> 19:41.980
by level.

19:41.980 --> 19:43.990
So lots of exciting things coming.

19:43.990 --> 19:45.040
I'll see you soon.
