WEBVTT

00:07.060 --> 00:08.170
Welcome back.

00:08.200 --> 00:14.770
In the last video, we learned a little bit more about gameplay cues, and we have our gameplay cues

00:14.770 --> 00:24.070
now all in the same folder, and we've designated the gameplay cue notify paths to that folder and Blueprint's

00:24.070 --> 00:27.700
ability system gameplay cue notifies they're all here.

00:27.730 --> 00:36.160
Now that's great, but so far we've only created the gameplay cue notify static type of gameplay cue,

00:36.160 --> 00:38.800
and we've seen that there are others now.

00:38.800 --> 00:41.110
Gameplay cue notifies static is limited.

00:41.140 --> 00:47.890
It's not actually instanced, so this is treated as if it were, say, a static function call on a static

00:47.890 --> 00:49.000
function library.

00:49.030 --> 00:57.250
For example, a gameplay cue notifies static is a gameplay cue notify that operates on the class default

00:57.280 --> 01:04.480
object, so there are no instances spawned when we execute the gameplay cue.

01:04.600 --> 01:07.450
Now there's another kind of gameplay cue notify.

01:07.480 --> 01:14.380
There's the gameplay cue notify actor, and for the gameplay cue, notify actor, we actually do spawn

01:14.380 --> 01:18.130
an instance of that class when we execute it.

01:18.160 --> 01:20.110
I'd like to create one of those now.

01:20.710 --> 01:28.900
So I'm going to go to create new blueprint class and search for gameplay cue notify and choose Gameplay

01:28.900 --> 01:31.420
Cue Notify Actor and select it.

01:31.420 --> 01:36.550
And I'm going to call this GC underscore shock loop.

01:37.300 --> 01:41.650
Shock loop seems to indicate that this is going to be something that loops.

01:41.650 --> 01:44.920
And that's what gameplay cue notify actors are pretty good for.

01:44.950 --> 01:51.460
If you need some kind of looping sound, or perhaps a Niagara system that needs to stick around until

01:51.460 --> 01:53.290
you remove this gameplay cue.

01:53.320 --> 01:55.870
Gameplay cue notify actors are great for that.

01:55.870 --> 01:57.010
Now if we open it.

01:57.040 --> 02:01.150
Notice that it's a lot different looking than our GC Shock Burst.

02:01.180 --> 02:05.910
Shock burst has an event graph and this on execute that we overrode.

02:05.920 --> 02:08.800
But shock loop actually has a viewport.

02:08.830 --> 02:10.560
This is an actual actor.

02:10.570 --> 02:13.930
It has a default scene route like all actors have.

02:13.960 --> 02:16.820
It has a construction script an event graph.

02:16.840 --> 02:19.750
It even has begun play event.

02:19.750 --> 02:20.200
Tick.

02:20.200 --> 02:23.440
All of that stuff, all the stuff an actor has.

02:23.440 --> 02:25.390
But it's a special kind of actor.

02:25.390 --> 02:26.290
It's a gameplay cue.

02:26.290 --> 02:28.690
Notify actor and the gameplay cue.

02:28.690 --> 02:35.860
Notify actor has some functions we can override to determine what happens when we execute this gameplay

02:35.860 --> 02:36.520
cue.

02:36.640 --> 02:43.060
Now, in the class settings, notice that we can even implement interfaces and things like that.

02:43.060 --> 02:45.010
And in the class defaults.

02:45.040 --> 02:48.580
This is where we set the gameplay cue tag.

02:48.580 --> 02:54.610
And of course we'll need one if we want this shock loop to be executable as a gameplay cue.

02:54.640 --> 03:00.370
So I'm going to go to Project Settings Gameplay Tags and add a new gameplay cue tag.

03:00.370 --> 03:04.270
And this will be gameplay cue shock loop.

03:05.040 --> 03:09.020
And I can close project settings and our new shock loop.

03:09.030 --> 03:12.930
I'm going to set its gameplay queue tag to Shock loop.

03:12.960 --> 03:16.530
Now one important setting is auto destroy on remove.

03:16.560 --> 03:18.270
You're going to want to check that.

03:18.300 --> 03:26.160
Otherwise, subsequent calls to execute this gameplay queue won't work if it's not destroyed when the

03:26.160 --> 03:27.750
gameplay queue has been removed.

03:27.780 --> 03:34.980
Now, a gameplay queue can be added to an actor, and it can stay active until you remove it from that

03:34.980 --> 03:35.640
actor.

03:35.640 --> 03:40.440
And in order to determine what happens when active, we can override a function.

