Welcome back.
So we have a pretty nice electrocute ability.
And we're going to want a debuff associated with it.
So I'd like to make a stun effect.
And the stun effect is going to immobilize the enemy.
If you want you can have a periodic damage amount applied while in the stun debuff status, but I'd
really like no damage applied.
I would just like to show that the enemy is in that stun debuff, and that they're immobilized, and
play a different animation to show that they're stunned and a different particle system, and so on.
So we're going to implement that.
But before we do, I'm going to show one little issue that we have now that we have two different spells.
The Firebolt and electrocute.
Now it's kind of hard to reproduce.
But if I cast the Firebolt and while I'm casting the Firebolt, if I cast electrocute before the Firebolt
is finished, we'll actually interrupt Firebolt.
Now it's hard to see and repro at normal speed like this.
There.
I interrupted it even before the fireball was spawned.
Now this is actually a pretty easy fix.
I'm going to show you first though the problem a little bit.
Slow down.
So I'm going to set the cast Firebolt montage to a rate scale of 0.1.
And then I'll go ahead and cast a Firebolt.
And while casting cast the electrocute spell and you'll see that we interrupt it.
So that's not good, but it's a pretty easy thing to fix.
We could go into our.
Blueprints.
Ability.
System.
Aura.
Abilities and fire.
Firebolt.
Gar.
Firebolt.
Spell.
And remember, we have all these gameplay tag containers.
And these allow us to block other abilities.
For example.
So we have a block abilities with tag.
And if we set this to say just abilities, then we would literally block all abilities that have the
abilities tags on them.
So in that case, if I cast, I can spam the right mouse button all day long and even hold it down and
nothing happens until that Firebolt spell is done and we lose that ability tag.
Now blocking all abilities with the abilities tag is a little too broad, so if you wanted to make sure
it's only those offensive spells like fire and lightning spells, you could add the fire.
You could add the lightning tag, and you can block those spells and not block other abilities.
So in this case, we could cast I can spam the right mouse button.
Nothing happens until I lose that abilities fire tag and then I can finally cast.
So that's a way to do it.
And if you wanted to, you could create a specific tag for blocking abilities like a player blocked
offensive spells or something like that, and then all your offensive spells could have that tag, and
then they could all block that tag if you wanted to do that.
But that's just something to keep in mind.
We can always block other abilities that grant specific tags, and this is because we have those tags
in our ability tags container.
Okay.
So I'm going to set the rate scale back to one for Firebolt.
And with that with a quick save we can start thinking about the stun debuff.
Now we already have a stun debuff tag and the ability to apply a debuff, as our attribute set is dynamically
creating and applying a gameplay effect.
If we go into Aura attribute set, we have a debuff function we're calling, and based on the debuff
chance, it's applying a gameplay effect with these debuff parameters, and it's a duration based effect.
So we can apply this using the stun gameplay tag.
And if we do that, then our enemies will be stunned.
So the first step to applying that type of debuff is to go into our lightning to electrocute ability
and make sure that we actually apply that gameplay effect, which means we need to apply damage with
a set by color, magnitude for the stun chance.
And this is actually pretty easy to do now that we've set up a really robust framework because our damage
gameplay abilities already have a debuff chance, I could set that debuff chance to 100 and we can.
For now, just leave a debuff damage and a debuff frequency and duration.
And if we leave these there and we actually assign those set by color magnitudes, we should see our
enemies get Debuffed with the debuff damage type that corresponds to damage lightning.
The question is when do we do it?
Now I didn't want to apply a debuff while we're holding the right mouse button or whatever input button
down, as we're just applying damage here with one set by color magnitude and that is the damage lightning.
So that's the behavior I want while we're holding our input down.
But as soon as we release it, I'd like to apply one last damage amount.
Now, that last damage amount could be the damage amount that we have on our ability.
It could also be zero.
And we could just set our set by color magnitudes for the debuff.
That's an option too, but we need to figure out when we're going to apply that effect.
And that's going to be when we end our ability.
We can go into clear timer and end ability.
And in this function we're removing the gameplay effects.
If we go into prepare to end ability, we go in and we remove the gameplay cue on the actor for our
primary target, and we remove the gameplay cue on actor for the additional targets as well.
What we can do here is we can also apply one final damage gameplay effect, and if we do that we need
damage effect params.
So what we can do is we can call make damage effect params from class defaults.
And the target actor here is actually the target we're trying to apply damage to.
Right.
And if first target implements interface is false, well we're applying this gameplay cue to the avatar
and we don't want to damage the self.
So in this case we don't actually need to apply damage to the avatar actor, do we?
Now if the first target does implement the interface, we can then apply damage to that mouse hit actor
and then to the additional target.
So I'd like to do that.
I'd like to make the damage effect params from class defaults.
And then we can use apply damage effect which is on our Aura Ability system library which takes those
damage effect parameters.
And the target actor here can be the mouse hit actor.
This is really just used to calculate things like death impulse.
And as soon as we've done this, then applying the damage effect to our primary target, we should see
a debuff because our debuff chance is 100%.
Now, after doing that, we remove the shock loop queue from all the additional targets.
We can do the same thing here.
We can duplicate those two nodes, only this time our damage effect params we make will be using this
target, our array element.
And we're going to apply that damage effect to that.
Now if we don't want to do any damage, we could set that damage amount.
We could break this struct.
And we can make a new one.
We can make damage effect params and instead of using our function, we can use just a make damage effect
params.
And if we expand it and we expand this one, we could drag and connect all of these that we want in
our damage effect params.
But we could then override the base damage here.
Now if you don't want to cause any damage then you would stick a zero in there.
I'm actually okay with not doing that.
And then we'll just cause our little one damage at the end for this one last farewell damage amount,
right?
And I'm going to go ahead and try to avoid crossing wires as much as I can.
So for this, just keeping things as organized as I can here.
We'll do this.
And if you do have to cross wires in any circumstance, you could keep those wires as short as possible.
But usually there's a way to avoid crossing wires.
So we could do this.
So if you try hard enough, you should usually be able to avoid crossing those wires.
Okay.
So we're calling applied damage effect now on the primary and additional targets.
And because we're using our damage effect params created with make damage effect params from class defaults.
Those damage effect params will now have a debuff chance, and we're setting it to 100 for now.
So as soon as we release on our electrocute ability, we should see.
What if we don't kill?
The enemy.
We now also have a knockback chance as well.
But yes, now you can see every one second they're getting five damage because they actually have the
debuff associated with electricity, which is stun.
Now, I didn't want a knockback for this ability and I see that my knockback chance is zero.
So I'd like to see where we're using that knockback chance.
I'm going to go into my aura attribute set and search for knockback, and we see that we're getting
our knockback force.
And if it's nearly zero then we're not applying that knockback.
It looks like we're not actually taking that knockback chance into account.
So we could take that chance into account.
Another thing we could do is just have it set to a zero force here.
We're not actually checking the knockback chance.
And in fact, that knockback chance isn't even in the effect context, so we'd have to check it before
we even create those damage effect params.
But in the case of the electrocute ability, we could just set our knockback force magnitude to zero
and then we won't be seeing a knockback force.
So they'll just be sitting there.
So now we're applying a stun debuff.
As soon as our electrocute ability is finished, as soon as we release it.
And that's great.
And of course this will be applied to the additional targets as well.
But as I mentioned, I don't want my stun debuff to cause any damage.
So for my debuff damage I'm going to set that to zero.
And that way if we're applying that debuff, well we don't see any numbers because we're not causing
any damage.
But I want to do something else.
I want to respond to that debuff tag for lightning, which is stun and immobilize the enemy so they
can't move.
I also want to make them show with their animation that they're stunned.
So this will involve a couple of steps.
For one, we need to go into our character folder and into our app enemy, the parent class for all
of our enemy animation blueprints, and we need them to know if they're stunned.
So how do they know if they're stunned?
Well, we could have a stun variable here.
And if we're going to set a stun variable here, then we need a stun variable on the aura enemy class.
And we need to set that.
So a couple of things to do here.
One is to have a stun variable on the at least the enemy class.
We could have one on aura too.
So we could put it on the base character class.
And we also need to respond to a gameplay tag and specifically the stun tag, and set that boolean based
on that.
So let's go ahead and go into our C plus plus project.
And we'll go ahead and start by adding a stun variable on the base character class.
So in the public folder we'll go to character or a character base and we'll add a new Boolean variable.
Now this can be public and we can call this a boolean with the name B is stunned.
It'll be false by default.
Now if we set this on the server we're going to want this to be set on clients as well.
So this should be a replicated variable.
We'll make it uproperty replicated.
And we should also be able to at least read it in blueprint.
So we'll make this blueprint read only.
And now we have a stunned variable.
Now in addition to this we need to respond to receiving the stunned tag.
And I'd like to make a callback function for this.
I'll make it a void function called stun tag changed.
It'll receive a const f gameplay tag called callback tag and an int 32 called New Count.
And we've seen how to respond to these gameplay tags before the callback has to be of this signature.
Strangely, the gameplay tag can't be a const reference, just a const gameplay tag.
We'll go ahead and make this definition here, and we need to make sure to assign this to a delegate
when we've initialized our ability.
Actor info.
Now here we have an ability actor info and it's empty.
And we could put it here so that all of our characters will respond to this tag.
But I'd rather do it in the child classes, because I don't want the success of this to be contingent
on the order that we call super.
Let me show you what I mean.
If I go into to the private folder, into character and or a character, and here in an ability actor
info, if I call super first before my ability system component is a valid pointer, well then if we
assign our callback here to a delegate on the ability system component, that ability system component
won't be valid yet.
And so it would be required for us to call super at the very end.
And that doesn't make our system very robust, because if someone comes in and sees super called at
the end and they say, oh, we should call that at the beginning and then it breaks it, well, that's
a brittle system.
And I don't want our system to be brittle.
I want it to be strong.
So we're going to bind to this delegate only when we know our ability system component has become valid.
So what we'll do here is as soon as our ability system component is valid on aura, we'll take it and
we'll call register gameplay tag event.
Now we have to specify the tag that's going to be for a gameplay tags get.
Dot and it's going to be a debuff.
Tag.
The debuff tag will be stun and for gameplay tag event type, it's going to be new or removed.
And now we have this delegate.
We can go ahead and add a callback to it with add new object using this and the name of the callback.
And the callback is going to be the address of a ora character.
Stun tag changed.
So now we know our aura character will register this, but we want the enemy character to register as
well.
So we'll go to the enemy.
And as soon as the enemy has a valid ability system component, we'll go ahead and.
Do the same exact thing.
Now, instead of a character here, it's going to be.
Our enemy.
And yes, you could just use the base class here, but if we were to override that function, maybe
make it virtual and do something different for a character versus our enemy, well, then we could specify
here which one.
But either way, now we're registering a gameplay tag event and we're registering stun tag changed,
which we have here in our character base.
Stun tag changed.
And what can we do in stun tag changed?
We can do whatever we like.
But what I'd like to do is, first of all, I'd like to immobilize the character.
Now we're immobilizing the character in the hit react, aren't we?
I think we're just doing it in Aura enemy.
Let's find out.
If we look at Hit React, we have hit react tag changed where we check the callback tag, check its
count, and we know we're hit reacting.
If that count is greater than zero and we set character movement, max walk speed, and we have a base
walk speed here that we added to the aura enemy.
And then of course we set the blackboard component, blackboard key hit reacting so we can do something
like this in aura enemy and an aura character base.
We could also set auras max walk speed.
But for aura we don't need to set a blackboard key do we.
So for that reason it might be wise for us to make stun tag change virtual, and then we can have some
basic functionality in the parent version and additional functionality in an override for each child.
So from Aura Enemy, I'm going to copy these two lines and go into Aura Character Base and paste them.
But instead of be hit reacting, we're going to set be is stunned based on this tag.
And then we can check be is stunned and we can set max walk speed.
But base walk speed is just a variable on the enemy class.
But we can move that into aura character base.
So if we search for base walk speed.
We can move that.
And we can move it here into our character base.
We can make it protected and really stun tag change could be protected as well.
So we'll move that here to.
Now.
Base walk speed could be 600 for the default value, but we'll want that a lower value for enemies.
So we can go into Ora enemy and set it in the constructor.
We can say base walk speed equals.
And we had 250 here for enemies.
And that can be set per enemy.
But or a character can get 600.
And the ora character base function here will set our max walk speed to zero.
If we're stunned and set it back to its base walk speed when we're not stunned.
Now get character.
Movement is an incomplete type.
We can include that.
We have it in Ora enemy.
It's right here.
Now we can cut that and we can move it into Ora Character base instead.
So we'll put that here.
So now we're immobilizing the enemy and we're setting B is stunned, which is a replicated variable.
We can use that in our animation blueprint.
So let's go and do that.
Okay.
So our enemy is still using character movement component.
So we'll need to put that back.
So we're keeping it here in our character base.
But we'll also keep it in the enemy class as well.
And of course, before we test this out, let's go into our character base, because now that we're
replicating a variable, B is stunned, our or a character base needs to have git lifetime replicated
props, doesn't it?
So we're going to put that just below the constructor.
We'll have get lifetime replicated props.
This takes a T array.
Of f lifetime property.
By reference and it's out.
Lifetime props.
All of this has to be exactly typed like this, by the way.
You cannot change out lifetime props.
You cannot have an uppercase T there.
This all has to be exact.
We'll go ahead and generate the definition.
And in this function we need to use do rep lifetime specifying a or a character base.
And the variable b is stunned.
And if we want to use do rep lifetime, we have to include net slash unreal network dot h.
So with that, let's go back into the editor.
I'll go ahead and open what we had open.
And here in App Enemy, we're going to want to access that stunned variable from the enemy class.
So right here as we cast to Ora enemy, if we dragged off of this and type stun we can get as stunned.
But we need this every frame.
So we're going to have to take ora enemy and promote this to a variable.
We'll call this Ora enemy.
And hook that up.
And now that we have this, we can get this here.
We'll use a sequence node now.
And we'll get our enemy down here.
I'm going to make it a validated get.
Now we're going to type in stun.
Get is stunned and promote this to a variable called stunned.
And we'll set this every frame, and we need to change our pose based on if we're stunned.
So in our anim graph.
I'm going to open that and go into main states.
We have idle walk, run.
Now I'm going to have a stun state.
So I'm going to add a state and call this stun or stunned.
And we'll transition into this state if our stunned variable is true, and we'll transition back if
the stun variable is false.
Pretty simple.
So we'll have a not ball and hook that in.
And for stunned, we need a sequence player.
And we'll hook that in there.
We'll compile and save.
And now it's just up to our child animation blueprints based on this to set that sequence player so
we can start with our goblin.
We'll go to Goblin.
Here's our goblin slingshot.
And we can go to Asset Override.
Expand these.
And here's our stunned.
We can set the sequence here.
And I'm going to search for stun.
And we have a slingshot stun loop.
Where in the Goblin slingshot.
So we'll set that there.
And compile and save and close.
And we'll do this for the next one.
So we're going to go to character Goblin Spear app Goblin Spear.
And we'll set that asset override for stunned.
I'm going to search for stun.
And we have a stun loop for Goblin Spear.
And by the way, if you want to take a look at these, here's the stun loop for Goblin Spear.
And here's the stun loop for the slingshot goblin so they look nice and stunned.
Okay, so that is for Goblin Spear.
We can go back and let's go ahead and do the shaman.
So here's a shaman.
We'll go ahead and set that for the shaman.
I'm going to search for stun and we have shaman stun.
We can go to that and see what that looks like.
And here's the shaman.
Stunned.
Nice and stunned.
After that, we can go to.
Let's do the ghoul next.
AVP ghoul, and we'll set the asset override here for stunned searching for stun.
And here's a stun animation.
And here's what it looks like.
Nice and stunned.
Kind of sleeping.
Almost.
Okay, that's the goal.
And the last one we can do is our demon.
So we'll go into the demon animation blueprint and override the asset for stunt.
Here I'm going to search for stun, and there's a demon stun.
And here's the demon stunned animation.
Okay, so now that we have those in our animation blueprints, all we need to do really is test it out.
But let's do this for aura while we're at it.
We'll go to Content Blueprints, Character Aura, app aura, and we'll just take care of the stun loop
for aura as well.
So we'll just have a stun state here.
And aura does have a stun animation.
If we go to that, here's what Aura Stun looks like.
Nice and sleepy and stunned.
Now for stun.
I'm just going to make a boolean here on our animation blueprint.
We're going to get our character.
We're going to add a pin here.
We're going to get this app character and type stun.
We'll go ahead and get is stunned.
And we'll promote this to a variable as well.
We'll call it stunned.
And we'll hook that in.
And then we can just check this, just like we're checking our in shock loop.
So we'll have stun here.
And I'll just have one going back to idle.
And this will check stunned.
And we'll say not boolean.
And if we're not stunned we'll go back to idle.
And then we can have a state alias going to stun.
We'll call it to stun and go into stunned.
And this will be if stun becomes true.
And what states do we want to go to stunned.
Well, we'll go to stunned.
If we're idle.
We'll go to stunned if we're in air and the cast shock loop, or if we're running.
So we can basically get stunned if we're in any of those states.
So that'll handle that.
Okay, so we can stun one of our enemies.
Okay.
So it is going into that stun.
But it played the hit react and it finished the hit react animation first before going into the stun.
So that was a bit of a wait that we had to do.
And then going into the stunt animation was a bit abrupt.
So I'd like to go back to the AVP enemy anim graph two main states and into our stunned.
And the duration for this transition could be a little bit longer.
So it sort of blends a little bit better.
And in addition to that, I'd like my hit react montage to be a little faster.
So I'm going to go to assets enemies.
Goblin animations spear and we'll go to M hit react Goblin spear.
And I think I'd actually like this animation cut a little bit.
So I'm going to take my hit react spear.
I'm going to duplicate it first.
This is just a tweak, but I'm going to duplicate and call this hit react spear underscore cut.
And I'm going to cut this short.
To about here.
So I'm going to remove from frame 28 to 42.
Now, I do want this animation to be a root motion animation.
I'm going to enable root motion.
And then I'll go to the montage and I'll add this cut animation to it.
And delete the old one from it.
So it's a little faster now.
Let's try this.
Okay, that's better.
And I'm just going to see if my slingshot hit react needs to change too.
So I'm going to go to Goblin.
Animation slingshot and go to the hit react.
I think this one's actually fine.
So I'll leave those as is.
And now, whenever they're stunned, we see that stun.
And after five seconds it should go back to not stunned.
So something we need to do is make sure from the behavior tree standpoint, that our enemies can't do
anything if they're stunned.
We don't want them to move.
We don't want them to attack.
So we can go into our behavior tree.
And just like we're checking, am I not hit reacting before doing anything else?
We can also check if we're stunned.
And for that reason, I'd like to go to the blackboard and add a new key called stunned.
We'll go ahead and save.
And right here next to me not hit reacting.
We're going to right click on the selector add decorator.
Choose blackboard.
And for this blackboard based condition we're going to do the same thing that we did here.
And am I not hit reacting.
We'll do a notify the observer on value changed.
So we'll change that.
We'll use observer abort self.
So we'll change that.
We'll use key query is not set.
So key query is not set.
And we'll choose the blackboard key.
Stunned.
And we'll change the node name to.
Am I not stunned?
Question mark.
And then we can just set the stunt tag.
And I'm going to set that from C plus plus.
In stun.
Tag.
Changed in aura.
Enemy.
And I'd like to set this blackboard key just like we did in Ora enemy and hit react.
Tag changed when we did it for hit reacting.
We'll do the same thing for the stun tag, which means an ora enemy.
We should override stun tag changed, so we'll say Virtualvoid stun tag change will override this function.
We'll generate the definition.
And we'll do what we did and hit react tag change.
Namely, we'll go ahead and change a blackboard key with set value as bool.
Now we still want to call super because that's going to take care of the max walk speed.
But we're also going to want to set value as bool for the stun blackboard key.
I think it's called stunned.
We'll have to double check.
And what are we going to set it to.
Well we need to check new count.
In fact we already set that in stun tag changed and or a character base we set.
B is stunned here.
So we could just use B as stunned.
Right here.
We'll set the stun tag to be is stunned.
So we can compile and check this out.
So I'm going to open my assets.
I actually don't need an aura.
I'll keep electrocute open.
I'll close app enemy and we'll open our behavior tree where we set.
Am I not stunned?
I'm going to open this behavior tree.
I'm going to keep it open and just show the value of that blackboard key for stunned.
Right here.
And I'll stun the enemy.
And we'll see if that stunned blackboard key gets set to true.
So I can just barely see it right here.
It's set to false.
Now I see that it's set to true, and it should stay true for five seconds and go back to false.
Good.
Now let's see if we're preventing movement.
While that is true.
And it looks like.
We are and as soon as it goes back.
It can then attack again.
Until then, it can't do anything.
It's stunned.
That's what I wanted to see.
Now, we do have to keep in mind that we duplicated this behavior tree, and we have a different one
for elementalist enemies.
So they're going to need their own decorator.
Here.
They have a stunned because they're using the same blackboard.
And the blackboard is a separate asset.
So as soon as we added stun to our blackboard well our elementalist behavior tree is using that.
But we do need to add a decorator choosing blackboard and set this.
We're going to set it to on value changed.
Observer aboard self key query is not set.
Blackboard key stunned and the node name will be.
Am I not stunned.
And now our shaman should behave as well.
So with that, we have a working stun mechanic.
So that debuff works.
We can have it cause damage if we like.
And the last thing I could try is to make sure this works on aura.
So what we can do is we can take this enemy.
We know that the enemy is actually.
Let's check its character class.
I think it's set to Ranger because it's launching rocks, which it shouldn't.
That's because it is set to Ranger.
We can set it to warrior, actually, and then we can change the melee gameplay ability.
We can change its damage type so we can go to ability system, enemy abilities, melee attack.
And if we change its damage type to lightning and we change its debuff chance to 100, then we should
see that aura will be stunned.
And since there's a debuff damage of five, she'll take damage while she's stunned as well.
Let's just see if that works.
And she's stunned.
And while we can.
Rotate.
We actually can't move.
So we don't want aura to be able to rotate.
But other than that, we can't move.
Let's see if we can cast spells.
We can cast spells, so we want to block any spells while we're stunned as well.
So two things to fix really quick.
We'll go to ability system, aura abilities fire, Firebolt Firebolt and we're going to add a tag to
activation block tags.
We're going to add the stun debuff tag.
So debuff.
Stun and we shouldn't be able to launch a Firebolt while stunned.
We'll do the same thing for abilities lightning electrocute.
So activation block tags.
We're going to add debuff stun here.
And now if we're stunned, we shouldn't be able to cast those spells.
Okay.
And we're not able to cast those spells.
And we are when we're done.
And I noticed that the stun animation was not looping.
So a couple little things that pop up here and there when implementing new things, right?
Let's go to Ora's Animation Blueprint and go to the stun state.
Take that stun sequence.
Player and set it to loop animation.
That'll fix that.
And how are we going to prevent aura from being able to.
Move around.
Well, we do have the ability to block input because we created some tags to block input.
Remember.
And or a player controller we're checking those in player or a player controller.
We're checking before even doing anything in ability input tag pressed and the other associated functions.
We're checking player block input pressed.
We could easily give that tag when debuffed if the debuff is the stun type, and it will be removed
when the stun debuff is removed.
That would be something we do in the aura attribute set.
If we look for our debuff function right here, we can add it to inheritable own tags container and
we can check the damage type or the debuff type either one.
So if we say if and we can get that debuff type that's this right here.
So we could paste that whole thing in here.
We could also just do a const gameplay tag called debuff tag and set it equal to this.
And then use debuff tag here.
And then we can check the tag here.
If debuff tag matches tag exact, and we can check to see if it matches F or a gameplay tags get debuffs
done.
If it does, then we'll also add two inheritable owned tags.
Container.
What tag we're going to add for a gameplay tags get.
Player block and we can block any number of these.
Input pressed input released.
Input held.
We could add all three.
We could even block the cursor trace while we're stunned.
Why don't we add all four of these block tags?
And since we're going to use this for a gameplay tags get multiple times, I'm going to go ahead and
also make a const or a gameplay tags.
Reference called gameplay tags.
Looks like I already did up here.
So that's actually unnecessary.
And I'll just use gameplay tags instead of get right there and right here.
And while we're adding our block cursor trace we'll add the other three.
We'll add block.
Input held.
We'll add block.
Input pressed and finally we'll add.
Block input released.
Now with that, if we're stunned, we can even add input.
Let's test that.
The stunt mechanic is so frustrating, isn't it?
You can't do anything while you're stunned.
Let's try that out.
There we go.
And I'm clicking.
I'm moving.
I'm trying things.
I can't do anything.
And as soon as it's done, I can move, I can click, I can do all the stuff I want to do.
So now we have a working stun mechanic and it should work in multiplayer.
Let's try it with two players.
I'll save all.
Press play.
And here on the client.
We'll try getting stunned.
Oh, it looks like we are able to do things and we're getting rubber banding because on the server it's
prevented.
On the client it's not.
So we do want to make sure that we get those tags.
So we've already seen that these dynamic gameplay effects we create in C plus Plus are not replicated.
And that means their tags are not replicated.
But one thing we are doing in our character base is we're setting B is stunned, which is a replicated
variable.
Now that's really useful because we can have a rep notify.
So if we have a rep notify then on the client when B is stunned replicates, we could either add or
remove those block tags.
So I'm going to add a rep notify and just make it virtual.
So in or a character base B is stunned is now going to say replicated using equals.
And we'll make an on rep underscore stun or stunned.
And we can create that rep notify void on rep underscore stunned.
And it has to be a new function to be a rep notify.
And we can implement on rep stunned which will only be called on clients when B is stunned is replicated.
And with that we can add or remove those tags to the ability system component.
And then our player state will know not to allow input.
Now I only want to do this on a character.
So I'm going to make on rep stunned virtual.
And I'm going to override it and or a character.
So we'll say virtual void on rep.
Stunned.
Override and we'll set it here.
And here in on rep.
Stunned.
I'm not going to call super.
I'm going to get our ability system component.
Cast to you.
Ora ability.
System component.
Our ability system component store that in a local variable called Ora asc.
Wrap that in an if statement.
And then take a risk.
And add gameplay tag.
We can even just call add loose gameplay tag and pass in a gameplay tag container, which we can create
here.
And we'll call this blocked tags.
And blocked tags.
Can have a tag added which will be for gameplay tags get dot player, block, cursor trace and all the
other associated tags.
So I'll make a const f or a gameplay tags called gameplay tags.
This could be a const ref.
And we'll use that here.
And we'll also take blocked tags and we'll add the other blocked tags.
Input held.
Input pressed.
And input released.
Now we only want to add these if be stunned is true.
So if be stunned then we're going to add these gameplay tags.
So we're going to say add block tags like so.
But in the case we're going to remove these gameplay tags.
And we're going to use remove loose gameplay tags passing in blocked tags.
Now notice there were replicated versions of these.
So ora ask add replicated loose gameplay tag.
You could use that if you want to use replication, but doing it this way we're only replicating one
little boolean and not those tag containers, so it's a little bit more optimized this way.
So with that change, we can try to restart instead of closing the editor or hitting stop and then running
in debug again, I can just click this rerun here and writer, and that will go ahead and close the
editor down and run in debug mode again.
It'll recompile and all that.
So just a little shortcut I use sometimes as well.
All right.
So let's try this with two players.
We'll try it on the client.
I'll go ahead and get hit.
And I'm not able to move.
Let's see if I can move again when it's removed.
And yes, I can.
So we can add those gameplay tags manually.
And then as long as those tags are on our character, we can't do anything.
We can try this on the server as well just to make sure everything works as expected.
Input is blocked.
I'm spamming these keys and as soon as I'm not stunned anymore, things work.
Now the last thing I want to try is on the client.
Let's try stunning this enemy.
And when I release the mouse button, I don't stop my electric ability.
And it's only if I release really fast.
So we'll fix that issue in the next video and we'll also polish up stun.
So great job and I'll see you soon.