WEBVTT

00:06.840 --> 00:07.890
Welcome back.

00:07.920 --> 00:13.920
Now we've got some really nice impact effects and they work just fine on the server, but on clients

00:13.920 --> 00:21.000
we don't see or hear anything and we know that that's because these gameplay abilities executed on the

00:21.000 --> 00:28.920
server are not replicated to any of the players because none of them actually own that ability system

00:28.920 --> 00:31.650
component that belongs to that enemy.

00:31.770 --> 00:34.650
So we're going to use a gameplay queue.

00:34.800 --> 00:40.580
Now there are different kinds of gameplay queues, so we're going to look at the simplest kind.

00:40.590 --> 00:42.390
So let's create a gameplay queue.

00:42.420 --> 00:47.970
We're going to go into Blueprints, Ability System Enemy and right click and make a new folder called

00:47.970 --> 00:48.870
Queues.

00:48.870 --> 00:55.140
And let's go into that folder now we're going to right click and make a new blueprint class and type

00:55.140 --> 00:56.250
gameplay queue.

00:56.280 --> 00:59.370
Now notice there are different types of gameplay queues.

00:59.370 --> 01:05.490
They all start with gameplay queue notify, and there's one called Actor and there's another called

01:05.490 --> 01:06.600
Static.

01:06.600 --> 01:09.660
And there are of course subclasses of these.

01:09.660 --> 01:14.820
We're going to choose gameplay queue notify static, which is what it sounds like.

01:14.820 --> 01:18.990
We won't actually be instantiating an object of the gameplay queue.

01:18.990 --> 01:20.460
Notify static class.

01:20.490 --> 01:24.140
It's a static version of the gameplay queue.

01:24.180 --> 01:31.800
Let's go ahead and select that and call this g c underscore and we'll call this melee impact.

01:33.650 --> 01:39.460
Now, if we double click to open this melee impact, we'll see that we have an event graph.

01:39.470 --> 01:47.270
So this gameplay queue is a class where we can specify what happens when the gameplay queue is executed.

01:47.390 --> 01:53.300
Now to specify that we override a function, we're going to choose on execute.

01:53.330 --> 01:57.920
Now notice on execute has a parent on execute.

01:57.950 --> 02:02.900
We can just hook those parameters straight in there and that returns a boolean.

02:02.900 --> 02:07.520
And this is basically like calling super in C plus plus.

02:07.670 --> 02:13.640
Now we can choose what happens here and on execute has parameters.

02:13.640 --> 02:21.380
This is a gameplay queue parameter structure which we can drag off and break to see a bunch of different

02:21.380 --> 02:25.940
bits of data that we have access to when we execute a gameplay queue.

02:25.940 --> 02:30.230
So if we execute a gameplay queue with parameters, we have access to those.

02:30.230 --> 02:35.760
Some of them are filled in automatically when this gameplay queue is executed from a gameplay effect

02:35.760 --> 02:37.170
which we can do.

02:37.170 --> 02:41.730
But if we execute this gameplay queue manually, we have to fill these in.

02:41.730 --> 02:48.660
And as you can see there are lots of parameters here, including an effect context we can pass through

02:48.660 --> 02:55.260
a magnitude we can even pass in a source object, which is good for passing arbitrary data.

02:55.260 --> 02:57.120
So we have information here.

02:57.420 --> 03:02.550
Now what I'd like to do in melee impact is play the sound and spawn the particles.

03:02.760 --> 03:07.170
So I'm going to right click and just use place out at location.

03:10.200 --> 03:12.720
And for now I'm going to hardcode the sound.

03:12.720 --> 03:14.370
It's going to be SFX.

03:16.100 --> 03:24.920
And I'm not sure what sound I use, so I'm going to go into my ability system, enemy abilities and

03:24.920 --> 03:26.180
melee attack.

03:26.210 --> 03:32.270
And I see that I'm getting that sound from the tagged montage that's in our enemy.

03:32.660 --> 03:39.650
So I'm going to go to my spear enemy edit Goblin spear, Search for attack.

03:39.650 --> 03:42.350
And here it is, it's SFX Swipe.

03:42.350 --> 03:51.260
I'm going to browse to it and then come back to GC Melee Impact and use that SFX swipe Now for the location.

