WEBVTT

00:06.870 --> 00:07.860
Welcome back.

00:07.860 --> 00:09.870
Now our save system is working.

00:09.870 --> 00:12.960
Except for the fact that we're not saving our abilities.

00:12.960 --> 00:15.750
If I create a new slot and play.

00:15.750 --> 00:20.400
Yes, I load in with my default abilities if it's the first time.

00:20.400 --> 00:27.360
But if I go ahead and save the game and quit and come back and load in, there are no abilities because

00:27.360 --> 00:32.850
we're not handling that case, only those default abilities if it's the first time.

00:33.300 --> 00:37.110
So what we need to do is save our abilities.

00:37.110 --> 00:37.770
Now.

00:37.770 --> 00:44.160
Abilities are objects of type you gameplay ability, but we don't even really use that.

00:44.160 --> 00:50.640
Most of the time we use ability specs, and for most of the stuff in our code base, we identify abilities

00:50.640 --> 00:52.710
by a series of gameplay tags.

00:52.710 --> 00:57.510
We have an ability tag, we have status tags, we have slot tags.

00:57.510 --> 01:03.750
So really, if we want to save a gameplay ability, we also need to save the information pertaining

01:03.780 --> 01:04.920
to that ability.

01:05.340 --> 01:12.720
Now I'd like to create a struct to save all the pertinent data that we need for saving a gameplay ability.

01:12.720 --> 01:16.710
Now we can define that here in load screen save game if we like.

01:16.710 --> 01:20.850
So I'm going to make a struct here to store the information for an ability.

01:20.850 --> 01:24.150
I'm going to make this struct called f saved.

01:25.160 --> 01:26.090
Ability.

01:27.590 --> 01:30.410
And I'd like this to be exposed.

01:31.370 --> 01:36.620
With you struct, I'll make it a blueprint type and give it a generated body.

01:36.620 --> 01:43.400
And it's going to have several pieces of information pertaining to an ability, the first of which is

01:43.400 --> 01:45.260
the actual ability class.

01:45.530 --> 01:47.990
A subclass of we're going to store that.

01:47.990 --> 01:51.650
It's going to be a subclass of you gameplay ability.

01:51.740 --> 01:54.080
We're going to forward declare that.

01:55.400 --> 01:57.800
And we'll call this game playability.

01:59.660 --> 02:01.790
Now this will get a new property.

02:02.330 --> 02:04.730
We'll make it edit defaults only.

02:05.420 --> 02:07.160
Blueprint read only.

02:08.950 --> 02:12.400
Category class defaults.

02:12.790 --> 02:16.360
Now, if we're going to save an ability, this is not enough.

02:16.360 --> 02:18.190
We need to know other things about it.

02:18.220 --> 02:20.110
We need to know the gameplay tag.

02:20.110 --> 02:24.340
So we're going to have F gameplay tag called ability tag.

02:24.340 --> 02:29.320
We'll set that equal to an empty F gameplay tag by default.

02:29.620 --> 02:32.110
Either that or abilities none.

02:32.110 --> 02:33.070
Either one.

02:34.760 --> 02:37.430
We'll just make it an empty tag for now.

02:37.790 --> 02:43.040
You property edit defaults only blueprint read.

02:43.040 --> 02:43.520
Write.

02:43.550 --> 02:46.760
Now we're going to need to include the header file.

02:47.180 --> 02:48.980
Gameplay tag container.

02:49.340 --> 02:53.960
But the ability tag isn't the only gameplay tag an ability has.

02:53.960 --> 02:55.970
It also has an ability status.

02:55.970 --> 02:57.290
Let's add that one.

02:58.090 --> 02:59.500
It also has a slot.

02:59.530 --> 03:00.970
What's its input tag.

03:00.970 --> 03:01.540
Right.

03:01.540 --> 03:04.090
We're going to call this ability slot.

03:04.680 --> 03:08.940
And finally, if we're saving an ability, we need to know the ability level.

03:08.940 --> 03:14.550
So we'll have an int 32 called level or rather ability level, either one.

03:14.550 --> 03:17.490
And it could be an int 32 or a float.

03:17.490 --> 03:18.330
Doesn't matter.

03:18.330 --> 03:22.500
Ability levels are typically floats, but we can save it as an integer.

03:22.500 --> 03:23.880
That's totally fine.

03:24.000 --> 03:29.400
So we have this struct that defines all the information for saving an ability.

