Welcome back.
Now the aura damage gameplay ability has lots of parameters.
Well, not a lot, but a few.
And some of them have to do with debuffs.
Now.
Now I'd like a nice, easy to use function on our ability system library that can take in a number of
parameters including a damage effect and just apply that damage effect to some target.
So all the things associated with that setting all the set by color magnitudes, I'd like to be handled
by this function.
Now, this function can take a whole bunch of parameters in, but we're going to have more and more
parameters as we create more and more combat tricks and combat features.
And each time we add more parameters, we're going to have to add those parameters to this function
we're going to make.
So to get around that, I'd like to make a new type of struct for damage parameters and the struct can
take all these parameters and store them and we can simply pass that into our function.
That will apply the damage gameplay effect.
So we're going to create a new type and I'm going to put this in the header file where we're defining
our ability system types.
So that's going to be our ability types.
And here in our ability types, this is where we've defined our custom gameplay effect context.
This is also where I'd like to define my custom struct for damage effect parameters.
So we can put this above our effect context or below it.
It doesn't matter.
I'll put it above and this is going to be a struct.
I'm going to call it F damage effect params and I'm going to make this a use struct with blueprint type
so it gets a generated body and f damage effect params can get a default constructor.
I'm just going to define it open and close its body here like that.
And because I plan on passing this struct over to ora ability system library, I'm just going to have
a world context object in here as one of the member variables of this struct.
It's going to be a U object pointer.
This can be actually a T object pointer.
Of type.
You object and I'm going to call it world context object.
And I'll set it equal to a null pointer.
Now, this will be a new property, but I'm not going to expose any of these parameters.
So if we feel like exposing these to blueprint, we can.
I know it's a blueprint type.
That doesn't mean we need to set these necessarily in blueprint.
I plan on setting them from C plus plus.
Now we'll have a world context object.
We're also going to have a damage gameplay effect class.
This will be a subclass of and it'll be a new gameplay effect.
And this will be the damage gameplay effect class.
So we'll call it damage gameplay effect class.
So giving this a new property as well.
We can set this to a null pointer.
We can initialize everything to null that we can.
Now the damage effect params is going to carry the source ability system component with it.
So we'll make a t object pointer of type you ability system component called source ability system component.
And in addition to that we'll have the target ability system component.
Now we won't be able to set this until we know what the target ability system component is, but as
soon as we do know, we can set that.
So I'm going to also have a target ability system component as well.
And I'll just be giving all of these new property macros.
Now damage effect params needs to know how much damage to cause.
So I'm going to have a float.
We'll call it base damage.
It'll be initialized to zero.
We can also carry along the ability level.
So I'm going to have a float ability level and that will be one.
So if we don't set it, it'll just be one.
We're going to have a damage type so we know what kind of damage we're causing.
So we'll have an gameplay tag called Damage type and we'll set that equal to an empty gameplay tag.
And of course we'll have four variables pertaining to debuffs.
We'll have float debuff.
Chance and these will all get zero by default.
We'll have a float debuff.
Damage.
We'll have a float debuff.
Duration and we'll have a float debuff frequency.
So if we have damage that doesn't do any debuff, we could just set that debuff chance to zero.
So we'll go ahead and just stick a property on everything here.
And with that we have the makings of our damage effect params.
So because we have damage effect params and we have an aura damage gameplay ability, these effect params
are going to be set based on variables that exist in our gameplay ability such as the base damage.
Once we retrieve it from a curve table perhaps, and the ability level the damage type and these variables
here.
So I think it would be nice if we created a function on the damage gameplay ability that can make damage
effect params from the class defaults.
So we'll make a function that can do that on or a damage gameplay ability.
This can be a public function and we could even expose it to blueprint so we can make a function that
returns some damage effect params and we can add the include for that or ability types here so that
we can use this type and the function will be make damage effect params from class defaults.
And this can take in an a actor called Target actor passed in by Pointer.
That way, if we already know who the target is, then we can get its ability system component and set
any parameters from that target actor.
And if we don't know who the target actor is, we can pass in a null pointer.
In fact, we can just set this equal to a null pointer by default, and that way it's an optional parameter
so we can generate this definition.
And what this function will do is create a new f damage effect params.
So we're going to say f damage effect params called.
We'll call it params.
And we can start setting things on the params.
Now first we have params dot world context object.
I'll go in order of the order that I added these in or ability type.
So we'll start at the top world context object.
So world context object and it's tempting to just pass in target actor but target actor could be a null
pointer.
So we definitely want a valid world context object here.
So I'm just going to pass in the avatar from this ability so we can get Avatar actor from actor info
and pass that in.
Now the next thing we added was damage gameplay effect class and on the aura damage gameplay ability,
we're going to have a damage gameplay effect class so we can set that right there.
Now the next one in our damage effect params is the source ability system component and we can get that
from an ability, no problem.
So we're going to take that source ability system component and we can get our ability system component
by using get ability system component from actor info.
After that we have the target ability system component and for this we may or may not have a valid target
actor yet.
So what we'll do is just place an if and say if target actor, then we'll call get ability system component
on the you ability system blueprint library.
So we'll say get ability system component passing in target actor and we'll only call it if target actor
is not a null pointer of course get ability system component if we go to it.
We'll see that it calls ability system globals get ability system component from actor.
And if we go to its definition, we see that if actor equals null pointer return null pointer.
So really this check is already done for us.
We don't actually have to make that check.
So if we want this to be a little bit more compact, it's no problem just setting that ability system
component to what's returned from this function as what's returned from this function will just be null
if target actor is null.
So we can say params dot target ability system component equals and we'll call that function.
So I can close ability system blueprint library after target ability system component is based damage.
Now base damage is just a float in our params, which means we need to perform that lookup from the
damage curve table.
Right.
Well we can do that pretty easily.
So we're going to say params dot damage and it's actually base damage and that's going to be gotten
from our damage and from damage.
We can call get value at level simply passing in get ability level.
Now after base damage is ability level so we can pass that in as well.
So we can say params dot level or I mean ability level of course equals get ability level after ability
level comes the damage type.
So we can say params dot damage type equals damage type.
And after the damage type we have debuff chance damage, duration and frequency.
We're going to set those as well.
So params dot debuff.
I'm going to go ahead and copy this.
And we have debuff chance we'll set that equal to debuff chance.
We have debuff damage that'll be debuff damage.
Debuff duration equals debuff duration.
And DBA frequency will be debuff frequency.
And after that we've set all the parameters.
So this function has done its job and it can simply return params.
Now I see this squiggly here.
You probably notice this.
I completely breezed over it, but I didn't actually set damage.
Gameplay effect class equal to damage effect class.
That's something that I needed to do.
Now the function is complete and actually this can be made const.
It isn't changing any state on the ability, so we can just stick the const keyword on there.
No problem.
And now we have make damage effect params from class defaults and this makes it easy so we don't have
to just create an f damage effect params and manually fill everything in.
It's just going to do it itself.
It's an inherent ability.
That's not to say we couldn't create an f damage effect params anyway, but now we have this and now
we can create a function on our ability system blueprint library that takes one of these effect params
and applies a gameplay effect.
So that is our next task.
And now we can create a static function on our ability system library that will take in an F damage
effect params and using those params.
It will apply the damage gameplay effect to the target.
And that's going to be your quest.
So we'd like a function to apply a damage gameplay effect.
So create a function in aura ability system library for doing this.
Make it take in an F damage effect params.
And it's going to assign all the set by color magnitudes for the gameplay effect and apply it to the
target.
This can be a static function and you can expose it to blueprint if you like.
So pause the video and create this function in your function library.
Now.
Okay.
So we need a function that can take in an f damage effect params.
So I'm going to close all tabs except this one, but I'm going to open up my ability system blueprint
library that's going to be in ability system and here it is Aura, ability, system library.
I'm going to make a new function in here.
And I'll go ahead and stick it second to last because this weird little function off on its own doesn't
have a U function macro.
So I'm going to push it off to the side and we're going to make a new static function and this is going
to be apply damage effect and it's going to take in a const reference of F damage effect params and
I'll call this damage effect params like so.
Now I didn't give it a return type, but that's something that you probably found yourself wondering
what is the return type?
What should it be?
Should it be void?
Well, when I apply a damage gameplay effect, what I'm left with is an effect context handle.
Sometimes you may wish to keep that context handle and hold on to it.
Hold it dear to your heart.
So that's what I'm going to return is an gameplay effect context handle.
It's okay if you didn't do that.
That's just what I'm going to do now.
I'm going to go ahead and generate the definition.
But actually before going in and adding things to it, let's make it a new function.
I'm going to go ahead and make it blueprint callable, so I'm going to copy the function macro from
up here and stick it right here.
And subcategory can be damage effect.
Okay, so what is this function going to do?
Well, first I know that I'm going to want to apply a gameplay effect.
We can work backwards if we like.
I can call apply gameplay effect one of the various versions of it.
And if we're going to apply a gameplay effect by this point in time, we need the target ability system
component to be valid.
So if it's not valid by this point, I'm considering that an error and I'll go ahead and let it crash.
So to apply a gameplay effect to the target, I need to get that target.
So I'm going to get it from damage effect params because we have a target ability system component and
the target ability system component has apply gameplay effect to self.
We can apply a gameplay effect spec to self.
You could have used apply gameplay effect spec to target, but then your source ability system component
would have to be valid unless you called apply spec to target from the target to the target.
Either way, we have options.
Now.
If we call this function we need a gameplay effect spec.
Right?
Which means we need to make one of those and I'm going to make one from the source ability system component.
So I'm going to take damage effect params dot source ability system component and make a gameplay effect
spec with make outgoing spec.
Now make outgoing spec is going to need to know the damage gameplay effect class which also exists in
the parameters so we can take damage effect params dot damage gameplay effect class.
It also needs the level that's in our effect params too.
It's the ability level.
And finally the context is the last input.
We're going to make an effect context as well.
So if we take our damage effect params, we take our source ability system component we can call make
effect context.
You see how we put a few key pieces of information into this struct and all of a sudden we already have
the ability to do a lot of things.
It's kind of amazing, right?
Now once we've created the context handle with make effect context, I'm going to store it in a local
variable.
So this is an F game gameplay effect context handle.
I'm going to call it effect context handle.
And we know that the context handle has a source object we can set.
So I'm going to take effect.
Context handle dot source object.
Actually, it's Add source object, and I'm going to add the source Avatar actor.
So I'm going to go ahead and make a const local a actor for storing the Avatar actor.
I'm going to call this source Avatar actor and just get it from the ability system component on the
source.
So that's going to be damage effect, params dot source ability system component dot get avatar actor.
So I have the source avatar actor and I'm going to pass that in to add source object.
So my effect context has the source object.
Now make outgoing spec needs that effect context handle.
So I'm going to pass in effect context handle and this outgoing spec is an gameplay effect.
Spec handle so I can save that in a local gameplay effect spec handle called spec handle.
Okay, so we now have the spec handle and when we apply the gameplay effect, we can.
Pass in the gameplay effect spec.
Now we can do what we've done before by taking a spec handle, accessing data and dereferencing that
pointer we've seen before that we had to call get right.
But I'm going to let you in on a little secret.
You don't actually have to call get Dereferencing.
The wrapper will also give you the dereferenced value inside of it.
Pretty cool, right?
A little bit less syntax there.
So now here's the thing.
We have basically just created a convenience function that takes all these params and just applies the
gameplay effect carried in those params, but we need to assign set by caller magnitudes, don't we?
That's the whole point of making this function for our convenience.
So we're going to assign set by caller magnitudes here and we'll start with the damage that's the most
important now to assign a set by caller magnitude.
We use the ability system blueprint library.
And the function that we need is assign tag set by color magnitude and it needs a spec handle.
While we have the spec handle, we can pass that straight in.
We also need the damage type and that's on damage effect params.
It's called damage type.
We also need the magnitude and that's the damage on damage effect params, it's called base damage.
So now if we call this function passing in some valid effect, params will basically just have a damage
gameplay effect.
Now I'd like to also assign tags set by color magnitudes for all the debuff parameters and there's four
of them.
So I'm going to take this line all the way up to spec handle and copy it and paste it and the next input
I'll go ahead and close the parentheses and add the semicolon and the next input is the gameplay tag
that's going to be for those debuffs.
So I'm going to go ahead and just get aura gameplay tags straight away.
So const for gameplay tags.
That'll be a const reference.
I'm going to call it gameplay tags and use for a gameplay tags get.
So back down to our set by caller magnitude.
I'm going to use the debuff.
And we need debuff chance, damage, duration and frequency.
So I'm going to use debuff chance.
I'm going to get that first and set that equal to the value in our damage effect params for debuff chance.
And we're going to have three more of these set by collar magnitudes.
The next one will be debuff, we can do debuff damage and that's going to be the debuff damage from
our damage effect params.
We'll go ahead and do this again.
The next one can be debuff duration which will be set to, you guessed it, debuff duration.
And the final one is the frequency, right?
And that'll be set to debuff frequency.
So now we've just assigned a whole bunch of set by color magnitudes.
And apply damage effect can apply that damage gameplay effect.
Now this returns a context handle, so I'd like to return that effect context handle.
This is just for convenience.
I mean, we don't have to return this, but I just happen to choose to return this and we'll see later
if we need to use it.
Now our spec handle could be const here.
Writer thinks I made a typo in effect context handle.
I didn't.
So.
So now we have this function that can apply damage effects by receiving some params.
Now, this is great because the effects spec is now going to carry these set by caller magnitudes along
with it.
And in the next video, we'll see how we can use this function.
So give compiling a try.
Let's see if we can catch any errors.
Looks like I have one.
You gameplay effect undeclared identifier.
So I didn't forward declare you gameplay effect.
I'm going to go ahead and do that.
So I'm going to compile again.
And that's going to do it.
All right.
Great job on the challenge.
And I'll see you in the next video.