03:51.260 --> 03:59.090
My gameplay parameters has a location, so as long as I set that when I trigger this cue will have a

03:59.090 --> 04:00.440
valid location.

04:00.740 --> 04:05.510
So I'm going to go ahead and hook that in and then I'm going to spawn a Niagara system.

04:05.510 --> 04:08.810
So I'm going to use spawn system at location.

04:08.810 --> 04:14.000
And for this I'm just going to for now hardcode my blood.

04:15.230 --> 04:18.950
That blood impact and use the same location.

04:19.460 --> 04:26.030
Hook that up like so and we'll go ahead and return after that.

04:26.240 --> 04:32.210
So we have this melee impact and I'd like to execute this gameplay queue.

04:32.240 --> 04:39.110
Now in order to execute a gameplay queue, we identify them by tag and if we select class defaults,

04:39.110 --> 04:41.030
we'll see that under gameplay queue.

04:41.060 --> 04:43.010
We have a gameplay queue tag.

04:43.130 --> 04:43.640
Now.

04:43.640 --> 04:46.820
The tag that we use has to start with gameplay queue.

04:46.820 --> 04:54.230
So if we go to edit and project settings here in project settings in gameplay tags, notice that we

04:54.230 --> 05:01.190
have gameplay queue, we can click plus to add a sub tag and we're going to call this melee impact.

05:01.190 --> 05:03.740
And I totally spelled it wrong.

05:03.740 --> 05:09.710
So I'm going to rename this to melee impact with a C there.

05:10.160 --> 05:12.920
And now we have melee impact.

05:13.310 --> 05:18.300
Now I can go into my gameplay queue, melee impact and select gameplay queue.

05:18.300 --> 05:25.260
Notice it only lets you select a tag that has gameplay queue in it and it has to be the topmost parent

05:25.260 --> 05:26.460
in the hierarchy.

05:26.460 --> 05:32.640
But now that I have this gameplay queue tag here in melee impact, we can execute the gameplay queue

05:32.640 --> 05:41.400
by tag as the game has a gameplay queue manager which is responsible for performing the lookup by tag.

05:41.400 --> 05:48.510
So back in game melee attack, what we can do now instead of spawning a system at location, we can

05:48.510 --> 05:54.510
go ahead and just disconnect that for now and go back to the completed for the for each loop.

05:54.510 --> 06:00.600
And if we have hit a target before we end the ability, instead of playing a sound at location, I'm

06:00.600 --> 06:07.410
going to move that out of the way and I'm going to right click and type execute gameplay queue with

06:07.410 --> 06:09.480
params on owner.

06:09.810 --> 06:15.090
So hooking this up, we now have the ability to execute a gameplay queue.

06:15.120 --> 06:20.310
I'm going to go ahead and hook that up to end ability and we choose the gameplay queue tag that's going

06:20.310 --> 06:21.930
to be melee impact.

06:21.930 --> 06:24.210
And if we compile we get an error.

06:24.210 --> 06:26.790
If we don't pass in gameplay queue parameters.

06:26.790 --> 06:31.890
So we're going to drag off and make gameplay queue parameters and then we can compile.

06:32.560 --> 06:35.950
Now Unreal is telling me I have to restart.

06:35.980 --> 06:40.960
So what I'm going to do is save all and quickly restart.

06:42.210 --> 06:45.330
And I'll go ahead and open up all my asset editors.

06:45.720 --> 06:51.090
So back in melee attack, we're no longer spawning system at location.

06:51.090 --> 06:53.700
We're no longer playing sound at location.

06:53.700 --> 06:55.950
We're executing a gameplay cue.

06:55.980 --> 07:02.570
This is a static gameplay cue where specifying the melee impact tag and we're passing in gameplay cue

07:02.640 --> 07:03.410
parameters.

07:03.420 --> 07:05.160
This is of course an empty struct.

07:05.160 --> 07:07.170
We're not setting anything on it.

07:07.350 --> 07:15.240
But let's see what happens if we execute this as we're playing a sound which we've hard coded and spawning

07:15.240 --> 07:17.340
a system which we've hard coded as well.

07:17.430 --> 07:19.440
So let's go ahead and.

07:20.410 --> 07:21.460
Press play.

07:34.760 --> 07:36.360
So we're getting the sound.

07:36.380 --> 07:38.270
We're not getting the impact particles.