03:41.140 --> 03:48.880
Now on active is, as we can see by the pop up called, when a gameplay cue with duration is first activated

03:48.880 --> 03:52.300
and will only be called if the client witnessed the activation.

03:52.330 --> 03:58.810
So in other words, if we activate this and we have some looping sound and a looping beam particle effect

03:58.810 --> 04:03.400
or something like that, if another player spawns in, they won't see it.

04:03.430 --> 04:04.510
They missed it.

04:04.540 --> 04:12.370
Whereas if we spawn that effect in while active, while active is good for things that a newly spawning

04:12.370 --> 04:14.200
in player should see.

04:14.230 --> 04:21.280
So while active will be triggered for a player that spawns in, whereas on active is a one off that

04:21.280 --> 04:22.600
that player missed.

04:22.630 --> 04:27.340
Here's a good way to think about when to use on active versus while active.

04:27.580 --> 04:33.520
Let's say you have an explosion, and as soon as this gameplay cue is added to an actor, you want that

04:33.520 --> 04:34.930
explosion to trigger.

04:35.020 --> 04:41.080
And if a new player spawns in and this gameplay queue is still active, well, you don't need it to

04:41.080 --> 04:42.130
see that explosion.

04:42.130 --> 04:44.200
That explosion happened in the past.

04:44.230 --> 04:45.500
It's done.

04:45.520 --> 04:50.710
But let's say now that you're spawning a beam effect like a shock electric beam.

04:50.710 --> 04:56.470
And while this gameplay effect is active, you want that beam to be active.

04:56.470 --> 05:00.160
And if a new player spawns in, they should see that beam.

05:00.190 --> 05:05.270
So while active, should trigger for them because it's still happening.

05:05.290 --> 05:12.820
So in our case, for a shock loop for our electric beam we're going to want to override while active.

05:13.030 --> 05:16.870
Now while active takes in the my target.

05:16.870 --> 05:19.170
But it can also take in parameters.

05:19.180 --> 05:21.760
And if we break the gameplay cue parameters.

05:21.760 --> 05:27.550
Notice that there are quite a few of them that can be passed into this gameplay queue, and this can

05:27.550 --> 05:28.720
be really useful.

05:28.720 --> 05:30.670
We can use any number of these.

05:31.250 --> 05:37.400
So we're going to be using this to spawn our electric beam and play a sound.

05:37.700 --> 05:42.740
Now an important question is how do we actually trigger this gameplay cue?

05:42.770 --> 05:44.360
How do we make it happen?

05:44.510 --> 05:48.410
Well, to do that, we add this gameplay cue to an actor.

05:48.740 --> 05:52.190
So let's go into our gameplay ability.

05:52.900 --> 05:56.530
Aura abilities lightning to electrocute.

05:56.530 --> 06:01.690
And let's actually add this gameplay cue to an actor.

06:02.020 --> 06:09.450
So after we've received the gameplay event, this is when I want to start spawning that electric beam.

06:09.460 --> 06:19.030
So what I can do is I can right click and type Add Gameplay cue on actor, and notice there's a looping

06:19.030 --> 06:20.590
in parentheses here.

06:20.680 --> 06:27.370
So if we add a gameplay cue on an actor, it's going to remain active until we remove it.

06:27.970 --> 06:30.970
We need to specify the actor to add this to.

06:31.000 --> 06:33.880
For now, I'm just going to pass in the avatar.

06:33.880 --> 06:38.920
So I'm going to get avatar actor from actor info and pass that in for now.

06:38.950 --> 06:41.980
And we're going to set the gameplay tag to Shock Loop.

06:42.310 --> 06:45.670
We can even make some gameplay queue parameters to pass in.

06:45.670 --> 06:49.300
And if I compile you'll see that that's required.

06:49.300 --> 06:53.020
So we're going to make gameplay queue parameters and pass them in.

06:53.350 --> 06:59.950
Now as soon as this node is reached, shock loop is going to be active.

06:59.980 --> 07:04.240
We can get that my target and we can get object name.

07:06.110 --> 07:08.300
And we can print it in a string.

07:16.250 --> 07:20.090
So we can see what happens when we add the gameplay cue.

07:20.390 --> 07:22.640
Let's press play and right click.

07:23.480 --> 07:25.310
And we get that print string.

07:32.370 --> 07:35.400
Now if we try to execute multiple times.

07:36.350 --> 07:38.270
Well, let's try it a second time.

07:38.270 --> 07:41.570
We don't see the printed string every subsequent time.

