Welcome back.
So now that we have four new attributes in our attribute set, we're going to learn how to easily create
some accessor functions to retrieve and set these, even though usually we don't set these from code
directly, we use gameplay effects, but we haven't learned about gameplay effects just yet, so we
do need to know that we can in fact set these from code with regular old setters.
Now for getters and setters, there exist some pretty handy macros that make it easy to mutate and access
these attributes.
And I'm just going to show you one for health.
Just under health, I'm going to use the gas specific macro gameplay attribute.
Underscore property getter.
Now, this requires two inputs.
The class name, which is you, or a attribute set, of course, and the property name, which is health.
So what exactly happens when we call this?
Well, let's go ahead and just jump to its definition.
I'm going to right click here in writer.
It's go to declaration or usages.
You can just peek the definition in Visual Studio, but here it is.
Gameplay attribute Property getter.
It's a macro.
It's defined right here.
In fact, here in attribute set this big comment explains it.
It says This defines a set of helper functions for accessing and initializing attributes to avoid having
to manually write these functions.
It would create the following functions for attribute health.
It uses health as the example.
It says that these macros result in creating Get Health, which is a const getter, set health which
does what you'd think a set health function would do, and in it health which initializes the health,
it says to use this in your game you can define something like this and then add game specific functions
as necessary.
And it says here, define this macro called attribute accessors.
If you define this, then when you call attribute accessors, it will call these four macros which create
the getter for the attribute, the getter for the value, the setter for the attribute and the emitter
for the attribute.
And why do we have get health attribute and get health?
Well, that's because the attribute itself is its own type of gameplay attribute.
That's the attribute that gameplay attribute data contains within and get health would return just the
float.
You could see it returns float here.
So one returns the actual attribute object, the other returns the numerical value of health.
See the difference?
So we can take a look at these macros.
It's not imperative that we understand the macros.
This is macro creation magic.
This macro here is generating a new function called get property attribute.
So it's using macro magic to generate a getter function for us.
And I'd just like to point out one quick difference between set and init.
You see, set is going to set the numeric attribute base.
That's the base value for the attribute, whereas init sets the base value but also sets the current
value base and current.
It's basically saying start off with the same base and current value, which is what we pass in.
So we get these nice accessor functions.
If we call these macros as we saw in aura attribute set dot h, I called gameplay attribute property
getter.
This is going to generate the getter for the health attribute, not its numerical value, but an object
of type gameplay attribute which is contained within that attribute data.
So why don't we go ahead and follow what the attribute set header recommends and that is to create this
attribute Accessors macro.
Let's go ahead and copy these lines.
And back in our aura attributes set at the top underneath all the includes.
We'll go ahead and paste them.
We need to delete these stars.
The asterisks that came from that multi-line comment.
And now we have this attribute accessors macro.
And if we call this, then we don't have to use all four of these.
So just under health, I'm going to replace this with attribute accessors here.
Now hovering over it says ability system component is incomplete.
That means we're going to have to include it here in the header file.
There's no way to get around that.
So I'm going to go into aura attribute set dot CPP up at the top where I've included ability system
component.
I'm just going to go ahead and control X to cut that out and we're going to include it right here in
the attribute set.
That way we can use these macros.
So the attribute accessors thing is just another one of those boilerplate things that you're going to
add to your attributes.
And because of this, we can now use those accessor functions.
For example, if I want to initialize health to say a value of 100, I can go into my constructor and
use init health and pass in 100.
And even though I didn't create an init health function, I used my attribute accessors macro which
calls these four macros, one of which creates the emitter and by default that's called init health.
So I can use that to init the health.
But how do we see that change?
How can we verify that it's working?
Well, we can compile and launch the editor.
I'm just going to go ahead and run and debug mode.
And right here in the editor, I can press play.
I can click in the viewport and I'm going to hit the tilde key to bring up the console and I'm going
to type the console command show debug.
That's one word ability system.
That's also one word.
So two words total show debug ability system.
Now this brings up a debug view for the ability system and it has a lot of information.
It shows attributes for Avatar or a character.
See, So we know that our avatar actor has been set correctly to be or a character.
It says authority.
That means we're looking at the authority version.
Now there are no other client machines, so the only version there is is the authority version.
And we see for owner BP or a player state.
So it knows that our avatar actor is the character and our owner actor is the player state.
That's all thanks to calling init ability actor info we see in red showing debug for BP or a character
press page up and page down to cycle between targets.
So if we press page up we can cycle to other targets and we see the name change right here.
It says showing debug for BP Goblin Slingshot C1 But we can cycle back around to our character.
It shows some other information.
It shows the name of the computer, that's my computer's name, and it actually has the location and
rotation right here and you can see it update as I'm moving around.
We have an instigator and an owner for our ability system component.
We see the controller is BP or a player controller and the pawn is BP or a character.
So it knows a lot of this information.
And beneath all that we see owned tags.
We're going to look at that as soon as we get into gameplay tags.
And yet underneath all of that, we see the four attributes.
Here we have health followed by 100.
That's what we initialized it to.
And then Max Health Mana and Max Mana, the other attributes and we didn't initialize those.
So show debug ability system is a great way to sort of debug some of our attribute values and also see
what gameplay tags our character has.
So that's a nice way that we can do some debug.
I'm going to go ahead and close out of the editor and now we've added some boilerplate here that we
can reuse for all of our attributes by using the attribute accessors and that gives us these functions
we can use to initialize and set.
Now I'll give you a bit of a spoiler.
The constructor is too early to call the setter.
That's why we have the emitter here.
But now we have this attribute accessors which we could use with all of our attributes.
So here's what your quest will be for this video.
You're going to use that attribute accessors macro on the other attributes.
So go ahead and add that.
That way you'll have those accessor functions.
And once you have those, you can now give initial values to all of the attributes.
So do that in the constructor and then use show debug ability system by playtesting the game and then
you can verify that those initial values have been set.
So pause the video and conquer this quest now.
Okay, so we can use our attribute accessors macro.
I'm going to be nice and lazy and copy it.
Being very careful to change it from health to max health for this one, I'll copy it again.
And just under Mana we'll add that changing it to Manna.
And finally we have Max Manna.
We'll change it to Max Manna as well.
So now we have attribute accessors.
For the rest we can go back and call init for all of them.
I'm going to call init max health.
Give it a value of 100 we can call init manna.
Doesn't matter what values we choose.
I'll just go ahead and choose 50 for mana and we'll use init max manna.
I'll go ahead and give it 50 as well and we can go ahead and run.
By the way, I'm running in debug mode.
We're not really debugging per se, but don't you worry, we'll be debugging a lot in this course.
We're just still kind of getting started here.
But don't worry, we'll learn a lot about debugging throughout the course.
Right now it's not that important whether you choose to run or debug at this point in time.
All right, so we're going to hit play.
I'm going to bring up the console.
I'm just going to press up on the keyboard.
That'll bring up my last command hitting enter and I see health and Max health are both 100 mana and
Max Mana are both 50.
They have been initialized successfully and it's looking good.
Excellent.
So great job.
We now have those attribute accessors yet another piece of boilerplate.
But now you know what it does.
You don't need to be intimidated by it when you see it.
You know that it simply creates some accessor functions that we can use.
And I'll say it again, we typically don't use those functions to change attributes.
We can, but we like to use gameplay effects instead as those can be predicted.
And we'll learn about those when we get to gameplay effects.
But for now we have accessors.
So great job and I'll see you soon.