07:38.270 --> 07:41.330
Actually, we're not passing in a location, are we?

07:41.360 --> 07:47.150
So if we go back to melee attack, remember, we have that location, we're using that in the gameplay

07:47.150 --> 07:49.280
queue, but we never actually set it.

07:49.310 --> 07:50.700
We can set that.

07:50.720 --> 07:55.220
So here's the location in our gameplay queue parameters that we made.

07:55.250 --> 08:00.800
We're going to use the combat socket location for that, so I'm going to go ahead and copy that, get

08:00.830 --> 08:04.150
Node and we're going to pass in the location now.

08:04.160 --> 08:10.370
So let's see what happens now that we're passing that into the queue parameters, let's press play.

08:11.940 --> 08:12.270
Here.

08:12.270 --> 08:17.430
I'm on the client and I can see and hear just fine.

08:18.300 --> 08:19.920
Thanks to our gameplay cue.

08:19.950 --> 08:21.630
Let's check out the server.

08:22.750 --> 08:24.990
And we see it on the server as well.

08:25.000 --> 08:32.740
So thanks to gameplay cues, we can now have visual and sound effects and those can be replicated.

08:32.740 --> 08:38.920
So even though we have an AI controlled character executing an ability which isn't going to replicate

08:38.920 --> 08:47.830
down to any human players, we can execute a gameplay cue and pass in optional parameters and use those

08:47.950 --> 08:49.810
now for the blood impact.

08:49.810 --> 08:53.740
We can actually get that from the thing that we're hitting, right?

08:53.740 --> 08:56.290
And we can know the thing that we're hitting.

08:56.320 --> 08:59.020
Thanks to our gameplay cue parameters here.

08:59.020 --> 09:02.470
We could say set it as the source object.

09:02.500 --> 09:09.520
If we wanted to do that, we could also get the effect context and we know that we can add any type

09:09.520 --> 09:13.300
of data we like in our effect context as well.

09:13.690 --> 09:18.880
So let's see what happens if we pass something along for the source object here.

09:18.880 --> 09:27.500
So in a melee attack, let's expand the make gameplay cue parameters and let's just see if we can pass

09:27.500 --> 09:29.480
something in for the source object.

09:29.510 --> 09:31.730
We know that we have a combat target.

09:31.760 --> 09:36.170
Let's just see what happens if we pass that in for our source object.

09:36.200 --> 09:39.620
So I'm going to right click and just type get combat target.

09:42.980 --> 09:49.040
And I'm going to take the true wire and just bring it way over here.

09:50.010 --> 09:52.350
And then bring it all the way back.

09:52.350 --> 09:54.210
We'll organize this in a second.

09:54.240 --> 09:56.130
We're going to use the Avatar actor.

09:56.130 --> 10:00.360
So get Avatar actor from actor info.

10:00.570 --> 10:05.250
And once we have this combat target, we're going to pass that in as the source object.

10:05.280 --> 10:06.510
This is an object.

10:06.510 --> 10:10.020
So it could be an actor, It can take an actor in.

10:10.260 --> 10:16.920
So once we have that combat target as the source object here in our gameplay queue, we can get that

10:16.920 --> 10:18.090
source object.

10:18.090 --> 10:23.820
And from the source object we can get those impact particles, the blood particles.

10:23.820 --> 10:31.050
So I'm going to right click here and type get blood effect and we're going to pass in that source object

10:31.050 --> 10:32.190
as the target.

10:32.220 --> 10:39.570
We're going to hook these up and this return value will be used for spawning the system.

10:39.930 --> 10:43.800
So now we're using the blood effect on the combat target.

10:43.800 --> 10:45.990
Let's see what happens if we do that.

10:47.100 --> 10:48.360
We get the blood.

10:48.960 --> 10:50.100
So same thing.

10:50.100 --> 10:57.400
But now this is kind of cool because we can change the blood effect just to prove that we can do that.

10:57.420 --> 11:02.700
I'm going to go into assets effects combat, and we have this blood impact.

11:02.700 --> 11:11.340
I'm going to duplicate it and call this blood impact, underscore green and open up this blood effect.

11:11.340 --> 11:15.900
Select initialize particle and change this to a green color.

11:16.270 --> 11:16.650
Nice.

11:16.650 --> 11:18.510
Kind of dark green, I think.