03:29.400 --> 03:36.210
And here in our load screen save game, we want to save all of our abilities so we can have an array

03:36.210 --> 03:40.380
of f saved abilities here saved in our save game data.

03:40.380 --> 03:44.340
So let's go ahead and add a new comment that says abilities.

03:45.330 --> 03:54.060
And we'll make a t array of our new struct type F saved ability called saved abilities.

03:54.600 --> 03:56.790
Let's go ahead and give that a new property.

03:58.280 --> 04:00.590
And now we need to save our abilities, right?

04:00.620 --> 04:02.240
So how are we going to do that?

04:02.240 --> 04:09.380
Well, we need to save this in our aura characters save function, that interface function.

04:09.380 --> 04:17.630
Let's go to character in the private folder or a character and find our save function.

04:17.630 --> 04:19.190
Save progress.

04:19.550 --> 04:22.100
So we need to save some data here right.

04:22.100 --> 04:27.590
Well if we're going to save some data here, we need to know how many abilities we have and all the

04:27.590 --> 04:29.150
information about them.

04:29.150 --> 04:32.360
That's all in the ability system component, isn't it?

04:32.360 --> 04:38.150
If we go to our ability system component here in the cpp file, I'm going to remind you of a function

04:38.150 --> 04:40.790
we made called for each ability.

04:41.180 --> 04:46.220
Now for each ability takes in an F for each ability delegate.

04:46.580 --> 04:47.720
What is that?

04:47.720 --> 04:50.840
Well, we can go to the header file to see what it is.

04:50.840 --> 04:56.780
It's a delegate one param that takes in a const reference to a gameplay ability spec.

04:56.780 --> 04:58.310
What does it do?

04:58.310 --> 05:06.680
Well, it loops over all of the activatable abilities, and for each of our abilities, it takes the

05:06.680 --> 05:11.690
delegate passed in to this function and executes it, passing in the ability spec.

05:11.720 --> 05:18.890
Essentially whatever we have bound to this delegate, which must accept an ability spec, it's executing

05:18.890 --> 05:23.300
that functionality for every ability that's in Activatable abilities.

05:23.300 --> 05:24.680
It's a for each loop.

05:24.680 --> 05:30.470
For abilities, well, we can use for each ability in or a character when we want to save our abilities.

05:30.470 --> 05:36.260
So before actually saving our data, we need to use F for each ability.

05:36.260 --> 05:44.480
We're going to make an F for each ability called save ability delegate.

05:44.660 --> 05:46.550
And we're going to bind a lambda to it.

05:46.550 --> 05:50.930
We're going to take save ability delegate using bind lambda.

05:51.350 --> 05:53.870
And we're going to bind a lambda to it.

05:53.870 --> 05:55.310
Let's make that lambda.

05:59.420 --> 06:08.300
And we're going to need an input parameter of const f gameplay ability spec reference called ability

06:08.300 --> 06:08.840
spec.

06:08.840 --> 06:11.510
So what are we going to do with that ability spec.

06:15.360 --> 06:16.830
Just indenting here.

06:16.830 --> 06:19.800
Well, I'd like to make an f saved ability.

06:20.370 --> 06:23.430
We're going to say f saved ability.

06:23.700 --> 06:25.410
Saved ability.

06:27.110 --> 06:30.680
And we're going to set all the properties on our saved ability.

06:31.070 --> 06:34.790
Looks like indentation doesn't want to play nice like that.

06:34.790 --> 06:38.060
I'm going to go ahead and have it how it was.

06:38.060 --> 06:43.520
So first of all, what properties on our saved ability do we need to set.

06:43.520 --> 06:45.350
Well let's look at that struct.

06:45.500 --> 06:48.080
We have the gameplay ability itself.

06:48.080 --> 06:49.490
How are we going to get that?

06:49.490 --> 06:55.850
Well, there's only one place that stores all of the gameplay ability classes the T sub class UVs and

06:55.850 --> 06:58.490
associates them with ability tags.

06:58.700 --> 07:01.580
That's our ability info data asset.

07:01.760 --> 07:08.180
Well, we can get that ability info data asset from Aura Ability System library.

07:08.180 --> 07:15.440
We can say you aura ability system library get ability info.

07:15.440 --> 07:17.930
Now this requires a world context object.

07:17.930 --> 07:18.530
No problem.

