Welcome back.
Now we're updating our ability statuses in the ability system component.
Actually, we're not doing that, but we have a function that can we're not calling it yet, but once
we do call it, then we'll be updating our ability statuses.
Specifically, what that means is we'll be looping through ability info and checking to see if any of
those gameplay abilities that have not been granted yet have a level requirement that we now meet.
But we need to call this function and pass in the current level as soon as we level up.
And we can easily do that because our Aura character has an interface function implementation.
If we go to Aura character, let's go to the CPP file and character or a character.
We have a couple of options.
We have add to player level that gets called and on the server from the attribute set and we also have
level up.
Now I'd like level up to just be concerned with, you know, cosmetics and things that happen as a result
of gaining a level and then add to player level, which calls add to level on the player state.
This is where I'd like to get the ability system component and call that function update ability statuses.
Now we need the ability system component.
So we're going to say you aura ability system component or ASC we'll cast to you or ability system component
didn't mean to include that library.
So I'm going to undo that.
It's going to be your ability system component and we're casting and we'll just call it get ability
system component.
Now I'm just going to wrap this in an if statement.
And here in the if statement, we'll take our ask and we can call update ability statuses passing in
the new level in player level.
And now the ability system component will respond.
And it's going to give any abilities that exist in the ability info that we meet the level requirements
for now.
But now we need to tell our widget controllers about this.
They need to know so they can update their widgets.
So our ability system component could use a new delegate.
I'd like to broadcast a couple of gameplay tags through a delegate, the ability tag and the new status.
So I'm going to declare a new delegate.
I'm going to say declare multicast delegate and it'll have two params I'm going to call it F ability
status changed and it's going to broadcast two gameplay tags.
I'll broadcast them by const reference.
So const f gameplay tag and we don't need to say their names, but I'm going to in a comment this will
say ability tag and this should be a const ability tag reference.
And I'm going to have a second gameplay tag.
Only this one will be the status tag.
And I can add an ability status changed delegate right here in the public section called ability status
changed and we'll be broadcasting this.
We could come in here to update ability statuses and broadcast it here, but this is only on the server,
so I want to handle broadcasting this on server and client in the case where the human controlling the
character can receive the broadcast on their machine.
For that reason I'm going to make a special client RPC just for this that will broadcast the ability
tag and the new status.
So here in aura ability system component, we'll go all the way down to the protected section and make
a new client RPC.
It's going to be called client update ability status.
So its inputs will be const gameplay tag reference.
Ability tag and const gameplay tag reference status tag and client update ability status will be a new
function with client and reliable, so we'll go ahead and generate the definition.
It has to have implementation in its name and this client RPC is just going to broadcast the delegate
ability status changed.
So we'll take ability status changed will broadcast.
We're going to broadcast ability tag and we're going to broadcast status tag.
And now all we need to do is call client update ability status in update ability statuses here.
So we'll do it as soon as we've given the ability because we know this ability has just had its status
changed.
So we're going to call client update ability status passing in the ability tag.
That's info dot ability tag.
And we're going to pass in that status.
We know the status is going to be eligible, so we can just pass that straight through.
Right there.
And with that, we now should have a delegate broadcast for when an ability status changes.
And now our widget controller can subscribe to that delegate and broadcast a delegate of its own up
to our widgets, which can update themselves.
Now that can actually be quite an easy thing for us to do.
All we have to do is use our ability info delegate.
So if we just really quickly go over to our private folder into UI, into widget controller and open
spell menu, widget controller and bind callbacks to dependencies, we can simply bind something to
ability status changed.
So we can call Git or ask.
We can get ability status changed.
And we can bind to it.
We can use add lambda.
We could just bind a lambda real quick.
So let's do our square parentheses and curly braces.
And I'm just going to put these braces on their own line.
And the function has to be able to take in a const f gameplay tag called ability tag and a const F gameplay
tag.
Calls status tag.
And all it has to do is get its ability info.
So if ability info remember our widget controllers have ability info as well.
Pretty convenient.
Now if we're going to get ability info, we have to capture this right there in the square brackets
and if ability info is valid we can get the ability info for the ability tag.
We can say for ability info, call it info equals ability info and we can call find ability info for
tag.
All of these helper functions are really really useful aren't they?
We can pass in ability tag and we now have the ability info.
And the thing is we've set the ability tag.
We just need to set the ability status.
So info dot and we have the status tag.
We can set it to status tag.
And then we can broadcast ability info delegate.
So we'll broadcast our info.
So that was pretty easy.
Now, whenever the ability status has changed on the ask, it's going to broadcast it.
Our spell menu is going to receive that info and receive its status tag.
That has just changed.
We know that's the up to date tag.
We'll get the ability info from the data asset and then we'll set the status tag and broadcast up to
our widgets, which should update themselves.
So the last thing to do is just see if we can change that second ability, the one with a level requirement
of two to update in the spell menu as soon as we level up to level two.
All right.
We're back in the editor.
Just double checking the ability tag is abilities lightning.
We still have lightning in our ability info data asset.
It's level requirement is two.
We can grant that ability as soon as we level up to level two and we should see the lightning bolt in
our spell menu.
So let's just see if it works.
We see the locked icon, and as soon as I level up, I expect to see it change and it does not.
So we need to figure out where we're not succeeding.
Now, the first thing I'm going to do is place a breakpoint in update ability statuses just to see what
that level value is.
That should give me some info, so I'm going to go ahead and level up.
And it looks like level is one.
Now, if I just leveled up, I expect it to be two, right?
But this could mean that I've made some kind of logic error.
So let's go back and if I click on gameplay effect execute, I see that I'm calling add to player level.
And you know what the num level ups is one, we only leveled up once, so we're actually passing in
that number of times we've leveled up over to the ability system component, not the total level we
need to pass the total level over.
So instead of passing in player level, we actually need to pass the total player level, which we can
get from Player State.
We can call Aura Player State get player level.
That is the level that we need to pass in.
So once again, fixing that logic error.
Let's see if all this works.
Okay.
Pressing play.
Looking at my spell menu all looks as expected.
Leveling up.
And I still have my break points, so I'm going to remove it and resume.
I have leveled up, I can open my menu and sure enough, I see the lightning bolt.
It's in the eligible state and that means things are working.
Now, we can't just go in there and.
Spend a spell point on it yet.
We haven't implemented that yet, but we do have our icon updating to the eligible state, which is
exactly what I wanted to see.
So this is looking really nice.
Now let's test the client.
We're going to go ahead and increase the number of players to two.
I'm going to full screen my client.
I'm going to look at it.
Looks like it's locked.
I'm going to level up once.
And it works on the client as well.
So that is looking beautiful.
Now I'm going to test one particular scenario, though.
I'm going to press play and I'm going to level up before I even open my spell menu for the first time
and then I'm going to open it up.
I wanted to do that because I wanted to make sure that it gets the current information accurately,
and I'm going to do that on the client as well.
I'm going to level up before the first time I open my spell menu and then open it up after leveling
up just to make sure I see what I expect and I do.
So things are looking really nice.
It's really exciting to be able to see your progress in a visible way.
And before we wrap up, I would like to see if our spell menu updates while it's open, because that's
an important thing too, except I can't move around while it's open, so I temporarily need to disable
that feature.
I need to go into UI overlay WB overlay and I have to go into attribute menu button clicked, which
is an event and in fact I have abstracted it away into input mode UI only.
So that's actually really convenient because all I have to do is disconnect this here and then I should
be able to run around even with my menu open.
So abstracting things into functions is handy.
All right, let's level up.
And there it updated looked good.
And for giggles, let's just test on the client as well.
I'm going to open my menu.
Level up.
And it updates.
So everything works as expected.
Excellent.
I'm going to go ahead and hook that back up.
Everything's looking good so far.
We still have some things to do, though, right?
If I now have an eligible spell, I want to be able to spend points on that spell.
So now we need to start implementing the spell points.
We have to be able to gain spell points.
We have to be able to spend spell points and we have to be able to select globes in our tree so that
we can then click spell point and spend a spell point on it.
So quite a few things to implement in our spell menu, but we're coming right along and things are really
starting to come together, which is really exciting.
Excellent job and I'll see you in the next video.