11:18.690 --> 11:21.030
Click okay and save that.

11:21.610 --> 11:24.670
And I'm going to open up my aura blueprint.

11:24.670 --> 11:34.120
So blueprints, character, aura, BP Aura, character and search for blood and set this to blood impact

11:34.120 --> 11:34.900
Green.

11:36.130 --> 11:38.380
Now if I press play.

11:39.260 --> 11:40.370
And I get hit.

11:40.400 --> 11:44.260
Now we see green and this is even on the client as well.

11:44.270 --> 11:47.300
And notice he missed that time and we didn't see anything.

11:47.300 --> 11:50.540
So that's exactly the behavior we want.

11:50.900 --> 11:52.730
So that's great.

11:52.760 --> 11:59.960
Now we're passing in a source object through that gameplay queue parameter struct, which is pretty

11:59.960 --> 12:00.650
cool.

12:00.980 --> 12:01.250
Okay.

12:01.250 --> 12:06.380
I'm going to go back to Aura and set this back to the regular blood impact because I want Aura to have

12:06.380 --> 12:07.190
red blood.

12:07.810 --> 12:09.220
And I'll close that.

12:09.580 --> 12:18.900
So now our gay melee attack is executing the gameplay cue and we don't need play sound at location anymore.

12:18.910 --> 12:25.960
So I'm going to go ahead and remove those nodes and we don't need spawn system at location anymore.

12:25.960 --> 12:31.090
I'm going to remove those nodes and we'll go ahead and make some room here for.

12:32.830 --> 12:35.320
The nodes that we have over here.

12:35.320 --> 12:38.040
We want this to be a little bit more organized.

12:38.050 --> 12:40.960
So let's just organize this a little bit.

12:41.200 --> 12:46.480
That's the thing about these blueprints, they can get a little bit messy, but with a little bit of

12:46.480 --> 12:54.310
care and perhaps external plugins, if you are inclined to use those, we can make our blueprints neater.

12:54.310 --> 13:02.080
But here, all we're doing after we looped is if we hit something, we're getting the combat target

13:02.080 --> 13:03.850
from the Avatar actor.

13:04.030 --> 13:10.930
We're setting that as the source object in some gameplay parameters that we're making, and then we're

13:10.930 --> 13:16.030
executing a gameplay queue with params on owner and ending the ability.

13:16.030 --> 13:20.530
And even if we never hit anything, we're still ending the ability.

13:20.980 --> 13:23.740
Okay, so that's looking good.

13:24.040 --> 13:29.590
I'm going to highlight these three nodes and hit queue so they're all aligned with each other and now

13:29.590 --> 13:31.510
this is looking a bit more manageable.

13:31.660 --> 13:33.050
Now this is great.

13:33.080 --> 13:41.450
Our gameplay queue uses that combat target, which is the source object in the gameplay queue parameters

13:41.450 --> 13:47.810
to spawn a system at location and we can go ahead and just clean up these as well.

13:48.520 --> 13:51.250
So this doesn't look too messy.

13:51.280 --> 13:52.180
There we go.

13:52.180 --> 13:53.080
That's better.

13:53.650 --> 13:54.220
All right.

13:54.220 --> 13:59.080
So now that this looks a little bit cleaner, we see that we're spawning a system and we're getting

13:59.080 --> 14:00.820
it from that source object.

14:00.850 --> 14:04.330
Now, what about the sound that we should be playing for?

14:04.330 --> 14:05.290
The impact?

14:05.320 --> 14:07.370
We're just hard coding one in.

14:07.390 --> 14:11.150
It'd be great if we could specify what sound to play.

14:11.170 --> 14:18.790
Now, once we get over here to GC melee impact, we could get that sound if we knew which montage we're

14:18.790 --> 14:21.630
playing because we have the effect causer.

14:21.640 --> 14:31.240
If we get the effect causer here, we could cast it to an enemy or create an interface function to retrieve

14:31.240 --> 14:33.160
something based on a tag.

14:33.160 --> 14:39.940
For example, we could retrieve the tagged montage from its attack montages array, something like that.

14:39.940 --> 14:47.980
And just to show what the effect causer is, we could call get object name right here and we could print

14:47.980 --> 14:49.190
the string here.

14:50.810 --> 14:52.190
Just for.

