Welcome back.
We're now in the attributes set and we're about to debuff stuff, but we don't know how to debuff right
here in C plus plus.
And so far we've only applied gameplay effects when we've had a gameplay effect class and we've created
gameplay effect blueprints.
Well, there is a way to create a gameplay effect in C plus plus right here.
Dynamically.
We can do that and we can apply it, but there are some limitations to doing it this way.
These are not supported for replication, so you just got to do it on the server and anything you change
should be replicated.
So if we're going to change something as in set the incoming damage or something like that, then we're
relying on the server handling that.
And either that attribute is replicated which meta attributes are not, or it changes something else
that is replicated and indirectly the client will catch wind of it.
So how do we create a gameplay effect and apply it right here and set all of its properties?
Well, first we create an effect context.
We say f gameplay effect context, handle effect context.
And how do we create an effect context?
Well, we need an ability system component.
So we're going to take the source ASC and call make effect context.
It's obvious that we need an effect context right.
We're going to be applying a gameplay effect.
So we already knew how to create an effect context in code.
That part was easy.
We can also set its source object.
We can say effect context dot add source object, and we can pass in props dot and we can set it to
source character or source avatar actor doesn't matter.
Okay, so enough of this stuff we already know about.
How are we actually going to create a new effect.
That's the question.
Well we do it this way.
We say you gameplay effect pointer.
We call it effect or something.
To that effect we use new object specifying the type you gameplay effect.
And we initialize it and we have to call git transient package.
Now.
In addition, we can pass in an F name, which will be the name of this gameplay effect.
So we don't have to, but we can.
It's nice when it has a name.
That way we can sort of know what this effect came from.
So I'm going to make an f string called debuff name because this is a debuff.
It's going to be an f string using print f.
And in the text I'm going to say dynamic debuff.
Underscore percent s.
And I'm just going to use the damage type to identify it.
So I'm going to take you or ability system library get damage type.
And we'll use the effect context handle the initial one, the original one that's in props.
That's how we know what the damage type is.
That's how we're getting that information.
But once we get this gameplay tag we need to call to string.
So we're calling to string on the tag we get.
And it's going to make a lot more sense if we make this a const gameplay tag called damage type, and
we just call or a ability system library.
Get damage type here and then just use damage type and here this is a lot less confusing.
So we'll do that.
Now we can pass in debuff name into new object but it requires an F name if we're going to do that.
So we can pass in an f name initialized with debuff name.
So now we've created an effect dynamically okay.
But as we know gameplay effects have settings on them.
They have a duration policy.
Are they instant.
Are they duration?
Are they infinite?
If they're duration, they have a period.
They also have a duration magnitude.
How long do they last.
Right.
And that's all information we can get from our ability system library with the effect context handle.
And I'd like to just collect all that information first so I can make a const float called Debuff Damage
and use your Aura Ability system library.
Get debuff damage passing in props.
Dot effect context handle.
I'm also going to make a const float called debuff duration.
And we'll call get debuff duration.
So changing this now to duration.
We're also going to get the frequency.
Debuff frequency.
So now we have some more information.
Okay, so now for the real stuff.
How do we set the properties on our gameplay effect.
Well first I'm going to take effect.
And we have lots of things on here.
Look at this modifiers period duration policy I'm going to set the duration policy.
These are all drop downs in the Gameplay effect blueprint.
But here they're variables and duration.
Policy is an enum with type EA gameplay effect duration type.
We can have infinite instant and has duration.
Now debuffs are going to have duration.
They'll be duration based.
We even know things like the duration and the period or debuff frequency.
So we can say effect dot period.
And that's going to be our debuff frequency.
And we know effect has duration magnitude.
Now duration magnitude can be set to any of the magnitude types.
Scalable float really whatever we want.
Notice that its gameplay effect modifier magnitude.
That's a parent class.
And we can use child classes such as F scalable float.
If we use a scalable float, we can initialize it with a float, and then it'll just be a float value
for all intents and purposes.
We're going to pass in debuff duration.
So now our effect has a duration with a period of debuff frequency and a duration magnitude of debuff
duration.
Now I'd like this gameplay effect to grant a gameplay tag.
I'd like it to grant the debuff tag.
Why?
Because I'd like my actors to know when they have been debuffed and when they're no longer debuffing.
Some of them may wish to play animations during the debuffs and so on.
Maybe we need some fire particle effects so our little gobbies are running around with their heads on
fire.
That sounds actually quite nice, so I'm going to make sure my effect will grant tags.
Now here's how we do it.
We take the effect and we get inheritable owned tags container and call add tag.
And we pass in the tag.
Now the tag is going to depend on the damage type, right?
So I need gameplay tags.
I'm going to make a const for a gameplay tags at the top here.
That's a ref called Gameplay Tags and it's going to be for a gameplay tags.
Get.
And down here we're going to get gameplay tags and I'm going to get that map.
What's it called?
Damage types to debuffs.
And I'm going to index it with the damage type.
So now our gameplay effect is going to contain this tag and grant that tag.
Okay cool.
Now we have stacking policy right.
So we need to take effect.
And we can take the stacking type variable.
And we can set that.
It's an gameplay effect stacking type.
And we can use aggregate by source and aggregate by target.
I'm just going to aggregate by source.
We also have our effect stack limit count.
And I'd like the stack limit count to be one.
So we've set some properties on our effect.
Now what about modifiers?
Effects have modifiers and we need to set that too.
After all, we need to know what attribute to change.
If this debuff is going to have any hope to cause damage whatsoever.
So first, here's what we can do.
We take effect and we get its modifiers, which is a hover over t array of gameplay modifier info.
Now, however many modifiers it may have zero, right?
But I'm going to show you just in case you find yourself in a situation where it might not be zero,
but you get the index of the modifiers numb.
Now the index of modifiers dot numb is out of range.
Of course, modifiers dot numb is the number of elements, so the index of the last element is this
number minus one.
So this gives us the number of an element.
If we were to add something to it.
Right.
So what we're going to do is add something to modifiers.
We're going to take effect modifiers dot add.
And we're going to add a new gameplay modifier info.
So f gameplay modifier info, we'll just construct a new one and pass it in there.
So now effect modifiers of ID or index is filled with something in it, right?
It has an F gameplay modifier info.
Not sure I like ID, I'm just going to call it index.
And at this point we know that modifiers of index has something.
So what we'll do is we'll get a reference to that f gameplay modifier info reference modifier info equals
effect modifiers indexed at index.
See how that works.
So we got the index before adding something to it.
And this space that we just filled in.
We now have a reference to that gameplay modifier info we just created.
Now we can modify modifier info.
Sorry, that was the worst use of the word modify.
Now we can change modifier info.
Is that better?
I think it's better.
So modifier info contains things like modifier magnitude.
How much is this modifier magnitude going to be?
In other words, how much damage are we going to cause every one second or whatever our debuff frequency
is.
So this can be set and it's going to be set using a scalable float.
As you can see, modifier types can be other flavors.
So you can see how deep this rabbit hole goes right now how much is that magnitude going to be.
Well we know debuff damage so that's how much it's going to be.
We can also take modifier info and we have the modifier op.
Again another thing that's just a dropdown in the gameplay effect here in Cplusplus it's an enum e gameplay
mod op.
And we can make this modifier additive division max multiplicative override.
We're going to set it to additive because we want to add a value to an attribute.
Speaking of attribute, we need to set the attribute modifier.
Info has the attribute and we can specify it.
So what attribute is it that we want to modify.
Well it needs to be incoming damage right.
The meta attribute.
So how do we get that meta attribute.
I mean we could just call the static getter function u or a attribute set get incoming damage attribute.
That would be just fine.
If we wanted to identify it by gameplay tag, we could use the map in our gameplay tag singleton, but
I don't think we added incoming damage attribute to it.
No worries, we know in our debuff that that's what it's going to be.
The incoming damage attribute.
Okay, great.
So now we've got a modifier.
And by the way you can add multiple modifiers just like you can in blueprint.
You just want to plus plus that index right.
And do this whole thing again.
Since I'm only planning on using index once though, I'm going to make that a const index.
Okay.
So we've created a gameplay effect.
How are we going to apply this gameplay effect.
Well what we can do is make a new gameplay effect spec, and we can use it with the new keyword for
gameplay effect spec pointer we can call it.
I'm going to call it mutable spec because it's not const, and I'm going to use new F gameplay effect
spec.
Now for this we have to pass in an effect an effect context, which we have that as well, and a level
we're going to.
Ply all debuffs at level one.
Whoops.
I put an extra asterisk there.
We're going to apply all debuffs at level one.
Now here's another level of complexity.
You can dive into your debuffs can have levels right.
And then you could perhaps use curve tables and what have you.
You could also just use a curve table for the magnitude here.
But that's just an extra level of complexity that we don't need to get into.
Once we have the mutable spec, we check if mutable spec.
If it's valid, then we can make our effect context.
And the main reason I want to make the effect context is just to set the damage type.
So that way we can identify the damage type by the time it gets through.
So I'm going to make a new F or a gameplay effect context.
We'll use the aura version and I'll call it aura context because that's the one that has a damage type.
So to get this in the form of an aura effect context, to set aura specific variables on it, we take
our effect context.
And just to remind you, we created this way up here with make effect context.
This is a new context, not the context that caused this debuff in the first place, but a completely
new one for the debuff.
So we're going to cast it and we're going to use Static Cast.
And we're going to cast to an for a gameplay effect context pointer.
And we're going to cast mutable spec.
Get context.
Dot get.
Alternatively, it would be the same if you just passed in effect context dot get.
So either one of those works.
Now that we have a context, we can set its damage type.
This needs to be a shared pointer though.
So again we got to make a shared pointer.
So gameplay tag here, we'll call it debuff damage type.
Can't call it damage type because we're already using damage type up here.
And we have to make a shared pointer we can use make shareable.
With a new gameplay tag and this can be initialized with damage type.
So notice I use make shareable here and not make shared because I'm constructing a new one.
So another way to do the same thing now set damage type is going to take in this shared pointer.
So after that now we've set the damage type on the effect context for this gameplay effect.
By the way this can be moved inside the if statement.
If you want to be fancy.
Now all of this is just setting up the gameplay effect.
Now we need to actually apply it.
So what we're going to do is take props, dot, target, ASC and call, apply gameplay effect spec to
self.
And we can pass in that spec that we just created mutable spec, which will have to be inside that if
statement if we want to use mutable spec.
So we'll use it here.
And it's a pointer.
So we have to dereference mutable spec.
So as you can see, doing things from C plus plus is a great deal more work, isn't it?
I mean, in the sense of more typing, most of this stuff is dropdowns that you can just select values
for.
But now we have the ability to do this in C plus plus.
And this is useful because if our effect context says we got a debuff, we got a debuff.
So we're going to debuff.
So that's how we're going to get our debuffs.
And we don't have any danger of an infinite loop here.
What I mean is that when the debuff causes damage then of course post gameplay effect execute will be
executed, handle incoming damage will be executed.
And we're not going to get a successful debuff because we're not setting that in our effect context
here.
Very important that we don't set that to true or even give it a debuff chance because, well, that
would result in an infinite loop potentially if your debuffs could cause debuffs.
Although if you could find a way to make that work without being infinite, maybe cap it off or something
that could be actually kind of cool.
So the last thing to do is compile and launch the editor.
After all that work, now that we have the ability to debuff and we can check to see if we're debuffing.
So I'm going to press play and launch a fireball.
Okay, so I'm not seeing any extra damage happening.
And you know what?
I only have a 20% chance to debuff, so give it a shot.
Need to give it a more of a shot here.
There we go.
We got a debuff.
Look at that.
Oh, and it killed the sucka.
I'm becoming a little too op here.
All right, all right.
Look at that.
Okay.
So interesting.
Our enemies are still taking debuff damage, even past death.
And that's because they're lingering around, and we're not making any checks to prevent debuffs when
dead.
So obviously, we can't be debuffing when dead.
And as soon as an enemy becomes dead, if they are still debuffing, well, they can't hit react, right?
We should not hit react when dead.
So a couple things we shouldn't cause damage.
If dead, we shouldn't hit react.
When dead.
We shouldn't debuff when dead.
A lot of dead checks that we need to put in place now.
One big overall blanket fix for this whole dead thing is to go up to gameplay effect.
Execute here and check to see if the source character is dead.
I mean, we have an interface, right?
Let's check that interface.
It's in interaction.
We're going to go to public interaction.
We have combat interface and it looks like combat interface.
Has a function called is dead blueprint, native event and everything.
So in the attribute set, something we can do first and foremost before anything else happens is we
can take the props.
We can take source character or source avatar actor, either one, and we can use this in our interface
function call.
We can say source character.
We can call implements with you combat interface.
We can check that.
If it does, we can check if and we can call I.
Combat interface.
Execute is dead.
And what do we want to do?
In that case we want to return.
Now of course execute is dead require source character.
So we'll pass that on in.
And that's it.
And if you wanted this to be a one liner, you can say and and you could check this second condition
second.
And you can put the return on the same line.
And you can put on your cool dude sunglasses.
Look at that.
So really, we can prevent everything that happens if the source character is dead.
All right, let's test that out.
Oh, it still happening, right?
Because source character is not right, is it?
It's got to be the target character.
Target character is the owner of this.
So we'll change that to target character.
Let's try this.
Okay.
Launching fireballs.
And look at that.
That one did.
Get a debuff.
It got a fire debuff and it killed it.
Let's try it on here.
You know what's going to make this a lot easier to test?
I don't know why.
I'm just leaving it up to chance.
I'm going to go to ability, system or abilities.
Fire.
Firebolt.
Go to its class defaults and set its debuff chance to a big fat 100.
There we go.
Guaranteed debuff.
Okay, so that worked.
And I just want to really, really make sure that if it's got still time left on the debuff.
In other words, if the debuff duration was like 10s that it stops when the character dies and I believe
it does.
Boom.
And it worked perfect.
So now we're debuffing, which is really exciting.
I'm going to set that debuff duration back down and I can set the debuff damage down too.
We'll leave it at five.
And with that we now have a burn debuff.
But it's a little boring, right?
All it does is damage, but it'd be nice if we had some fire.
If this little gobby had its head set ablaze, that'd be pretty cool.
So that's what I'd like to do in the videos to come.
But excellent job so far and I'll see you soon.