07:18.530 --> 07:19.580
We can pass one in.

07:19.580 --> 07:27.170
We just have to remember that get ability info is only going to return ability info on the server because

07:27.170 --> 07:29.330
stores only the game mode has it.

07:29.330 --> 07:31.610
This gets it from the game mode right?

07:31.610 --> 07:34.100
So really we should only be on the server here.

07:34.100 --> 07:37.970
In fact, let's just check for authority before we continue.

07:38.120 --> 07:42.140
We'll say if not, has authority return.

07:43.210 --> 07:47.230
So we won't even save the game if we're not authority.

07:47.260 --> 07:52.120
Now get ability info has squiggles because this is not captured.

07:52.120 --> 07:54.100
No problem, we'll capture this.

07:54.100 --> 07:57.640
And now that we have ability info we can call a function on it.

07:57.640 --> 08:02.650
Find ability info for tag passing in the ability tag.

08:02.950 --> 08:08.260
So how do we get our ability tag when all we have is the ability spec?

08:08.380 --> 08:11.560
Well let's look at our ability system component functions.

08:11.560 --> 08:14.410
We have a lot of useful functions.

08:14.410 --> 08:20.440
We have get ability tag from spec, and that can take an ability spec and give us the ability tag so

08:20.440 --> 08:21.370
we can use that.

08:21.370 --> 08:26.560
Now if we're going to use the ability system component, we need to capture it and we're going to have

08:26.560 --> 08:30.640
to cast our ability system component to our ability system component.

08:30.640 --> 08:33.430
And I'd like to do that before we enter the lambda.

08:33.430 --> 08:35.620
And we can just capture that local variable.

08:35.620 --> 08:44.260
So we're going to say you or a ability system component or a ASC will cast to it you or a ability system

08:44.260 --> 08:44.980
component.

08:44.980 --> 08:47.290
And we'll cast ability system component.

08:48.250 --> 08:53.470
And then we'll just capture or ask in our capture list along with this.

08:53.470 --> 09:01.720
And when we find ability info for tag, we can take or ask and call get ability tag from spec and pass

09:01.720 --> 09:03.400
in ability spec.

09:05.020 --> 09:08.080
Now this is a big line just to get the ability tag.

09:08.080 --> 09:11.440
So I'm going to need to manage this a little bit.

09:11.440 --> 09:15.010
I'm going to make a F gameplay tag.

09:15.130 --> 09:18.580
This can be const and it's going to be ability tag.

09:19.930 --> 09:22.450
So I'm going to use or ASC here.

09:26.230 --> 09:32.410
So now I have the tag and now we have an ability tag to pass in here.

09:32.440 --> 09:36.760
Now I'm also going to store my ability info in a pointer.

09:36.760 --> 09:41.620
So let's get the ability tag and the ability info up here.

09:43.120 --> 09:50.110
We'll also have you ability info called ability info equal to this line here.

09:52.970 --> 09:55.400
Now that's just this function.

09:55.400 --> 09:57.680
Call this one here.

10:00.630 --> 10:04.230
Is what we can use to retrieve an F or a ability info.

10:04.260 --> 10:08.940
We'll call it info that's going to be on ability info.

10:08.940 --> 10:12.090
The data asset Findability info for tag.

10:12.090 --> 10:12.630
Passing in.

10:12.630 --> 10:13.590
Ability tag.

10:14.310 --> 10:17.850
Okay, so we have the data assets.

10:17.850 --> 10:21.120
We have the struct for the given ability tag.

10:21.120 --> 10:24.180
And now we can set some things on our saved ability.

10:24.180 --> 10:26.160
We can take saved ability.

10:27.150 --> 10:33.120
Dot gameplay ability, and we can get the ability that we have in our ability info that we found for

10:33.120 --> 10:36.360
the tag we can take info dot ability.

10:36.360 --> 10:37.950
That's the subclass of.

10:39.170 --> 10:42.140
Now saved ability has other things.

10:42.140 --> 10:43.910
We have ability level.

10:44.570 --> 10:47.090
Now we can get that from the ability spec.

10:48.470 --> 10:50.060
Ability spec level.

10:50.090 --> 10:52.310
We also have saved ability.

10:52.700 --> 10:55.610
Dot here's ability slot.

10:55.610 --> 10:58.850
Well we can get that from our aura ability system component.

10:58.850 --> 11:06.530
So aura AC get slot from ability tag for example and pass in ability tag and we have the slot.

