Welcome back.
Now we've got some really nice impact effects and they work just fine on the server, but on clients
we don't see or hear anything and we know that that's because these gameplay abilities executed on the
server are not replicated to any of the players because none of them actually own that ability system
component that belongs to that enemy.
So we're going to use a gameplay queue.
Now there are different kinds of gameplay queues, so we're going to look at the simplest kind.
So let's create a gameplay queue.
We're going to go into Blueprints, Ability System Enemy and right click and make a new folder called
Queues.
And let's go into that folder now we're going to right click and make a new blueprint class and type
gameplay queue.
Now notice there are different types of gameplay queues.
They all start with gameplay queue notify, and there's one called Actor and there's another called
Static.
And there are of course subclasses of these.
We're going to choose gameplay queue notify static, which is what it sounds like.
We won't actually be instantiating an object of the gameplay queue.
Notify static class.
It's a static version of the gameplay queue.
Let's go ahead and select that and call this g c underscore and we'll call this melee impact.
Now, if we double click to open this melee impact, we'll see that we have an event graph.
So this gameplay queue is a class where we can specify what happens when the gameplay queue is executed.
Now to specify that we override a function, we're going to choose on execute.
Now notice on execute has a parent on execute.
We can just hook those parameters straight in there and that returns a boolean.
And this is basically like calling super in C plus plus.
Now we can choose what happens here and on execute has parameters.
This is a gameplay queue parameter structure which we can drag off and break to see a bunch of different
bits of data that we have access to when we execute a gameplay queue.
So if we execute a gameplay queue with parameters, we have access to those.
Some of them are filled in automatically when this gameplay queue is executed from a gameplay effect
which we can do.
But if we execute this gameplay queue manually, we have to fill these in.
And as you can see there are lots of parameters here, including an effect context we can pass through
a magnitude we can even pass in a source object, which is good for passing arbitrary data.
So we have information here.
Now what I'd like to do in melee impact is play the sound and spawn the particles.
So I'm going to right click and just use place out at location.
And for now I'm going to hardcode the sound.
It's going to be SFX.
And I'm not sure what sound I use, so I'm going to go into my ability system, enemy abilities and
melee attack.
And I see that I'm getting that sound from the tagged montage that's in our enemy.
So I'm going to go to my spear enemy edit Goblin spear, Search for attack.
And here it is, it's SFX Swipe.
I'm going to browse to it and then come back to GC Melee Impact and use that SFX swipe Now for the location.
My gameplay parameters has a location, so as long as I set that when I trigger this cue will have a
valid location.
So I'm going to go ahead and hook that in and then I'm going to spawn a Niagara system.
So I'm going to use spawn system at location.
And for this I'm just going to for now hardcode my blood.
That blood impact and use the same location.
Hook that up like so and we'll go ahead and return after that.
So we have this melee impact and I'd like to execute this gameplay queue.
Now in order to execute a gameplay queue, we identify them by tag and if we select class defaults,
we'll see that under gameplay queue.
We have a gameplay queue tag.
Now.
The tag that we use has to start with gameplay queue.
So if we go to edit and project settings here in project settings in gameplay tags, notice that we
have gameplay queue, we can click plus to add a sub tag and we're going to call this melee impact.
And I totally spelled it wrong.
So I'm going to rename this to melee impact with a C there.
And now we have melee impact.
Now I can go into my gameplay queue, melee impact and select gameplay queue.
Notice it only lets you select a tag that has gameplay queue in it and it has to be the topmost parent
in the hierarchy.
But now that I have this gameplay queue tag here in melee impact, we can execute the gameplay queue
by tag as the game has a gameplay queue manager which is responsible for performing the lookup by tag.
So back in game melee attack, what we can do now instead of spawning a system at location, we can
go ahead and just disconnect that for now and go back to the completed for the for each loop.
And if we have hit a target before we end the ability, instead of playing a sound at location, I'm
going to move that out of the way and I'm going to right click and type execute gameplay queue with
params on owner.
So hooking this up, we now have the ability to execute a gameplay queue.
I'm going to go ahead and hook that up to end ability and we choose the gameplay queue tag that's going
to be melee impact.
And if we compile we get an error.
If we don't pass in gameplay queue parameters.
So we're going to drag off and make gameplay queue parameters and then we can compile.
Now Unreal is telling me I have to restart.
So what I'm going to do is save all and quickly restart.
And I'll go ahead and open up all my asset editors.
So back in melee attack, we're no longer spawning system at location.
We're no longer playing sound at location.
We're executing a gameplay cue.
This is a static gameplay cue where specifying the melee impact tag and we're passing in gameplay cue
parameters.
This is of course an empty struct.
We're not setting anything on it.
But let's see what happens if we execute this as we're playing a sound which we've hard coded and spawning
a system which we've hard coded as well.
So let's go ahead and.
Press play.
So we're getting the sound.
We're not getting the impact particles.
Actually, we're not passing in a location, are we?
So if we go back to melee attack, remember, we have that location, we're using that in the gameplay
queue, but we never actually set it.
We can set that.
So here's the location in our gameplay queue parameters that we made.
We're going to use the combat socket location for that, so I'm going to go ahead and copy that, get
Node and we're going to pass in the location now.
So let's see what happens now that we're passing that into the queue parameters, let's press play.
Here.
I'm on the client and I can see and hear just fine.
Thanks to our gameplay cue.
Let's check out the server.
And we see it on the server as well.
So thanks to gameplay cues, we can now have visual and sound effects and those can be replicated.
So even though we have an AI controlled character executing an ability which isn't going to replicate
down to any human players, we can execute a gameplay cue and pass in optional parameters and use those
now for the blood impact.
We can actually get that from the thing that we're hitting, right?
And we can know the thing that we're hitting.
Thanks to our gameplay cue parameters here.
We could say set it as the source object.
If we wanted to do that, we could also get the effect context and we know that we can add any type
of data we like in our effect context as well.
So let's see what happens if we pass something along for the source object here.
So in a melee attack, let's expand the make gameplay cue parameters and let's just see if we can pass
something in for the source object.
We know that we have a combat target.
Let's just see what happens if we pass that in for our source object.
So I'm going to right click and just type get combat target.
And I'm going to take the true wire and just bring it way over here.
And then bring it all the way back.
We'll organize this in a second.
We're going to use the Avatar actor.
So get Avatar actor from actor info.
And once we have this combat target, we're going to pass that in as the source object.
This is an object.
So it could be an actor, It can take an actor in.
So once we have that combat target as the source object here in our gameplay queue, we can get that
source object.
And from the source object we can get those impact particles, the blood particles.
So I'm going to right click here and type get blood effect and we're going to pass in that source object
as the target.
We're going to hook these up and this return value will be used for spawning the system.
So now we're using the blood effect on the combat target.
Let's see what happens if we do that.
We get the blood.
So same thing.
But now this is kind of cool because we can change the blood effect just to prove that we can do that.
I'm going to go into assets effects combat, and we have this blood impact.
I'm going to duplicate it and call this blood impact, underscore green and open up this blood effect.
Select initialize particle and change this to a green color.
Nice.
Kind of dark green, I think.
Click okay and save that.
And I'm going to open up my aura blueprint.
So blueprints, character, aura, BP Aura, character and search for blood and set this to blood impact
Green.
Now if I press play.
And I get hit.
Now we see green and this is even on the client as well.
And notice he missed that time and we didn't see anything.
So that's exactly the behavior we want.
So that's great.
Now we're passing in a source object through that gameplay queue parameter struct, which is pretty
cool.
Okay.
I'm going to go back to Aura and set this back to the regular blood impact because I want Aura to have
red blood.
And I'll close that.
So now our gay melee attack is executing the gameplay cue and we don't need play sound at location anymore.
So I'm going to go ahead and remove those nodes and we don't need spawn system at location anymore.
I'm going to remove those nodes and we'll go ahead and make some room here for.
The nodes that we have over here.
We want this to be a little bit more organized.
So let's just organize this a little bit.
That's the thing about these blueprints, they can get a little bit messy, but with a little bit of
care and perhaps external plugins, if you are inclined to use those, we can make our blueprints neater.
But here, all we're doing after we looped is if we hit something, we're getting the combat target
from the Avatar actor.
We're setting that as the source object in some gameplay parameters that we're making, and then we're
executing a gameplay queue with params on owner and ending the ability.
And even if we never hit anything, we're still ending the ability.
Okay, so that's looking good.
I'm going to highlight these three nodes and hit queue so they're all aligned with each other and now
this is looking a bit more manageable.
Now this is great.
Our gameplay queue uses that combat target, which is the source object in the gameplay queue parameters
to spawn a system at location and we can go ahead and just clean up these as well.
So this doesn't look too messy.
There we go.
That's better.
All right.
So now that this looks a little bit cleaner, we see that we're spawning a system and we're getting
it from that source object.
Now, what about the sound that we should be playing for?
The impact?
We're just hard coding one in.
It'd be great if we could specify what sound to play.
Now, once we get over here to GC melee impact, we could get that sound if we knew which montage we're
playing because we have the effect causer.
If we get the effect causer here, we could cast it to an enemy or create an interface function to retrieve
something based on a tag.
For example, we could retrieve the tagged montage from its attack montages array, something like that.
And just to show what the effect causer is, we could call get object name right here and we could print
the string here.
Just for.
Clarity to see what that effect causer is.
And we can take a look at what happens.
So we see that it's set to none.
But that's, of course, because we have to pass it in right When we make the gameplay parameters,
we can set that effect causer.
We can call get Avatar actor from actor info and pass it in for the effect causer.
And now we should be able to see that effect causer and notice we see it on client and server.
So we know that our gameplay queue now that we've passed in the effect causer into our queue parameters,
it has the effect causer and it can look up from its attack montage tagged montages array which sound
we should play.
So how do we get that gameplay tag?
Well really we could pass it through with any of these gameplay queue parameters that we like.
Notice we have aggregated source and target tags.
These are gameplay tag containers and we could just pass in a container.
For example, we have our tagged montage, we can get that, we can break it and we can get this montage
tag and make a gameplay tag container with make gameplay tag container from tag.
And with this tag container if we set that aggregated source tags field here.
I'll go ahead and collapse that.
Now then in our gameplay queue melee impact, we can take that aggregated source tags and why don't
we just create a for each loop to loop through those tags and see what they are?
So aggregated source tags, we'll hook that in, we'll get an automatic make array because this is a
gameplay tag container structure.
Now we're going to loop through this aggregated source tags and for each of the tags I'm just going
to get a debug string and I'm going to print the string.
I just want to see on server and client what aggregated source tags is.
So if I go ahead and press play and get hit a couple times on client and server, we get montage attack
weapon.
So we know that we have that montage tag.
So what we'll do is we'll check that montage tag.
We want to get the sound corresponding to that montage tag.
How do we do that?
Well, we know that the enemy has an array of these tagged montages and we want to loop through and
get one that's using that tag.
Now, we may have multiple attacks using the same montage tag.
So really, if we looped through that array and got the first tagged montage that has that tag, if
we have multiple attacks that use the same tag, then that can be a problem, right?
The way to get around that would be perhaps to identify each tagged montage with its own unique tag.
And then we would call this instead of montage tag, we would call it something like socket tag so we
could identify montages and sockets separately.
But for now, I'm just going to find the tagged montage that has that same montage tag and just assume
that we only get one tagged montage per montage tag.
So for that I'd like a nice handy way to retrieve the correct tagged montage so we know which sound
to play.
And we can do that in the next video and we can even organize this a bit better so that our attack montage
is array actually does identify each tagged montage with a montage tag and identify each combat socket
with a combat socket tag.
So we'll organize this a little bit better in the next video.
I'll see you then.