07:41.570 --> 07:45.710
We're going to have to remove this gameplay cue because it's already active.

07:45.740 --> 07:48.110
So what we can do is remove it.

07:49.860 --> 07:51.930
Here in prepared to end ability.

07:54.600 --> 07:55.860
And how do we remove it?

07:55.890 --> 08:01.380
We can call remove gameplay cue from owner.

08:01.410 --> 08:05.010
Now this will remove the gameplay cue.

08:05.160 --> 08:09.690
And this is a function actually on the gameplay ability itself.

08:09.690 --> 08:13.170
So it can take in self as the reference.

08:13.170 --> 08:19.350
And it just is smart enough to find the avatar associated with this gameplay ability.

08:19.350 --> 08:23.520
And we specify the gameplay tag, we're going to choose Shock Loop.

08:24.410 --> 08:27.080
So we can go ahead and activate it.

08:27.110 --> 08:29.600
We got the string we can activate again.

08:29.600 --> 08:30.950
We got the string again.

08:30.950 --> 08:35.690
And we'll keep getting that string if we keep activating it because we keep removing it.

08:35.720 --> 08:42.650
Now if we want to see exactly when it's removed, we can do that here in our shock loop gameplay queue,

08:42.680 --> 08:44.780
we can override the function.

08:46.190 --> 08:48.590
Override on remove.

08:49.170 --> 08:52.980
And here in on remove we can also print a string.

08:55.040 --> 08:57.350
And I'll make this string red.

08:58.280 --> 09:03.080
And we'll say remove GCC shock loop.

09:05.500 --> 09:07.780
And now we can see when it gets removed.

09:07.810 --> 09:13.800
I'm still holding the mouse button down, and if I unclick, we see that it's removed.

09:13.810 --> 09:19.030
So the gameplay cue is added as soon as we get that gameplay event.

09:19.060 --> 09:25.900
It's removed when we unclick, but notice we didn't see the string the second time we release the mouse

09:25.900 --> 09:26.590
button.

09:26.680 --> 09:28.120
Let's see that again.

09:28.120 --> 09:29.230
So we get it.

09:29.260 --> 09:33.730
We get on remove, we activate again, and then we don't get on remove.

09:33.730 --> 09:35.410
So what's going on here?

09:35.710 --> 09:42.640
Well, if we click on class defaults we need to make sure auto destroy on remove is checked.

09:44.160 --> 09:45.810
If we have that checked.

09:46.850 --> 09:49.040
Then we should see the remove message.

09:49.870 --> 09:51.160
Every single time.

09:55.140 --> 10:04.770
So we'll make sure that each time GC shock loop is added and removed, the actual instance of this gameplay

10:04.770 --> 10:09.450
queue notify actor is going to be destroyed on remove.

10:10.160 --> 10:12.140
Okay, so that's great.

10:12.140 --> 10:15.950
But we want to see a electric beam, right.

10:16.070 --> 10:17.550
How are we going to do that?

10:17.570 --> 10:23.020
Well, first of all we need to go to while active and spawn a Niagara system.

10:23.030 --> 10:25.010
I'm going to remove the print string.

10:25.070 --> 10:26.660
I actually don't need the print string.

10:26.660 --> 10:28.220
And on remove either.

10:28.310 --> 10:33.200
And I'm going to use spawn system attached.

10:33.290 --> 10:43.430
I'd like to use spawn system attached because I want to attach this system to a specific socket, the

10:43.430 --> 10:46.970
socket on or staff in the case of aura.

10:47.300 --> 10:55.820
So back to the electrocute in the event graph up here where we're passing in gameplay queue parameters,

10:55.910 --> 10:58.850
I'd like to pass something in to my queue parameters.

10:58.850 --> 11:06.470
And here in the shock loop we can get something to pass into the component we want to attach to.

11:06.560 --> 11:10.460
Now, the gameplay queue parameters has a number of things that we can set.

11:10.490 --> 11:14.270
One of them is called target attach component.

11:14.270 --> 11:15.620
I'd like to set that.

11:16.810 --> 11:18.160
Now for electrocute.

11:18.160 --> 11:24.730
I'd like to get the weapon, and it'd be handy to get the weapon from an interface function call.

11:24.880 --> 11:31.710
So if I could just take my avatar and pass it into an interface function call that retrieves the weapon,

11:31.720 --> 11:38.080
well, then we could use that weapon, as the weapon is a skeletal mesh component, and we could pass

11:38.080 --> 11:42.250
that in as target attached component as that's a scene component.

