Welcome back.
So we're now ready to start making some gameplay abilities.
Now we could just make a blueprint based on the gameplay ability class.
If we go to ability system, we could easily just create a new blueprint and search for gameplay ability.
And here's the class.
Now we could do that, but much like we've created a base class for some of our other classes, I'd
like to make a base class for our gameplay abilities that we'll be using throughout this game project.
And that way if we have any common functionality that all of our gameplay abilities should have, then
we'll have that in our base gameplay ability class.
So we can go into C plus plus classes or public ability system and we'll make a new class.
I'd like to put it in a new folder called Abilities, so we'll do that.
Let's go ahead and create a new C plus plus class.
We'll choose all classes and find gameplay ability and choose gameplay ability.
Here it is.
And we'll put it in its own folder called Abilities.
And this is going to be our base ability class.
We'll call it aura.
Gameplay ability or whatever prefix you're using in your project.
So I'm going to create the class.
I'm going to go ahead and close down the editor.
And wait for my new folder to show up in ability.
System.
Here it is.
And there's our gameplay ability.
I'm going to go ahead and close all tabs and open our gameplay ability.
We see that it's CP file is empty and so is its H file pretty much.
So.
Here's our gameplay ability class.
Now we want to be able to grant abilities.
They have to be granted and we do this usually on the server.
So the approach that we'll take for now is to just give our character a list of abilities that should
be given at the beginning of the game.
So I'm going to go into my public character folder and open my Aura character base.
Let's get that header file open there and we're going to add a t array of gameplay ability classes of
T subclasses, and then we can set that t array from within the character blueprint.
Now this can be a private variable, so I'm going to add a private section.
And this will be a t array of t subclassof.
So t subclassof storing a u gameplay ability.
Now this will be called startup abilities.
So these will be the abilities that should be given from the beginning of the game.
And I'm missing a an angle bracket there.
And there we go.
So I'm going to go ahead and give this a U property right off the bat with edit anywhere.
And these can be in the category of abilities.
So we'll have an array of abilities and we're going to want a way to give these abilities.
And we do this through the ability system component.
So let's make a function here on or a character base for adding those abilities.
So we'll make this a protected function just in case we want to override it in child classes and it'll
be a void function called add character abilities.
Let's go ahead and make a definition for this.
And add character abilities is something that should only add abilities on the server.
So the first thing I'm going to do is check for authority.
We'll say if not has authority, then we'll return.
Now, what do we do if we do have authority, we want to grant the ability.
Now, this is something that the ability system component has to do, and I'd like our ability system
component to actually be the one to handle it.
So even though we have a function here on the character class, it's going to call a function on the
ability system component, which will then give the start up abilities.
So let's go to our ability system folder and open our ability system component and let's add a public
function that we can call to give those start up abilities.
And this will be a void function.
We can call it add character abilities, we can call it give start up abilities.
It doesn't matter just to be consistent, we'll call it add character abilities.
The difference is this function needs to take in those gameplay ability classes, so I'm going to pass
them in by const reference to a t array.
So it'll be a t array storing t subclass of classes of you gameplay abilities.
This will be a const reference and we'll call this start up abilities.
So let's go ahead and generate the definition for this function.
And this will be what we call from the base character class.
So what is this function going to do?
Well, we're getting a t array of abilities.
We want to add those abilities, so we're going to loop through them.
So we'll say for and it's going to be t subclass of gameplay abilities.
We'll loop through those.
We'll call this ability class for each of those in start up abilities and we want to grant the abilities.
So how do we grant the abilities?
Well, we need to create an ability spec from each of these classes and that's pretty easy to do.
We just create an F gameplay ability spec.
This is a struct that requires an ability class.
We're going to pass in the class ability class and it also requires an ability level.
For now we'll just pass in one and these are in 30 twos for levels.
So ability levels are integers and we can store this in a local variable, we can say const F gameplay
ability spec and we'll call this ability spec.
And once we have a spec, we can simply give the ability with a function that exists on the ability
system component called give ability, and it requires that ability spec, we're going to pass it in
and with that we have the ability.
Now that's one option.
Another option is to give the ability and activate it immediately.
There's a function called give ability and activate once, and this one requires the ability spec,
we'll pass that in and it also takes in an optional gameplay event data.
We'll learn about those later.
For now we'll give this a try.
Now the red squiggles say Non-const Lvalue reference cannot bind to lvalue type const f gameplay ability
spec.
This is telling us that this can't be const if we're going to give ability and apply once.
So that's an important nuance to understand.
Give ability can accept a const ability spec, but if you're going to give and activate once it cannot
be const something to keep in mind.
So we have two options now I'm going to comment out, give ability and I'm going to leave this one.
Give ability and activate once because I'd like to see what happens when an ability gets activated.
And this is perhaps at this stage the easiest way that we know how to activate an ability.
So the last thing to do here is to call this function.
We're going to go back into our character base, and if we have authority, we'll call the function.
But this means we need to access the ability system component and we're going to cast it.
So we're going to say you ora ability system component, right?
And as soon as I do that, Ryder is going to include my header for it.
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
ahead and use cast checked and this will be casting to Ora ability system component and we're casting
ability system component.
Now once we have that and if we have authority, we're going to call Ora AC Now, we could call give
ability directly, but as I said, I'd like to give that responsibility to the ability system component
itself.
So we're going to call add character abilities here.
So add character abilities, which requires the start up abilities and we have that array start up abilities.
So the question now is when do we call add character abilities?
So where is a good place to call this?
Well, for Aura, a good place to call it is in possessed by.
And we'll take care of aura for now.
We'll handle the enemy later.
So let's go into the private folder, into character and open aura character dot CP and right here in
possessed by after we've called init ability actor info, let's call our new function which we called
add character abilities.
So we'll call that.
And now we should see our character abilities added after an ability actor info.
So now that we're calling this function, we expect to be granted all the abilities in our startup Abilities
array.
The last thing we can do is test this out.
So let's go ahead and compile and launch the editor.
So when trying to compile, I have some errors here.
I'm going to look at the first one.
It says you game ability undeclared identifier right here.
We can fix that pretty easily.
I'm going to forward declare it here.
So up at the forward declarations, let's forward declare you game playability and that's going to take
care of that error.
So let's go ahead and launch the editor.
And with the editor open, the last thing to do is give our character some abilities.
Now, first I'm going to open the character class.
So character aura.
Here's BP Aura character.
And that array should be in abilities.
So searching for abilities.
Here's our start up abilities array.
Now we need an ability to give.
If I click plus and I open the dropdown, well, I could give the default or a game play ability.
I can even give the base game play ability class and any of the other two built in ability classes.
But I'm going to make a blueprint based on my aura gameplay ability class.
So I'm going to go into Blueprints ability system and we'll make a new folder for gameplay abilities.
This will be called gameplay abilities.
We'll open this up, we'll make a new blueprint class here based on aura gameplay ability.
Let's make that.
And I'm just going to call this GA for gameplay ability test.
Gameplay ability.
Let's double click this and open it up now.
Here's what a gameplay ability blueprint looks like.
Notice it has an event, activate ability and an event on end ability.
So we have an event and of course there are C plus plus functions as well that we can implement.
But here in Blueprint we have an event activate ability which as you can imagine, is executed when
the ability is activated.
We can prove that to ourselves.
Let's print a string and we're going to say test ability activated.
And we'll change its color to orange and we'll change its duration to five seconds.
That way we'll know when the ability is activated.
But let's also print something on end ability.
So we'll go ahead and duplicate this.
Drag it in and I'm going to change its color to a more red color.
And this will say test ability ended.
Okay, so now we know our ability is doing something.
Let's compile and save and let's go to Aura character and add this new ability to test gameplay, ability,
compile and save.
And now we should expect this to be granted and activated when we press play.
So I'm going to save all press play and there we see test ability activated and then we can move on
with our lives.
But notice we never got that end ability print string executed.
So events on end ability was never called.
Now abilities can end themselves if I right click and type end ability look at that end ability.
We also have end ability locally and end ability state as abilities can have a concept of ability states.
For now let's just concern ourselves with end ability.
As soon as we've printed the string we can end the ability, we can even use delays and other asynchronous
actions here in abilities.
Why don't we do a delay of, say, five seconds?
And then we can end the ability there.
Let's compile.
Let's press play.
There's our string.
And in five seconds, we should see testability ended.
There it is.
Our ability has been ended.
So there we have it.
We've created our first gameplay ability class.
We've added an array of startup abilities to our base character class and we filled it in with a single
gameplay ability.
We've created a blueprint based on our gameplay ability class printing a couple strings.
So pretty basic so far.
And we've also created functions to give these abilities in our base character class.
We have Add character abilities.
All this does is accesses the ability system component and calls add character abilities.
We call this function in or a character in possessed by and our ability system component class loops
through this array of gameplay abilities and calls give ability and activate once.
Now we are capable of giving the ability and not activating it, and that's with give ability.
So we have two options there that we've learned about so far, and because we're giving the ability
and activating it immediately, we're getting our event activate ability executed from within our test
gameplay ability.
And we've seen that we can use asynchronous nodes here such as DeLay, and we're waiting five seconds
and then ending the ability which we're proving is working with another print string node.
So great job.
We've now created our first gameplay ability.
This is only the beginning.
We'll continue with this in the next video.
I'll see you soon.