14:54.850 --> 14:57.940
Clarity to see what that effect causer is.

14:57.970 --> 15:01.180
And we can take a look at what happens.

15:03.300 --> 15:05.100
So we see that it's set to none.

15:05.100 --> 15:10.950
But that's, of course, because we have to pass it in right When we make the gameplay parameters,

15:10.950 --> 15:12.870
we can set that effect causer.

15:12.870 --> 15:20.040
We can call get Avatar actor from actor info and pass it in for the effect causer.

15:20.040 --> 15:26.400
And now we should be able to see that effect causer and notice we see it on client and server.

15:26.490 --> 15:34.320
So we know that our gameplay queue now that we've passed in the effect causer into our queue parameters,

15:34.320 --> 15:43.410
it has the effect causer and it can look up from its attack montage tagged montages array which sound

15:43.410 --> 15:44.370
we should play.

15:44.520 --> 15:47.460
So how do we get that gameplay tag?

15:47.610 --> 15:52.620
Well really we could pass it through with any of these gameplay queue parameters that we like.

15:52.620 --> 15:55.530
Notice we have aggregated source and target tags.

15:55.530 --> 16:00.090
These are gameplay tag containers and we could just pass in a container.

16:00.300 --> 16:08.350
For example, we have our tagged montage, we can get that, we can break it and we can get this montage

16:08.350 --> 16:14.440
tag and make a gameplay tag container with make gameplay tag container from tag.

16:14.440 --> 16:20.950
And with this tag container if we set that aggregated source tags field here.

16:21.810 --> 16:23.490
I'll go ahead and collapse that.

16:23.490 --> 16:30.750
Now then in our gameplay queue melee impact, we can take that aggregated source tags and why don't

16:30.750 --> 16:37.680
we just create a for each loop to loop through those tags and see what they are?

16:37.710 --> 16:43.920
So aggregated source tags, we'll hook that in, we'll get an automatic make array because this is a

16:43.920 --> 16:45.870
gameplay tag container structure.

16:45.900 --> 16:51.990
Now we're going to loop through this aggregated source tags and for each of the tags I'm just going

16:51.990 --> 16:56.610
to get a debug string and I'm going to print the string.

16:58.650 --> 17:04.590
I just want to see on server and client what aggregated source tags is.

17:04.590 --> 17:11.760
So if I go ahead and press play and get hit a couple times on client and server, we get montage attack

17:12.030 --> 17:12.750
weapon.

17:12.750 --> 17:17.250
So we know that we have that montage tag.

17:17.250 --> 17:22.020
So what we'll do is we'll check that montage tag.

17:22.020 --> 17:27.210
We want to get the sound corresponding to that montage tag.

17:27.210 --> 17:28.800
How do we do that?

17:28.830 --> 17:36.450
Well, we know that the enemy has an array of these tagged montages and we want to loop through and

17:36.450 --> 17:39.030
get one that's using that tag.

17:39.030 --> 17:43.770
Now, we may have multiple attacks using the same montage tag.

17:43.770 --> 17:50.730
So really, if we looped through that array and got the first tagged montage that has that tag, if

17:50.730 --> 17:55.170
we have multiple attacks that use the same tag, then that can be a problem, right?

17:55.200 --> 18:01.660
The way to get around that would be perhaps to identify each tagged montage with its own unique tag.

18:01.660 --> 18:08.230
And then we would call this instead of montage tag, we would call it something like socket tag so we

18:08.230 --> 18:12.190
could identify montages and sockets separately.

18:12.190 --> 18:20.620
But for now, I'm just going to find the tagged montage that has that same montage tag and just assume

18:20.620 --> 18:25.270
that we only get one tagged montage per montage tag.

18:25.270 --> 18:34.000
So for that I'd like a nice handy way to retrieve the correct tagged montage so we know which sound

18:34.000 --> 18:34.900
to play.

18:34.900 --> 18:41.770
And we can do that in the next video and we can even organize this a bit better so that our attack montage

18:41.770 --> 18:50.890
is array actually does identify each tagged montage with a montage tag and identify each combat socket

18:50.890 --> 18:52.810
with a combat socket tag.

18:52.810 --> 18:56.950
So we'll organize this a little bit better in the next video.

18:56.980 --> 18:58.180
I'll see you then.
