WEBVTT

00:06.850 --> 00:07.980
Welcome back.

00:08.020 --> 00:11.440
So we're now ready to start making some gameplay abilities.

00:11.470 --> 00:15.690
Now we could just make a blueprint based on the gameplay ability class.

00:15.700 --> 00:22.900
If we go to ability system, we could easily just create a new blueprint and search for gameplay ability.

00:23.530 --> 00:25.150
And here's the class.

00:25.150 --> 00:31.090
Now we could do that, but much like we've created a base class for some of our other classes, I'd

00:31.090 --> 00:37.030
like to make a base class for our gameplay abilities that we'll be using throughout this game project.

00:37.240 --> 00:42.850
And that way if we have any common functionality that all of our gameplay abilities should have, then

00:42.850 --> 00:45.910
we'll have that in our base gameplay ability class.

00:46.300 --> 00:53.770
So we can go into C plus plus classes or public ability system and we'll make a new class.

00:53.770 --> 00:58.420
I'd like to put it in a new folder called Abilities, so we'll do that.

00:58.450 --> 01:01.690
Let's go ahead and create a new C plus plus class.

01:01.690 --> 01:08.720
We'll choose all classes and find gameplay ability and choose gameplay ability.

01:09.440 --> 01:10.520
Here it is.

01:10.760 --> 01:14.060
And we'll put it in its own folder called Abilities.

01:14.790 --> 01:17.820
And this is going to be our base ability class.

01:17.820 --> 01:18.990
We'll call it aura.

01:19.030 --> 01:23.200
Gameplay ability or whatever prefix you're using in your project.

01:23.220 --> 01:25.290
So I'm going to create the class.

01:25.440 --> 01:27.990
I'm going to go ahead and close down the editor.

01:28.640 --> 01:32.100
And wait for my new folder to show up in ability.

01:32.120 --> 01:32.660
System.

01:32.660 --> 01:33.620
Here it is.

01:33.620 --> 01:35.800
And there's our gameplay ability.

01:35.810 --> 01:41.210
I'm going to go ahead and close all tabs and open our gameplay ability.

01:41.210 --> 01:46.670
We see that it's CP file is empty and so is its H file pretty much.

01:46.850 --> 01:47.630
So.

01:47.630 --> 01:49.880
Here's our gameplay ability class.

01:50.420 --> 01:53.600
Now we want to be able to grant abilities.

01:53.600 --> 01:57.380
They have to be granted and we do this usually on the server.

01:57.380 --> 02:05.150
So the approach that we'll take for now is to just give our character a list of abilities that should

02:05.150 --> 02:07.040
be given at the beginning of the game.

02:07.220 --> 02:14.330
So I'm going to go into my public character folder and open my Aura character base.

02:14.690 --> 02:22.100
Let's get that header file open there and we're going to add a t array of gameplay ability classes of

02:22.100 --> 02:28.460
T subclasses, and then we can set that t array from within the character blueprint.

02:28.460 --> 02:33.350
Now this can be a private variable, so I'm going to add a private section.

02:35.180 --> 02:38.480
And this will be a t array of t subclassof.

02:38.510 --> 02:43.040
So t subclassof storing a u gameplay ability.

02:44.090 --> 02:48.440
Now this will be called startup abilities.

02:48.680 --> 02:53.240
So these will be the abilities that should be given from the beginning of the game.

02:53.510 --> 02:56.720
And I'm missing a an angle bracket there.

02:57.290 --> 02:58.580
And there we go.

02:59.120 --> 03:05.180
So I'm going to go ahead and give this a U property right off the bat with edit anywhere.

03:06.320 --> 03:12.320
And these can be in the category of abilities.

03:12.800 --> 03:18.830
So we'll have an array of abilities and we're going to want a way to give these abilities.

03:19.100 --> 03:22.220
And we do this through the ability system component.

03:22.550 --> 03:27.980
So let's make a function here on or a character base for adding those abilities.

03:27.980 --> 03:34.430
So we'll make this a protected function just in case we want to override it in child classes and it'll

03:34.460 --> 03:38.580
be a void function called add character abilities.

03:41.070 --> 03:43.320
Let's go ahead and make a definition for this.

03:44.570 --> 03:49.800
And add character abilities is something that should only add abilities on the server.

03:49.820 --> 03:52.760
So the first thing I'm going to do is check for authority.

