Welcome back.
So now that we have our ability info data asset, we need to figure out how to get information to the
widgets about which abilities we have equipped or given to our ability system component.
So this is going to involve linking our ability system component with our widgets.
And the middleman for that is our widget controller.
So we're going to open our widget controller.
And the widget controller for this overlay is our overlay widget controller.
So let's go into that class.
I'm going to go ahead and close all tabs for now and open up our public folder and we're going to go
into UI widget controller overlay, widget controller.
Let's get that open.
In addition to this, I'm going to open up my ability system folder and go to aura ability system component
as well.
So these have to communicate somehow with each other.
So how are we going to communicate which abilities we have, or at least when it's appropriate to get
those abilities and look up their data from our data asset?
Well, one way is to create a delegate we can broadcast from our ability system component.
I'd like to broadcast a delegate for when our abilities have been given.
Now this can be a regular, plain old delegate, but in case I want to bind to it from multiple different
classes, it's going to be multicast.
But I don't plan on exposing this to blueprint.
We're just going to broadcast this so our widget controller can pick it up.
So I'm going to declare a multicast delegate and I'm going to call this F abilities given.
So F abilities given can be broadcast whenever we give our abilities.
Let's create this.
It's got to be a public variable.
And I'm going to stick this right here under our other delegate f effect asset tags, and I'm going
to call this abilities given.
And to make it clearer, we could call this abilities given delegate.
And I'm not going to bother renaming our asset tags in this way.
I'd like to stay with the task at hand so we have an ability as given delegate.
I'd like to broadcast this delegate when our abilities have been given.
When is that?
Well, let's go into our CPP file and find out.
Right here we have Add character abilities.
This is when we call give ability.
So after we loop over all the start up abilities that have been passed in here, we know that our abilities
have been given and we can broadcast that delegate abilities given delegate.
So let's go ahead and broadcast that here.
At this point, we know that our abilities have been given, and if we respond to this in our widget
controller, we know that we can access those abilities on the ask ability system component.
So what we'll do is go into our overlay widget controller and what function in this class do we need
to use to bind to our new delegate?
Well, bind callbacks to dependencies is the function where we're doing those things.
So here in bind callbacks to dependencies, we have our ability system component, we can access it
and bind to delegates.
So what do we want to bind to on abilities given?
Well, I'd like a function to bind to it and then we can bind it right here after we've bound to our
other ability system component delegates.
So I'm going to make a new function on my widget controller.
It can be in the protected section and it'll be a void function that takes zero arguments.
And I'm going to call this function on initialize startup abilities.
So we'll call this as soon as we know that the ability system has given all of its startup abilities.
So I'm going to generate a definition for this and bind this callback to our new delegate on the ability
system component.
So we're going to say ability system component.
We're going to get that abilities given delegate or what was it called?
Yes, it's called abilities given delegate.
It's in the public section.
And of course, we can't get this unless we cast to aura ability, system component.
Now we're doing it here.
So what this means is it's now time to have a local variable, right?
So I'm going to make a you or a ability system component called aura ask and set it equal to the result
of this cast here.
And we can actually wrap this in an if so, we're going to say if here and inside the if we're going
to use aura ask.
So instead of casting and calling the function from that cast directly, I'm going to change this to
aura ask.
And then this goes all into our if statement right here like so and let's see if I can hit tab there.
There we go.
Now it's nice and indented and our ability is given.
Delegate has to be accessed from the aura ability system component.
So once we access that here, now we can bind and we're going to use Add you object as this is binding
just to multicast delegate and we can bind using this followed by the address of our new callback,
which is going to be this function here.
So the fully qualified on initialized start up abilities.
Okay.
So as soon as the abilities have been given, we're calling this function, right?
And then we could go in and find all abilities on the ability system component.
But here's the thing.
We can't be absolutely sure of the timing of things here.
For example, let's say that things go as we expect.
Our widget controller reaches this line in the code.
It uses add object and binds its callback here to abilities given delegate.
And let's just assume that our ability system component has not given its abilities yet.
Well, in that case, things are going to work out just fine.
We'll bind to our callback and then our ability system some time later will give the abilities and broadcast
the delegate, at which point our callback will be called and we can access those abilities, look up
their tags in the data asset and all that.
Now consider for a moment what would happen if the ability system component gave its abilities first
and broadcast that delegate before we even got to this line here?
Which one happens first?
Well, we can't be sure because it could change.
It could be different depending on what's happening on the server versus the client and so on.
So we have to take care of both situations.
We have to take care of the situation where the abilities are given first and the broadcast is made,
in which case we'll be binding to that broadcast too late.
And we also have to take into account the situation where the opposite happens.
We bind first and then the AC broadcasts.
So to take care of both, what we can do is have a boolean on the ability system component for when
the abilities have been given.
So I'll put that right under Add character abilities.
It's going to be a bool called be abilities, or rather we should call this startup abilities given.
It'll be false by default, but as soon as we've given abilities we'll set it to true.
So back in our ability system component just before making the broadcast, we're going to set be startup
abilities given equal to true.
That way we can always check that and we can know if those abilities have been given or not.
Now in the widget controller we can check.
So here in bind callbacks to dependencies, we can take that risk.
So if our AC startup ability is given and if this is true, we know that our abilities have been given,
in which case on initialized startup abilities, which is going to go and get that ability information
from the AC, it can safely do that.
So we really don't even care about binding to that delegate.
We're just going to call the callback ourselves directly.
Now there's an else case, however, and the else case means that startup ability is given is not true.
In other words, the ability system component has not given the abilities yet.
It has not made the broadcast yet.
So in that case, we do want to bind our callback to abilities given delegate.
So we'll have an if else here now.
So this way we're taking care of both situations.
Now on initialized startup abilities is going to need that ability system component and rather than
getting our ability system component variable and casting again, we could just pass in the pointer
of a U or a ability system component straight into on initialized startup abilities.
I'd rather do that than do a second redundant cast.
So we're going to pass in a pointer to this type.
We're going to call this aura ability system component.
I'm going to check up at the top to see if it's been forward declared or included.
It has not.
So I'm going to forward declare class you or ability system component.
Now this function requires a pointer to this.
So we'll go back to the CPP file and take this function.
And pass it in now because it requires this pointer.
We can't bind it to abilities given delegate anymore unless abilities given delegate is designed to
broadcast a parameter that can be passed into the callback.
So for that reason, we'll go to our ability system component and change this from declare multicast
delegate to multicast delegate one param and then we can pass that pointer.
It's going to be a you or a ability system component and that's a pointer.
So now that this delegate is a different type, it can now have functions bound to it that require this
pointer.
And with that we can come back and see that our error is gone.
But now this function requires an aura ability, system component.
So when we call it here, we can call it passing in or ASC.
And now the function will receive that.
And in addition we have to go back to aura ability system component CP where we're making the broadcast
because this broadcast now needs a pointer to the aura ability system component.
We can simply pass this straight in.
And now our widget controller has our callback on initialized startup ability is called and this function
is now going to be able to get information about all of the abilities in the ability system component.
So I'm going to just make a to do comment here that says get information about all given abilities,
look up their ability info and broadcast it.
Two widgets.
So we have a few things we need to do here, right?
Now, the first thing I'm going to do is just make a sanity check.
I'm going to make an if check taking aura ability system component and check to see if it's startup
abilities has been given.
And I'm going to return early.
If it has not.
So I'll return with a not here if be startup ability is given is not true and then we'll know past that
point that those abilities have been given.
Now I'd like an easy way to do something for all of my activatable abilities, and I don't really want
to have to loop through all of those abilities from within my widget controller.
I don't want to loop through Activatable abilities outside of the ability system component class.
So in the next video we're going to work on a way to easily do something for all of our abilities in
our ability system component and that thing we want to do here is what we have our to do for.
We want to get information and broadcast it to widgets.
So we'll take care of that in the next video.