Welcome back.
So now we've created a spell menu widget controller, and we need to construct it.
Now let's go ahead and close all tabs, and we're going to open up our HUD class.
I'm going to go into UI, HUD, Aura.
HUD.
Why?
Because we have our widget controllers for our project on this class.
They live on the HUD.
They're not technically singletons, but we only have one of each one and we access them through the
HUD.
Well, indirectly, actually, we access them usually with our aura ability system library functions
and those access them through the HUD.
We're going to now have a spell menu widget controller and it too is going to live on the HUD, just
like the attribute menu and overlay widget controllers.
So we're going to add variables to the HUD so that we can create our spell menu.
Widget Controller.
I'm going to copy our object pointer.
You attribute menu widget controller called attribute menu, Widget Controller and the class for that
attribute menu, widget controller and paste them.
We're going to change these though to spell menu widget controller, which I'd now like to forward declare.
So I'm going to go ahead and forward declare it here.
You spell menu widget controller and that's going to be the type for my new object pointer, which I
will call spell menu Widget Controller.
I'm also going to have a subclass of of this type called spell menu Widget Controller class.
Now that I have these, I'm going to need to set spell menu widget controller class on the HUD blueprint.
Now we construct the other widget controllers with these get functions and these require widget controller
params.
We're going to make a get function for the spell menu widget controller as well.
So we're going to copy one of them and change its return type to use spell menu widget controller.
It's going to be called get spell menu widget controller and it's going to take widget controller params.
We can go ahead and generate the definition.
And what this will do is just the same thing as what the other get functions do.
It checks to see if the spell menu widget controller is null.
So we'll say if spell menu widget controller equals a null pointer.
If it's null, it's going to create one.
If it's not null, well, either way it'll return spell menu widget controller.
So we need to create that widget so we can say spell menu.
Widget controller equals new object.
We're going to create a you spell menu widget controller.
The header file will be auto included for me and we pass in this for the outer object and the class
will be spell menu widget controller class.
Once we've created it, we set its widget controller params calling spell menu widget controller set
widget controller params passing in wc params.
As the spell menu widget controller inherits set widget controller params and then we call bind callbacks
to dependencies.
Spell menu, widget controller bind callbacks to dependencies and then it returns.
So the first time this is called and creates it, we have all this stuff happening The second time it
gets called.
After that we just return the pointer.
We only create the spell menu widget controller once.
Now this is great, but we want something on the aura ability system library to make this easier.
So I'm going to go to Aura ability system library and go up to my get functions for the widget controllers.
I'm going to copy one of them and simply paste it and this will be for the spell menu widget controller.
So it can still be blueprint pure in the category of the others, but it's going to return a you spell
menu widget controller, which we will add a forward declaration for and it's going to be called get
spell menu widget controller so we can change its name.
And it takes in a world context object just like the others.
We can generate the definition for it and it's going to be just like the others.
Well, let's go ahead and copy the contents of get attribute menu, widget controller and analyze it.
First we get the player controller using get player controller.
We get the HUD as well.
We get the aura player state from the player controller.
We get the ability system component and attribute set.
We construct F widget controller params and then we take our aura HUD and we call well not get attribute
menu widget controller, but rather get spell menu widget controller.
That's all it's going to do.
Now you may be thinking to yourself these three functions look awfully similar to each other.
Is there a way to not repeat ourselves for a lot of this?
Well, sure.
We could make a function that could do most of this work for us.
We can create a function that makes the widget controller params.
That's what most of this stuff is for, right?
In other words, we could create a new function here.
It could be a static function, it could even be blueprint pure and this can be get widget controller
params or actually make widget controller params more specifically and this can return an F widget controller
params.
We're going to have to add the include here if we're going to use it, which means we can remove the
include from in the CPP file that's or a widget controller.
So we can remove that from the CPP file.
And this function is going to be called make widget controller params and it can take a world context
object.
Now what this function will do is what these other functions are repeating in each of them.
We'll just get the player controller, get the HUD cast aura, HUD get the player state, get the AC,
the AI's make widget controller params and return them.
In fact, we can just return the f widget controller params that we make here.
We don't have to make a local variable for them.
Now at the end we have to return an empty f widget controller params.
So f widget controller params like that.
And now we have a function that we can use in each of these so we don't have to repeat ourselves.
But here's the thing, though.
What if some of these casts fail?
Well, we should be able to know because if we get an empty widget controller params when we create
our widget controller, that's not good.
That's not going to be a very pleasant experience.
So rather than returning an EF widget controller params, here's something we can do.
We can pass the widget controller params in as a reference that's not const so ef widget controller
params reference called out wc params.
And instead of returning a widget controller params, we can return a boolean that will be representative
of the success.
Then we don't have to include or a widget controller here.
We can forward declare a widget controller params.
We can say struct f widget controller params here.
And then we can just include that header back here.
And we can change this function signature to return a bool and it also takes in a widget controller
params out wc params.
And then out wc params can simply have its members set.
We can say out wc params dot attribute set equals as.
Out wc params dot ability system component equals asc.
Out wc params dot player state equals ps and out wc params dot player controller equals p c.
And by the end of this out wc params will be filled in and if we fill it in we can return.
True.
And if we never get this far by the end of it, we'll return False.
So now we have a function that tells us whether or not this was a success.
And then here in, say, git overlay widget controller, we can check the Boolean.
I'm just going to make some room here and create an EF widget controller params called WC params.
I'm going to call make widget controller params right here passing in world context.
Whoops.
Not duplicate world.
Passing in world context object and wc params.
And this returns a boolean so we can say const bool be successful params.
And if that's a success.
So if be successful params then.
Well return or git overlay widget controller passing in those wc params.
But wait a minute.
We don't have a HUD here.
Right?
So how do we get that aura?
HUD?
Do we just go and go through all this stuff again?
Well, no, that would be silly, wouldn't it?
What we can do instead is we can pass in a pointer to make widget controller params that we can fill
in.
In other words, we can pass in a out parameter, a pointer that we can pass in by reference, much
like wc params.
That's right.
I said pass a pointer in by reference.
Now that sounds kind of strange, but we can do it.
We can have a third input parameter of type A or a HUD pointer, but it's a pointer passed in by reference.
So we have asterisk and the reference operator here and we'll call this out or HUD looks kind of crazy,
but all we need to do is treat it like any other reference.
It just happens to be a pointer that we have a reference to.
So here in make widget controller params, we're passing in a HUD, a reference to a pointer and now
out aura HUD can be assigned the result of this cast.
So what we can do is say out aura HUD equals and we can perform this cast here.
Just like that.
And now what we're checking in this if statement is the out or HUD.
So as soon as we've made it to this, we'll be setting that pointer.
And this is passed in by reference.
So whatever pointer we pass in, it will be altered outside the function as well.
So now we just need to pass a pointer in to make widget controller params.
We're doing the same thing that we're doing with WC params making a variable and passing it in and expecting
the function to fill that variable in.
It just happens to be a pointer.
We can say a or a HUD pointer called or a HUD.
Now we set it equal to null pointer so that it's initialized to null, but we pass it in to make widget
controller params and that way after this function has been called then on a HUD should be filled in
and then we can call get overlay widget controller.
Now we don't even really need a local variable successful params.
We can just call this function since it returns a bool.
Right here in the if statement.
So this looks a little bit less amateur.
And after this or a HUD, our local pointer has been set and we can call get overlay widget controller
pretty nice.
And then if we don't make it this far, if everything fails, we return a null pointer, no big deal
and get overlay.
Widget controller no longer needs to repeat itself by getting all this stuff.
Instead, it can just do this stuff here.
So we've saved a little bit of work and we can just test this out before we go and change the other
two functions by just making sure that we have an overlay widget controller and that everything works
from our health globe to our mana globe to whatever abilities we have equipped.
We can just test out everything.
So we can press play.
Even in multiplayer, we're testing.
Looks like Mana is updating.
Let's see if we can take some damage.
Yes we can.
Even our cooldowns are being shown.
So we see that everything's working.
So we can do this.
We can call make widget controller params now and we can do that in our other get functions for attribute
menu controller and spell menu Widget controller.
So I'm going to just copy these lines and come down here into get attribute menu, widget controller
and paste them.
The only difference with this is we're going to return our HUD get attribute menu widget controller.
That's the only difference.
And we'll go ahead and delete the rest and we'll copy these.
I'm going to put that input parameter on the same line.
And then here we'll do the same thing for spell menu.
Widget controller.
The difference is we'll call get spell menu.
Widget controller.
Okay, so now that we have a jet spell menu, widget controller, we can call that to get the spell
menu widget controller for our project.
And I'd like to do that for our spell menu as soon as it's constructed, which means we do need to make
sure that our aura HUD has a spell menu widget controller.
And that means we need to create a blueprint, as I'd like to have a blueprint for the spell menu.
Widget Controller.
Now, if we go back and look at our spell menu, widget controller header file and compare it to the
overlay widget controller.
We'll see that overlay widget controller is blueprint type, blueprint able.
Let's go ahead and add that to spell menu widget controllers class so we can make a blueprint from it.
And let's go ahead and launch the editor.
Okay, so we're back now.
A couple things.
Let's go first into blueprints and UI and widget controller and let's make a new widget controller blueprint
class.
So Blueprint class, we're going to search for spell menu, Widget controller.
Choose that, select it and we'll call this BP spell menu.
Widget Controller.
Now we have a spell menu widget controller and it does have an ability info data asset.
We should set that.
That way it has access to the ability info just like our other attribute menu widget controller has
ability info.
It just happens that now it's inheriting ability info from aura widget controller and it doesn't actually
use it.
But we could set it just in case we need to use it in the future.
Overlay widget controller has already had its set, so when we moved it into the parent class, blueprint
was smart enough to still have that set.
So we have a blueprint for spell menu widget controller.
We need to go to Aura HUD and set spell menu Widget Controller class to BP.
Spell Menu.
Widget Controller.
Now it can be constructed, and that means we can have our spell menu set its own widget controller.
Let's go into BP spell menu, go into the graph and we can have it set in as early as event construct.
Let's just go ahead and add a sequence node.
So we can organize things.
So first we're binding to the on clicked for the close button.
I'm going to make a comment and say Close button clicked and we'll move that out of the way.
And after that, we're going to set our own widget controller.
We're going to call the blueprint function library function, get spell menu, widget controller, and
it requires a world context object.
Now, this is the third time I've called one of these that needs a world context object, and I've been
using self every single time for that world context object.
And that is grinding my gears because look at some of these other nodes.
Look at this function.
It has an input parameter and look it says self.
It's defaulting to self.
We don't have to pass self into that one.
Why do we have to keep passing self into our functions if it's always going to be self?
I'd like it to default to self.
So before we continue, I'm just going to really quickly close out and go back to Aura ability system
library and make these functions default to the self for that input.
Now how do we do that?
Well, we can take a look at where we've done this before and we have done this before.
We can go into our ability system folder, into ability tasks to target data under mouse.
We did it here, didn't we?
We added something to the meta specifiers.
We have default to self and we set owning ability to default to self so we can take any of our input
parameters and set them to default to self this way.
So if we go into our aura ability system library for our world context objects, we can make those default
to self.
So what we do is we go to the U function macro, we add meta equals parentheses, and then we add our
meta specifier and target data under mouse shows us it's just default to self equals and then we specify
the input parameter.
So I'm going to put default to self equals and we'll use world context object.
And I'm going to add that to not only make widget controller params, which I don't plan on calling
from Blueprint, we're calling it internally here, but hey, it's there if we need it and then get
overlay widget controller can get it get attribute menu.
Widget controller can get it get spell menu, widget controller can get it.
And with that I'm going to relaunch the editor and use my nice blueprint pure function and not be bothered
to have to get a self node.
Okay, so let's get back into that blueprint where in spell menu in the graph.
And look at this.
Now it's defaulted to self so I don't have to right click type self.
Get a reference to self and hook it in.
No, we don't have to do any of that.
It's already set to self and now that we have this, I'm going to call set widget controller and set
my spell Menu's own widget controller.
It's a big boy.
It's doing it itself.
And now we can make sure that this works by telling the spell menu.
Widget Controller Hey, tell us what you got.
Let me see what your widget controller's name is.
Who is your widget controller?
Let's get object name.
We'll plug it in there.
We'll print it out.
And we should see this when we open the spell menu.
I'm going to move this client out of the way.
Open the spell menu there.
There's my widget controller's name spell menu, Widget controller C zero.
And it works.
Let's see if it works on the client too.
It does.
We're successfully setting our spell menus, widget controller.
And not only that, because of all the trouble we went through last video, our spell menu widget controller
inherits some stuff from the Aura widget controller.
It inherits the ability to broadcast some info about its abilities.
It has the.
Capability, I'll say, because ability is not their best word to use.
It has the capability to broadcast ability info and that's going to be very handy for setting our equipped
abilities row here so we can see the same info that we see down here.
So we're going to do that next.
Really exciting.
I'll see you in the next video where we continue this.
See you soon.