03:52.850 --> 03:57.380
We'll say if not has authority, then we'll return.

03:58.150 --> 04:02.920
Now, what do we do if we do have authority, we want to grant the ability.

04:03.460 --> 04:09.760
Now, this is something that the ability system component has to do, and I'd like our ability system

04:09.760 --> 04:12.550
component to actually be the one to handle it.

04:12.550 --> 04:17.860
So even though we have a function here on the character class, it's going to call a function on the

04:17.860 --> 04:22.210
ability system component, which will then give the start up abilities.

04:22.210 --> 04:30.070
So let's go to our ability system folder and open our ability system component and let's add a public

04:30.070 --> 04:33.400
function that we can call to give those start up abilities.

04:33.400 --> 04:35.110
And this will be a void function.

04:35.110 --> 04:39.430
We can call it add character abilities, we can call it give start up abilities.

04:39.430 --> 04:44.080
It doesn't matter just to be consistent, we'll call it add character abilities.

04:44.080 --> 04:49.720
The difference is this function needs to take in those gameplay ability classes, so I'm going to pass

04:49.720 --> 04:52.210
them in by const reference to a t array.

04:52.360 --> 04:59.780
So it'll be a t array storing t subclass of classes of you gameplay abilities.

04:59.780 --> 05:04.820
This will be a const reference and we'll call this start up abilities.

05:05.810 --> 05:09.230
So let's go ahead and generate the definition for this function.

05:09.230 --> 05:12.680
And this will be what we call from the base character class.

05:12.680 --> 05:14.720
So what is this function going to do?

05:14.750 --> 05:16.820
Well, we're getting a t array of abilities.

05:16.820 --> 05:20.230
We want to add those abilities, so we're going to loop through them.

05:20.240 --> 05:25.760
So we'll say for and it's going to be t subclass of gameplay abilities.

05:25.760 --> 05:27.230
We'll loop through those.

05:27.320 --> 05:37.430
We'll call this ability class for each of those in start up abilities and we want to grant the abilities.

05:37.550 --> 05:39.500
So how do we grant the abilities?

05:39.500 --> 05:45.620
Well, we need to create an ability spec from each of these classes and that's pretty easy to do.

05:45.650 --> 05:49.790
We just create an F gameplay ability spec.

05:50.180 --> 05:53.780
This is a struct that requires an ability class.

05:53.780 --> 06:00.740
We're going to pass in the class ability class and it also requires an ability level.

06:00.740 --> 06:05.570
For now we'll just pass in one and these are in 30 twos for levels.

06:05.570 --> 06:13.550
So ability levels are integers and we can store this in a local variable, we can say const F gameplay

06:13.580 --> 06:17.480
ability spec and we'll call this ability spec.

06:17.780 --> 06:23.540
And once we have a spec, we can simply give the ability with a function that exists on the ability

06:23.540 --> 06:29.600
system component called give ability, and it requires that ability spec, we're going to pass it in

06:30.500 --> 06:32.960
and with that we have the ability.

06:33.260 --> 06:35.750
Now that's one option.

06:35.780 --> 06:40.010
Another option is to give the ability and activate it immediately.

06:40.010 --> 06:46.790
There's a function called give ability and activate once, and this one requires the ability spec,

06:46.790 --> 06:51.920
we'll pass that in and it also takes in an optional gameplay event data.

06:51.920 --> 06:53.390
We'll learn about those later.

06:53.390 --> 06:55.590
For now we'll give this a try.

06:55.610 --> 07:03.320
Now the red squiggles say Non-const Lvalue reference cannot bind to lvalue type const f gameplay ability

07:03.320 --> 07:03.770
spec.

07:03.800 --> 07:09.380
This is telling us that this can't be const if we're going to give ability and apply once.

07:09.380 --> 07:12.770
So that's an important nuance to understand.

07:12.770 --> 07:19.400
Give ability can accept a const ability spec, but if you're going to give and activate once it cannot

07:19.400 --> 07:21.860
be const something to keep in mind.

07:22.040 --> 07:29.060
So we have two options now I'm going to comment out, give ability and I'm going to leave this one.

07:29.060 --> 07:34.940
Give ability and activate once because I'd like to see what happens when an ability gets activated.

07:34.940 --> 07:40.460
And this is perhaps at this stage the easiest way that we know how to activate an ability.

07:40.850 --> 07:44.060
So the last thing to do here is to call this function.