11:06.920 --> 11:13.190
What else do we have saved ability dot here's ability status.

11:13.340 --> 11:15.530
Well we can take aura AC.

11:17.460 --> 11:20.790
And call git status from ability tag.

11:21.660 --> 11:27.390
So we've done a whole bunch of work up front that's making our life a lot easier now, as we don't have

11:27.390 --> 11:29.160
to go and make those functions.

11:29.160 --> 11:32.430
So we have four pieces of information.

11:32.430 --> 11:35.760
Let's look at load screen, save game and take a look at saved ability.

11:35.760 --> 11:36.810
We have ability.

11:36.810 --> 11:43.950
We have ability, tag ability, status ability slot ability level ability level slot status.

11:43.950 --> 11:46.260
And here's our ability tag.

11:46.410 --> 11:55.020
We can set that here to saved ability dot ability tag equals ability tag okay.

11:55.020 --> 11:57.660
So we have a saved ability and we filled it out.

11:57.660 --> 11:58.410
Great.

11:58.410 --> 11:59.880
Now what do we do with it.

11:59.880 --> 12:05.190
Well we need to capture save data and save data right here.

12:05.190 --> 12:07.230
It's a save data pointer.

12:07.230 --> 12:10.050
And we can pass that pointer into the capture list.

12:10.050 --> 12:12.270
I'm going to pass it in by reference.

12:12.270 --> 12:14.340
So we won't even copy that pointer.

12:14.340 --> 12:20.610
And we're going to take save data and take its saved abilities array and add to it.

12:20.610 --> 12:23.550
We're going to add saved ability.

12:23.550 --> 12:26.850
So we have a lambda bound to this delegate.

12:26.850 --> 12:33.360
And if it gets executed with an ability spec passed in then it's going to create a saved ability and

12:33.360 --> 12:36.030
add it to save data which is captured.

12:36.390 --> 12:38.130
Really we could capture by pointer.

12:38.130 --> 12:39.210
It doesn't have to be reference.

12:39.210 --> 12:39.900
That's fine.

12:39.900 --> 12:48.120
Now after creating this lambda I want this lambda to be executed for each ability.

12:48.120 --> 12:54.600
So that's why aura Ability, system component or ask has for each ability.

12:54.630 --> 12:59.010
Because we can pass this save ability delegate in.

13:02.890 --> 13:11.620
So after we've done this, our save game object save data is going to have all of our abilities added

13:11.620 --> 13:15.010
to it in the form of an F saved ability.

13:15.010 --> 13:16.510
That's all of them.

13:16.510 --> 13:22.990
All the abilities in Activatable abilities, no matter what ability type they have, no matter what

13:22.990 --> 13:28.330
their status is, no matter their slot or their ability tag.

13:28.330 --> 13:30.250
Now I just said ability type.

13:30.250 --> 13:35.200
And that reminds me, we're going to probably want to know the ability type, whether it's offensive

13:35.200 --> 13:37.000
or passive or neither.

13:37.000 --> 13:43.810
So let's go back to load screen save game and add one more gameplay tag for the ability type.

13:45.800 --> 13:48.470
So this will be simply ability type.

13:50.240 --> 13:55.910
And here in our character, we're going to set that to we're going to get saved ability.

13:57.380 --> 13:59.120
Dot ability type.

14:01.090 --> 14:09.880
And we can get or ask get ability type and we don't have get ability type do we.

14:09.880 --> 14:10.570
That's okay.

14:10.570 --> 14:12.820
The ability type is an ability info.

14:12.820 --> 14:15.940
We can take info dot ability type.

14:16.090 --> 14:17.170
That's fine.

14:17.410 --> 14:19.330
So now we're saving that too.

14:19.360 --> 14:21.550
So we're saving all this information.

14:21.550 --> 14:26.920
And once we load up we can give ourselves those abilities from the save data.

14:26.920 --> 14:29.440
And we're going to do that in the next video.

14:29.440 --> 14:31.210
So let's go ahead and compile this.

14:31.210 --> 14:36.760
Make sure there's nothing screaming out at us from the compiler.

14:36.940 --> 14:39.130
So we have a successful compile.

14:39.130 --> 14:43.780
And in the next video we'll go about loading our abilities from disk.

14:44.350 --> 14:45.220
Great job.

14:45.220 --> 14:45.940
I'll see you soon.