11:42.250 --> 11:44.440
And we can just pass it right in there.

11:44.710 --> 11:46.330
That would make things easy.

11:46.330 --> 11:49.150
So I'm going to go ahead and close the editor.

11:49.770 --> 11:50.910
Saving all.

11:52.540 --> 11:57.820
I'm going to open my combat interface, and I'm going to add a function to get the weapon.

11:57.820 --> 12:00.130
I don't think we have a get weapon function.

12:00.130 --> 12:04.360
So this function will return a skeletal mesh component.

12:04.750 --> 12:10.150
So it's going to return a new skeletal mesh component pointer.

12:10.150 --> 12:12.970
And this will be called get weapon.

12:14.570 --> 12:17.120
And I'd like it to be a blueprint native event.

12:17.150 --> 12:18.650
Blueprint callable.

12:22.730 --> 12:29.180
So we'll go ahead and put that here and we'll override it in the base character class or a character

12:29.180 --> 12:29.870
base.

12:29.960 --> 12:39.540
So here in combat interface we'll say virtual you skeletal mesh component get weapon implementation.

12:39.560 --> 12:41.210
We'll implement it.

12:44.500 --> 12:47.350
And we're going to simply return the weapon.

12:50.060 --> 12:53.480
So now we have this easy to use function to get the weapon.

12:53.780 --> 12:57.650
Let's go ahead and compile and launch back up.

12:59.800 --> 13:07.000
And we can go right back into electrocute, back to where we're making gameplay parameters, and we

13:07.000 --> 13:10.270
can set the target attach component.

13:10.420 --> 13:13.270
So I'm going to right click and type Get Weapon.

13:13.300 --> 13:16.050
We're going to use that interface function call.

13:16.060 --> 13:21.160
We can use get avatar actor from actor info and pass that in.

13:22.010 --> 13:26.930
And take the return value and hook it up to target attach component.

13:27.260 --> 13:33.230
So right before we add the gameplay cue, we're going to call this function get weapon.

13:35.270 --> 13:40.610
Okay, I just made some spaghetti knots here, so I'm going to make sure to tidy up.

13:41.240 --> 13:42.500
My nodes here.

13:43.200 --> 13:49.800
And of course, this is something that will be refactoring into a collapsed function to make things

13:49.800 --> 13:51.750
easier to see and to read.

13:51.780 --> 13:54.810
But for now, this is okay.

13:57.920 --> 13:58.750
There we go.

13:58.760 --> 14:02.590
Trying to keep the spaghetti to a minimum here.

14:02.600 --> 14:06.740
And now we're passing in target attach component.

14:06.740 --> 14:09.170
And here in shock loop I don't need shock burst.

14:09.170 --> 14:10.130
I'm going to close that.

14:10.130 --> 14:13.340
But here in shock loop in while active.

14:13.400 --> 14:18.920
Now that we have a target attached component we can hook that in to spawn system attached.

14:19.040 --> 14:21.980
And we can get that tip socket.

14:23.120 --> 14:27.080
So we can pass in tip socket and we can double check that.

14:27.080 --> 14:28.220
That's what it's called.

14:28.220 --> 14:36.140
If we go to characters or staff SQM staff and it's actually called yes tip socket.

14:37.520 --> 14:42.740
So we're spawning a system and we're attaching it to the TCP socket.

14:43.350 --> 14:45.030
Now the system template.

14:45.060 --> 14:48.450
We're going to search for beam and get electric beam.

14:48.540 --> 14:55.260
Now I'd like to check auto destroy because as soon as this is deactivated, I'd just like it to be destroyed.

14:55.620 --> 15:00.570
Okay, so we've spawned a system, but what about the end of that beam?

15:00.570 --> 15:02.790
Because we're going to attach it to the tip socket.

15:02.790 --> 15:09.180
But the beam itself has an endpoint, and we can see that by browsing and opening the electric beam.

15:09.330 --> 15:17.550
If we go into this first emitter and you'll see that there are other emitters that are not active and

15:17.550 --> 15:19.110
there's two that are.

15:19.140 --> 15:25.980
If we go into blue electric beam and select beam Emitter setup, notice there's this beam start and

15:25.980 --> 15:27.270
beam end.

15:27.300 --> 15:29.100
And you can see that these say user.

15:29.100 --> 15:34.950
And it says a read only value which can be initialized per system and modified externally by the level

15:34.980 --> 15:37.620
by blueprint or by C plus plus.

15:37.620 --> 15:40.320
So we have a beam start and beam end.