07:44.060 --> 07:50.180
We're going to go back into our character base, and if we have authority, we'll call the function.

07:50.180 --> 07:55.640
But this means we need to access the ability system component and we're going to cast it.

07:55.640 --> 08:00.770
So we're going to say you ora ability system component, right?

08:00.920 --> 08:06.050
And as soon as I do that, Ryder is going to include my header for it.

08:06.320 --> 08:12.920
This will be a pointer, we'll call it ora AC and it's going to be the result of a cast and I'll go

08:12.920 --> 08:20.300
ahead and use cast checked and this will be casting to Ora ability system component and we're casting

08:20.570 --> 08:22.310
ability system component.

08:22.940 --> 08:30.710
Now once we have that and if we have authority, we're going to call Ora AC Now, we could call give

08:30.740 --> 08:36.920
ability directly, but as I said, I'd like to give that responsibility to the ability system component

08:36.920 --> 08:37.790
itself.

08:37.790 --> 08:40.640
So we're going to call add character abilities here.

08:41.330 --> 08:49.190
So add character abilities, which requires the start up abilities and we have that array start up abilities.

08:49.650 --> 08:53.270
So the question now is when do we call add character abilities?

08:53.280 --> 08:55.200
So where is a good place to call this?

08:55.200 --> 08:59.880
Well, for Aura, a good place to call it is in possessed by.

09:00.030 --> 09:01.920
And we'll take care of aura for now.

09:01.920 --> 09:03.360
We'll handle the enemy later.

09:03.360 --> 09:10.380
So let's go into the private folder, into character and open aura character dot CP and right here in

09:10.380 --> 09:17.460
possessed by after we've called init ability actor info, let's call our new function which we called

09:17.700 --> 09:19.470
add character abilities.

09:20.560 --> 09:22.030
So we'll call that.

09:23.370 --> 09:28.540
And now we should see our character abilities added after an ability actor info.

09:28.560 --> 09:34.860
So now that we're calling this function, we expect to be granted all the abilities in our startup Abilities

09:34.860 --> 09:35.610
array.

09:35.760 --> 09:38.280
The last thing we can do is test this out.

09:38.460 --> 09:42.120
So let's go ahead and compile and launch the editor.

09:43.310 --> 09:47.870
So when trying to compile, I have some errors here.

09:47.870 --> 09:49.010
I'm going to look at the first one.

09:49.010 --> 09:52.880
It says you game ability undeclared identifier right here.

09:52.880 --> 09:55.610
We can fix that pretty easily.

09:55.700 --> 09:57.800
I'm going to forward declare it here.

09:58.310 --> 10:05.540
So up at the forward declarations, let's forward declare you game playability and that's going to take

10:05.540 --> 10:06.650
care of that error.

10:06.650 --> 10:08.570
So let's go ahead and launch the editor.

10:10.950 --> 10:17.040
And with the editor open, the last thing to do is give our character some abilities.

10:17.160 --> 10:19.500
Now, first I'm going to open the character class.

10:19.500 --> 10:21.380
So character aura.

10:21.430 --> 10:23.910
Here's BP Aura character.

10:24.060 --> 10:27.330
And that array should be in abilities.

10:27.570 --> 10:29.670
So searching for abilities.

10:30.260 --> 10:32.430
Here's our start up abilities array.

10:32.450 --> 10:34.360
Now we need an ability to give.

10:34.370 --> 10:42.010
If I click plus and I open the dropdown, well, I could give the default or a game play ability.

10:42.020 --> 10:48.380
I can even give the base game play ability class and any of the other two built in ability classes.

10:48.380 --> 10:52.400
But I'm going to make a blueprint based on my aura gameplay ability class.

10:52.400 --> 10:58.340
So I'm going to go into Blueprints ability system and we'll make a new folder for gameplay abilities.

10:58.340 --> 11:01.430
This will be called gameplay abilities.

11:01.670 --> 11:09.080
We'll open this up, we'll make a new blueprint class here based on aura gameplay ability.

11:09.980 --> 11:11.300
Let's make that.

11:11.300 --> 11:16.730
And I'm just going to call this GA for gameplay ability test.

11:16.760 --> 11:18.440
Gameplay ability.

11:19.340 --> 11:21.710
Let's double click this and open it up now.

11:21.710 --> 11:24.680
Here's what a gameplay ability blueprint looks like.

