Welcome back.
Now, we had a list of steps and we've accomplished step one where we've created our secondary attribute
gameplay tags and we handle them in C plus plus.
Now as we're creating them natively with our singleton or a gameplay tags, now we need an attribute
info data asset, basically an asset that we can use to store info in the form of a struct which we're
going to create called f or attribute info struct.
So we're really going to knock out two and three in this video.
So let's do it.
So from within the editor, I'm going to make another C plus plus class and this time it's going to
be a data asset.
So I'm going to go to C plus plus classes or a public.
And this is related to the ability system.
I'm going to open ability system here and make a new C plus plus class.
And this is going to be a data asset.
So I'm going to go to all classes and search for data asset.
And choose data asset and click next.
Now this can be in ability system and I'm going to add a subfolder called data.
So ability system slash data and this will be for attribute info.
So I'm going to call it attribute info.
Let's go ahead and create the class and close the editor.
So we should get our attribute info data asset inside of the data folder.
I'm going to go ahead and collapse both public and private and reopen ability system data and open attribute
info.
And here we go.
We have you attribute info, which is a new data asset.
Now, if you've never used a data asset before, I think you're really going to like them because they
give us the opportunity to store asset information in a nice blueprint settable class.
So I'm going to go ahead and right click on attribute info, close other tabs and use control K or alt
O in writer to open up the companion file so I have the H and CP files.
And in attribute info, we're going to want to store some structs and we haven't created this struct
yet, but we want to create a struct to store all the information associated with a given attribute.
So once an attribute changes, then we can broadcast this struct object up to the widget blueprints
who will receive it and update themselves with that information.
So I'd like to make a struct and I'd like it to be for attribute info.
So I'm going to declare a new struct called f ora attribute info and we'd like to be able to use this
in blueprint.
It needs to be blueprint type.
So we're going to give it a use struct macro with blueprint type and that means it needs a generated
body of course.
Now attribute info is going to need a gameplay tag to identify which attribute this info is for.
So we're going to use gameplay tags to identify attributes.
This will be an F gameplay tag then and we're going to call it attribute tag.
And if we're using F gameplay tag well we now need to include the header file for gameplay tag container
dot h.
So there we have it.
And we also need a U property and we want to set this from the blueprint of our data asset.
So we're going to make this edit, at least edit defaults only and blueprint read only.
And we can initialize this with an empty gameplay tag like so.
So that's how we'll identify each of these struct objects is by gameplay tag.
Now the information that we need to pass up to the widget side is going to require some text for the
attribute name so we can set that attribute name in the attribute menu.
And whenever we have text that's user facing in a widget, we use F text.
So if you're ever wondering when to use F text, that's for the widgets.
That's when we set the text for a widget to show to the user.
So we're going to have an F text called attribute name.
This will be an empty F text and these will all get the same uproperty macro.
So we'll go ahead and copy that over and we'll also have another F text for the description.
So I'm going to go ahead and copy this and this will be attribute description.
And aside from that, we just need an attribute value.
So we're going to have a float for attribute value.
This will be broadcast up to the blueprint.
We'll initialize it to zero and give it a U property.
But I don't want to be able to edit this from within our data asset, so we're not going to expose it
to the data asset.
We're just going to expose to blueprint to read from.
But it's public in the struct.
So here in C plus plus we can set its value before we broadcast it up to the blueprint side, but we're
not going to expose it to the data asset just because that's not where the attribute value is set.
So if we did set it from the data asset, we'd just be overwriting it later when we check that attributes
true value.
So now we have our struct and if we need to later, we can always add more fields to the struct.
But for now this is great and we want our data asset to contain something filled with structs.
To me an array comes to mind.
So let's make a public section here and we'll create a T array of type F or attribute info.
And this is going to be called attribute information.
This will contain our attribute info structs.
Now we need to fill this in and we're going to fill it in in the blueprint.
So we're going to give it a U property and make this edit defaults only.
Blueprint read only.
So this is our list of actor info.
So we'll set that from the blueprint.
But I'd like a function here that will take a gameplay tag and return the correct info.
The correct attribute info from this array based on the gameplay tag.
So I want a function that returns an attribute info called find attribute info for tag and this will
take a const f gameplay tag reference called attribute tag and we'll pass in a boolean called B log
not found.
And I'll make it false by default.
And if we pass true into this, then if we try to find an attribute info struct from this array that
does not exist there, then we'll use a log to log an error and this can be a const function.
So let's make this lookup function.
Now we have an array and this function is taking in a game play tag for the attribute.
So how are we going to find the ability info struct in our array that has this attribute tag?
Well, we can use a for loop.
We can say for let's do a const for attribute info reference called info.
So for each of these in attribute information, then we can check the tag.
We can say if info dot attribute tag double equals our attribute tag passed in so we can use double
equals.
There's also the matches tag exact function.
So if you don't want to use double equals, you could use info dot attribute tag dot matches tag exact
passing in attribute tag.
This will check for an exact match.
So if you wanted to you could do this instead.
Either way is fine.
If it does match, then we return this info that we're on.
So we just simply return info and if we loop through the entire array and we never return, then we
make it down here, which means we never found an attribute info in the array and we can log an error
if b log not found is true.
So if we pass in true, that means we want to see an error when we don't get a successful attribute
info.
When we don't find one from the array so we can use log.
Now, we haven't defined our own custom log category, but for now we can use log temp error and for
the message we can say can't find info capital info for attribute tag and we can even say what the tag
is percent there on attribute info and we can even have the name of this class here.
We'll put a period there and we need two strings.
First will be our attribute tag.
We can use to string.
And next will be the name of this class and we can use with an asterisk get name safe passing in this.
And this is going to print an error message if we can't find anything in the array, but we still need
to return something.
So in that case, we'll return an empty or attribute info.
So now we have a function we can call and it's a public function that we can simply pass in a tag to
and receive the attribute info.
This was one of those challenges that we had mapped out that we needed to be able to find Once we have
a gameplay tag that is associated with an attribute, we can get this attribute info data asset and
get the aura attribute info structure out of this data asset.
So now that we have the data asset, we can fill it in with information.
So I can go ahead and compile and launch the editor and we can make a blueprint based on this data asset.
So back in the editor, let's make our data asset by going to Blueprints and ability system.
And we already have a data folder where we've placed data tables.
Now we're going to have our data assets be placed here as well.
So we right click, we go to miscellaneous and look for data asset.
Here is one and we search for our class attribute info and here it is.
Let's grab that, select it.
We'll prefix it with D A for data asset and we'll call this D a attribute info and we'll open this up
and here's our array called attribute information.
And if we click plus we now have an element with index zero and we have three fields we can set attribute
tag, attribute name that's an F text and attribute description.
Another F text.
Now there's an attribute value in this struct, but we did not make it exposed so that we can set it
in details panels.
Remember we made it only exposed to the event graph with blueprint read only.
The others are exposed to the details panel and we can set them so we can go ahead and add elements
to this array for each of our attributes.
And I'll start with the primaries.
So first I'm going to expand the dropdown, go to attributes primary and choose intelligence, and we
can go ahead and fill in the attribute name intelligence.
We can fill in the attribute description which I have already in my C plus plus project, if you'll
recall.
All I have to open is my aura gameplay tags.
Actually not the header file but the CPP file.
And here I've already added comments for each of these tags and the intelligence one has increases magical
damage.
I'm not sure why I chose intelligence first, but it's there and I can go ahead and paste that comment
there.
So all we have to do is put all the attributes here, and that's a repetitive process and I'm going
to go ahead and time lapse it and fill this out.
Okay, so I've added all the primary and all the secondary attributes here.
Now there's kind of a lot of them.
So if you really wanted to, you could have multiple arrays here, but I'm just going to have one single
array where I can set this information and all it has is the tag, that attribute name and the attribute
description which we'd like to use once we start broadcasting delegates that our widgets can bind to
and receive this information.
So this is looking great and we've already conquered the first three steps here in our next steps for
the attribute menu.
In fact, number four was to fill in the data assets.
So we've already done that.
Next, we need to create our widget controller for the attribute menu so we can start driving data to
the attribute menu to show the values of our attributes.
So that is our next step and we'll do that next.
Excellent.
I'll see you soon.