15:40.470 --> 15:44.310
These are parameters we can set on this Niagara system.

15:44.670 --> 15:50.670
So if we go back to shock loop when we spawn this system, we can then promote this.

15:50.670 --> 15:52.980
So we can take the return value.

15:53.010 --> 15:57.090
We can promote to a variable local or just a variable.

15:57.090 --> 16:03.690
I'm going to promote to a regular variable and call this beam system and we'll save that.

16:03.810 --> 16:06.210
That way we can remove it later.

16:06.570 --> 16:12.180
And now that we have this beam system, we can set that beam end for it.

16:12.180 --> 16:13.920
We can take the beam system.

16:14.700 --> 16:21.840
And we can call set Niagara variable and we can set it as a vector.

16:21.990 --> 16:24.750
There's vector two, three and four.

16:24.780 --> 16:26.900
I'm going to choose vector three.

16:26.910 --> 16:30.210
And we're going to hook this up and make sure it goes to the return node.

16:30.210 --> 16:33.960
And the variable name is going to be the beam end.

16:33.990 --> 16:35.330
We want to set the beam end.

16:35.340 --> 16:36.450
So beam.

16:38.330 --> 16:40.850
And and we need a value.

16:41.060 --> 16:46.190
Well, for now, I'd just like to see what this looks like when we pass a value in.

16:46.190 --> 16:51.340
So in GA electrocute we're going to pass a value in through the queue parameters.

16:51.350 --> 16:56.090
We'll just use the location and we have the mouse hit location.

16:56.120 --> 17:00.320
Why don't we pass that in as location and in shock loop.

17:00.320 --> 17:02.000
We'll take that location.

17:02.000 --> 17:04.970
I'll go ahead and just promote that to a variable as well.

17:06.640 --> 17:08.170
So take location.

17:08.170 --> 17:09.700
Promote to variable.

17:11.060 --> 17:15.260
And we'll call this mouse hit location.

17:16.450 --> 17:21.730
We'll set that and we'll use it to update that beam parameter.

17:22.750 --> 17:24.940
We'll pass in mouse hit location.

17:26.470 --> 17:30.070
Okay, now this is going to spawn the system.

17:30.070 --> 17:31.480
But what about removing it?

17:31.480 --> 17:31.780
Right.

17:31.780 --> 17:33.280
We need to remove it too.

17:33.280 --> 17:35.440
So we're going to go into on remove.

17:35.440 --> 17:39.760
And since we made beam system a variable we can get it.

17:39.760 --> 17:42.850
It would be safe if we convert it to a validated Get.

17:42.850 --> 17:47.500
And if it's valid then what I'd like to do is destroy it.

17:47.500 --> 17:48.730
So I'm going to take it.

17:48.910 --> 17:50.920
Call destroy component.

17:52.330 --> 17:54.610
It's going to auto deactivate itself.

17:55.270 --> 17:57.940
And then we can go to the return node.

17:58.600 --> 18:05.160
So with that, let's see what happens when we add and remove this gameplay cue.

18:05.170 --> 18:06.550
I'm going to save all.

18:06.790 --> 18:08.170
I'm going to press play.

18:08.780 --> 18:11.390
And there's our lovely beam.

18:14.850 --> 18:16.200
And it stays there.

18:16.200 --> 18:20.610
It sticks around until we release the mouse button.

18:22.100 --> 18:23.810
Isn't that lovely?

18:23.840 --> 18:24.560
Look at that.

18:24.560 --> 18:25.640
It looks great.

18:28.720 --> 18:32.580
Now it looks like it's not going up to the correct location here on the wall.

18:32.590 --> 18:37.210
But remember, the wall is not responding to the visibility channel, so it's going through the wall

18:37.210 --> 18:37.780
there.

18:41.850 --> 18:43.100
Same thing with this.

18:43.110 --> 18:45.930
It's not responding to the visibility channel.

18:45.970 --> 18:46.500
Right.

18:46.500 --> 18:53.700
So if we want to perform a trace that will hit that, we'd have to go and do that separately.

18:53.910 --> 18:55.620
But look at that.

18:55.650 --> 18:58.200
We have a very, very nice looking.

18:59.070 --> 19:00.330
Electric beam.

19:00.780 --> 19:04.140
It doesn't have sound, but we're going to take care of that very soon.

19:04.140 --> 19:08.190
But for now we have the beam and it's looking great.

19:08.430 --> 19:09.390
Excellent.

19:09.690 --> 19:12.600
Awesome job and I'll see you in the next video.