11:24.710 --> 11:30.080
Notice it has an event, activate ability and an event on end ability.

11:30.110 --> 11:35.930
So we have an event and of course there are C plus plus functions as well that we can implement.

11:35.930 --> 11:41.840
But here in Blueprint we have an event activate ability which as you can imagine, is executed when

11:41.840 --> 11:43.730
the ability is activated.

11:43.760 --> 11:45.500
We can prove that to ourselves.

11:45.500 --> 11:52.130
Let's print a string and we're going to say test ability activated.

11:53.430 --> 12:00.060
And we'll change its color to orange and we'll change its duration to five seconds.

12:00.210 --> 12:03.140
That way we'll know when the ability is activated.

12:03.150 --> 12:06.200
But let's also print something on end ability.

12:06.210 --> 12:08.580
So we'll go ahead and duplicate this.

12:09.400 --> 12:13.150
Drag it in and I'm going to change its color to a more red color.

12:14.180 --> 12:17.000
And this will say test ability ended.

12:18.330 --> 12:22.050
Okay, so now we know our ability is doing something.

12:22.050 --> 12:29.460
Let's compile and save and let's go to Aura character and add this new ability to test gameplay, ability,

12:29.460 --> 12:30.990
compile and save.

12:31.110 --> 12:36.180
And now we should expect this to be granted and activated when we press play.

12:36.180 --> 12:43.020
So I'm going to save all press play and there we see test ability activated and then we can move on

12:43.020 --> 12:44.160
with our lives.

12:44.250 --> 12:48.960
But notice we never got that end ability print string executed.

12:48.960 --> 12:53.310
So events on end ability was never called.

12:53.310 --> 13:00.420
Now abilities can end themselves if I right click and type end ability look at that end ability.

13:00.450 --> 13:07.770
We also have end ability locally and end ability state as abilities can have a concept of ability states.

13:08.040 --> 13:11.070
For now let's just concern ourselves with end ability.

13:11.160 --> 13:17.280
As soon as we've printed the string we can end the ability, we can even use delays and other asynchronous

13:17.280 --> 13:19.120
actions here in abilities.

13:19.300 --> 13:23.050
Why don't we do a delay of, say, five seconds?

13:24.160 --> 13:26.230
And then we can end the ability there.

13:26.410 --> 13:27.580
Let's compile.

13:27.580 --> 13:28.580
Let's press play.

13:28.600 --> 13:29.920
There's our string.

13:29.920 --> 13:34.780
And in five seconds, we should see testability ended.

13:34.810 --> 13:36.040
There it is.

13:36.070 --> 13:38.080
Our ability has been ended.

13:38.170 --> 13:39.420
So there we have it.

13:39.430 --> 13:42.250
We've created our first gameplay ability class.

13:42.280 --> 13:49.240
We've added an array of startup abilities to our base character class and we filled it in with a single

13:49.240 --> 13:50.300
gameplay ability.

13:50.320 --> 13:55.240
We've created a blueprint based on our gameplay ability class printing a couple strings.

13:55.240 --> 13:57.070
So pretty basic so far.

13:57.370 --> 14:02.800
And we've also created functions to give these abilities in our base character class.

14:02.800 --> 14:04.670
We have Add character abilities.

14:04.690 --> 14:11.740
All this does is accesses the ability system component and calls add character abilities.

14:11.770 --> 14:19.450
We call this function in or a character in possessed by and our ability system component class loops

14:19.450 --> 14:25.310
through this array of gameplay abilities and calls give ability and activate once.

14:25.340 --> 14:31.640
Now we are capable of giving the ability and not activating it, and that's with give ability.

14:31.790 --> 14:37.520
So we have two options there that we've learned about so far, and because we're giving the ability

14:37.520 --> 14:44.900
and activating it immediately, we're getting our event activate ability executed from within our test

14:44.900 --> 14:46.070
gameplay ability.

14:46.340 --> 14:52.250
And we've seen that we can use asynchronous nodes here such as DeLay, and we're waiting five seconds

14:52.250 --> 14:57.840
and then ending the ability which we're proving is working with another print string node.

14:57.860 --> 14:59.180
So great job.

14:59.180 --> 15:02.020
We've now created our first gameplay ability.

15:02.030 --> 15:03.530
This is only the beginning.

15:03.530 --> 15:05.840
We'll continue with this in the next video.

15:05.990 --> 15:07.280
I'll see you soon.
