Welcome back.
Now we're changing our attributes and we've seen that our health can go into the negatives and we can
also fill up our health bar and continue increasing health.
Same goes for Mana.
In other words, we're not really enforcing any clamping.
Now, there are different ways to enforce clamping, and in this video we're going to learn one of them.
We're going to go into our attributes set.
So I'm going to open my public folder, go to ability system and open Aura attribute set.
And here in the public section, I'm going to override one of the functions that we've inherited from
the attribute set class.
So it'll be virtual and it's a void function.
And the function I'm interested in is called pre attribute change.
Now writer is offering to fill out the rest of it for me, so I'm going to go ahead and let it do that.
And as you can see, it takes in a const reference of a gameplay attribute, the gameplay attribute
struct and a float called new value and notice the float is passed in by reference and it's not a const
reference that should hint to you that we can change new value and something somewhere is going to change.
Now let's go ahead and generate this definition and let it call the super version of pre attribute change.
And I'd like to just see what happens in this function when we change an attribute.
Now, here's the cool thing about having an gameplay attribute here.
In the input parameter list, we can check that attribute and see if it's equal to any of our attributes.
We can use comparison operators to compare gameplay attributes.
They override the double equals operator.
So for example, we could say if attribute double equals and we can get any of our attributes thanks
to the attribute accessors, we can say get health attribute, for example, and we can compare and
see if the attribute is our health attribute.
Now, when any of our attributes change, whether it's from a gameplay effect or from being set directly,
this function will kick off in response and it's called pre attribute change, which means it's kicked
off before the change actually occurs.
Now this gives us the opportunity to do something preemptively, but we really shouldn't be firing off
events or kicking off gameplay logic here.
Epic recommends that we only use this function to do clamping.
Basically, that's really all it's good for now, just for demonstration and educational purposes.
We're going to place a log here, so we're going to say you log, we're going to make it a log temp
with warning
and we're going to say health percent F and we'll pass in new value.
And I'd like to do this for all of the four attributes we have.
So I'm copying it and changing this to get max health attribute and changing the comment to say Max
health and I'll copy both of these.
And instead of health we're going to change it to Mana.
I'm just going to highlight this section and here in writer I can hit control H, I can search for health
and I can replace with mana and I see that I have get health attributes, health get max health attribute
max health.
I'm going to replace all.
And now these are the mana versions.
Okay, cool.
And in Visual Studio it's control shift f I believe to find and replace.
Just make sure you know what you're doing there and I'm going to go ahead and close that mini menu.
And now we're seeing when any of our attributes change.
Now let's go ahead and run this in debug mode and change some attributes and see what we get printed
to the output log.
Okay, I'm back in the editor and I'm ready to test out some changes.
Now let's make sure we understand what each of our aura effect actors are doing right.
We have health potion and mana potion.
And we know that those use these GE potion heal and mana and these are instant gameplay effects which
means we know that they permanently change the base value of those attributes.
Now we also have these crystals and these are different.
They have duration and they also are periodic.
Now, because they are periodic, they act like instant effects, so they also permanently change the
base value.
We also have area the GE Fire area is periodic as well.
So all of these affect the base value permanently because they're either periodic or instant.
Now let's open the output log.
I'm going to dock it in the layout and bring it down here.
So that I can see it and I'll go ahead and press play and let's see what happens if we pick up a mana
potion.
Here we see Warning Mana 40.
Let's pick up the health potion and it says warning health 75.
I'm going to show debug just so we can compare and make sure that these are correct.
And sure enough they are.
Let's go into the fire volume and we see that our health is going down, going down by looks like one
per second as expected.
And let's go ahead and pick up a mana crystal.
And we see it going up.
And let's pick up a health crystal and we see it going up.
So as we can see, we have pre attribute change being called in response to these attribute changes.
Now here's the thing.
It's called pre attribute change, which means we have the opportunity to perform some sort of clamping
before the change occurs.
So if we change this new value.
Well what happens?
Right?
Because we see that it's passed in by reference.
So is that going to actually change the attribute value?
Well, let's find out.
Let's say we don't want our health to ever go above our max health, for instance.
What we can do is we can set new value equal to the result of a clamp.
So f math clamp, we're going to clamp new value.
And we'll clamp it between zero and let's say, our max health.
So get max health.
And now, as our health value changes, it'll never go below zero or above max health.
Let's do the same thing for mana.
So down here, if attribute is the mana attribute, we're going to say new value equals new value but
clamped between zero and instead of max health we'll say max mana like so.
Now let's go ahead and run in debug mode.
All right.
And we're going to go ahead and press play.
I'm going to show debug ability system and let's start picking things up.
Let's go to the nanocrystals first.
We have ten mana max Mana is 50.
I'm going to pick up a health crystal.
We go up to 20 picking another one up we go up to 30.
Another one we go to 40 and another one we go up to 50.
And I think we have a man of potion over here if I pick that up.
Look at that.
We actually stay at 50.
Now that mana potion does work.
Right, Let's pick up the mana potion first.
There.
See?
We see that it does work.
We have 40 mana, but if we pick up a crystal, we go up to 50.
But if we pick up a second crystal, look at that.
Nothing happens.
Why?
Because before the attribute changes, we have the opportunity to do something in pre attribute change.
And because we're clamping it and we can't go above max mana, which is 50, we're preventing that mana
from going above the max.
We're clamping now.
The same goes for the health and it goes both ways, right?
We clamped so that the health cannot go below zero.
But this takes one away every second, which means I'm going to have to wait for Looks like 40 more
seconds to test that out.
That's going to take too long.
So I'm just going to test the other way.
I'm going to pick up a health potion.
I'm going to pick up the health crystal.
Is it enough to push me over?
No, but that's fine.
I believe that it's working.
We saw that it works for mana, so that's pre attribute change.
And again, it's not really meant to kick off any logic, it's really just meant to clamp and that's
what we're going to use it for.
So before the attribute changes, we can perform clamps.
I don't really feel like I need all of these logs and I'm not really going to clamp our max mana and
health.
I mean, I guess we could clamp it so it doesn't go below zero.
But for now I think I'm fine without clamping those.
I'm going to go ahead and remove all of these logs.
I don't feel like we need them, but I'm going to leave our clamping for health and mana.
I think those are useful, so we'll go ahead and leave those.
So pre attribute change is where we can modify the changes to the current value of an attribute.
And this function is called before the change actually happens.
Now that is a significant detail and we'll see why in a second.
Pre attribute change is triggered by changes to attributes, whether that's through attribute accessors
like the setters that we've created thanks to our boilerplate macros or due to gameplay effects.
Literally anything that changes the attribute can trigger this function.
Now, this does not permanently change the modifier for a given attribute.
It just changes the value returned from querying the modifier of the attribute.
In other words, we can clamp changes before the change happens, but there are later operations that
happen after pre attribute change and these will recalculate the current value from all modifiers involved.
So if the value of health changes, for example for any reason, then there are later operations that
will recalculate that health change, which means that our clamping will have no effect and we'll have
to clamp again later on.
So pre attribute change is not the most attractive choice to implement final clamping changes, but
it is there.
Now you may be curious as to what might be the best function to implement something for when an attribute
changes and be sure that that change will be final.
One of those functions is called post gameplay effect execute.
This actually happens after a gameplay effect has changed an attribute and we're going to learn about
this function in the next video.
I'll see you soon.