WEBVTT

00:06.970 --> 00:08.080
Welcome back.

00:08.410 --> 00:12.430
So we have the ability to launch fireballs, but we have an issue.

00:12.460 --> 00:15.340
We don't have any way to guide the fireball.

00:15.340 --> 00:18.590
We don't know which direction to send it off in.

00:18.610 --> 00:20.560
If we click over here.

00:21.680 --> 00:24.810
Our fireball still goes off into the distance that way.

00:24.830 --> 00:26.330
So that's a problem.

00:26.420 --> 00:32.320
We also would like a direction to orient the character towards.

00:32.330 --> 00:42.110
So I think that data that we want is basically the data of the hit result under the cursor when we click.

00:42.200 --> 00:47.310
Now we can create an ability task that can get this data for us.

00:47.330 --> 00:54.140
So here in GA Firebolt, as soon as we activate the ability, we could get that hit results under the

00:54.140 --> 01:01.020
cursor or at least the location associated with it and use that here in the ability.

01:01.040 --> 01:07.700
So we're going to make an ability task that can get that data for us and then we're going to see how

01:07.700 --> 01:13.670
this works in multiplayer and whether or not we need to make some changes to make this work for a multiplayer

01:13.700 --> 01:14.360
game.

01:14.600 --> 01:18.020
So first we're going to make a new ability task class.

01:18.050 --> 01:22.260
I'm going to go ahead and close out of some of these tabs.

01:22.260 --> 01:27.270
I think I'll go ahead and leave the Firebolt open and we'll go into C plus plus classes.

01:27.300 --> 01:29.550
Aura, public ability system.

01:29.700 --> 01:31.770
And we'll make a class right here.

01:31.890 --> 01:37.500
And I'm going to select all classes and search for ability task.

01:38.040 --> 01:45.300
So here we have ability task notice it's based on the gameplay task class and also notice that the engine

01:45.300 --> 01:48.830
has a number of ability tasks already built in.

01:48.840 --> 01:57.690
So we're going to make our own and I'm going to put this in ability system slash ability tasks and I'm

01:57.690 --> 02:03.120
going to name this target data under mouse.

02:03.120 --> 02:10.110
So this ability task will be concerned with getting data related to that hit results under the mouse

02:10.110 --> 02:10.950
cursor.

02:10.980 --> 02:18.390
Now notice we're calling this target data under mouse and gas target data means something specific.

02:18.390 --> 02:23.430
So this is a foreshadowing to a topic that we're going to get into very shortly.

02:23.430 --> 02:26.820
But for now, let's just create our ability task.

02:27.030 --> 02:33.780
I'm going to go ahead and close the editor and we'll let Ryder populate these folders here.

02:33.780 --> 02:39.760
And I'm going to keep Aura Projectile spell open, but I'm going to open target data under Mouse.

02:39.760 --> 02:42.580
There's the CP and here's the header file.

02:42.700 --> 02:43.450
Okay.

02:43.450 --> 02:50.980
Now we already took a look at play montage and wait and we saw that it had this static function that

02:50.980 --> 02:55.210
created an instance of this particular class and returned it.

02:55.330 --> 02:57.700
We're going to follow that pattern here.

02:57.700 --> 03:01.630
So for target data under Mouse, we're going to make a static function.

03:01.630 --> 03:03.040
It's going to be public.

03:03.040 --> 03:10.420
So here's our public section and we're going to make a static function that returns a new target data

03:10.450 --> 03:12.370
under mouse pointer.

03:12.370 --> 03:19.120
So we're going to call this function create target data under mouse.

03:19.660 --> 03:28.180
Now this function is going to receive the owning gameplay ability and that's pretty typical for these

03:28.180 --> 03:31.510
ability tasks they take in a new gameplay ability.

03:33.140 --> 03:34.730
And that's a pointer.

03:34.730 --> 03:37.070
And we call this owning ability.

03:37.190 --> 03:45.140
And whenever we call this function from within a gameplay ability, this owning ability parameter,

03:45.140 --> 03:50.470
we would like passed in by default and we would like it to be the self.

03:50.480 --> 03:52.730
In other words, the this pointer.

03:52.730 --> 03:54.530
But in blueprint it's called self.

03:54.530 --> 03:59.660
That's the current ability that's running this gameplay task.

03:59.660 --> 04:05.660
So we're going to have a new function macro with a number of specifiers here.

04:05.900 --> 04:08.960
So for one, it's going to be blueprint callable.

04:09.140 --> 04:11.750
Two, it's going to have a category.

04:11.750 --> 04:17.480
And for the category we're going to put it in ability pipe symbol tasks.

04:17.480 --> 04:19.250
So it's an ability task.

04:19.700 --> 04:27.620
Now in order to make this owning ability default to the self, we're going to use the meta specifiers.

04:28.790 --> 04:35.300
So meta equals and a new set of parentheses and we're going to default to self, but we're also going

04:35.300 --> 04:43.550
to hide the pin for owning ability so we can use hide pin equals and we specify owning ability.

04:45.120 --> 04:50.550
We also use default to self specifying owning ability.

04:51.700 --> 04:56.470
So by default it'll be defaulted to the self.

04:56.740 --> 05:00.470
And this function is internal.

05:00.490 --> 05:00.910
Right.

05:00.910 --> 05:07.050
We're exposing this to the event graph, but this is a special internal function.

05:07.060 --> 05:12.220
It's really just a factory that creates an instance of this task and returns it.

05:12.370 --> 05:19.870
So what we're going to do in the meta parentheses here is we're going to say blueprint internal use

05:19.870 --> 05:22.480
only equals true.

05:22.930 --> 05:26.860
Now, this is called create target data under mouse.

05:26.920 --> 05:34.060
If we want our blueprint node to have a different name, we can use a display name here in the meta

05:34.060 --> 05:35.080
parentheses.

05:35.110 --> 05:36.130
Let's go ahead and do that.

05:36.130 --> 05:38.680
Let's say display name.

05:40.550 --> 05:48.770
And that'll be equal to I'll put a comma after the quotes and we'll say target data under mouse.

05:49.070 --> 05:51.320
So now there will be a display name as well.

05:51.350 --> 05:54.290
So lots of new function specifiers here.

05:54.320 --> 05:56.090
That's pretty typical for these.

05:56.390 --> 05:59.960
So let's go ahead and implement the function.

06:00.700 --> 06:02.620
Create a definition for it here.

06:03.250 --> 06:06.010
And here's what we typically do.

06:06.040 --> 06:10.480
We create a new object of type U target data under mouse.

06:10.570 --> 06:12.610
So I'm going to copy this.

06:12.700 --> 06:16.510
Type paste it there and we can call it anything.

06:16.510 --> 06:18.190
It's a local pointer variable.

06:18.190 --> 06:26.380
We're going to call this my obj for object and to create a new ability task, we use new ability task.

06:26.410 --> 06:27.520
It's a template.

06:27.520 --> 06:28.870
It requires the type.

06:28.870 --> 06:32.200
We're going to make a new target data under mouse.

06:32.500 --> 06:40.390
And when we create a new one of these, it's going to require the gameplay ability that owns it.

06:40.390 --> 06:42.990
So we pass in the owning ability here.

06:43.000 --> 06:45.250
Now the name is optional.

06:45.250 --> 06:48.730
It defaults to an empty F name, so we're just going to leave it out.

06:48.730 --> 06:56.230
And now that we've created a new object, we can simply return it here, return my obj.

06:56.500 --> 07:04.430
Now, if we wanted to, we could set any number of variables on our target data under mouse and we could

07:04.430 --> 07:11.690
make this function here, take in any number of input parameters and we could get those passed in from

07:11.690 --> 07:17.540
the blueprint node and we can set those values right here on this object.

07:17.660 --> 07:21.830
I'm just going to have none so we can see what this looks like.

07:21.830 --> 07:25.910
If we attempt to create one of these from within our ability.

07:26.000 --> 07:32.150
So why don't we go ahead and compile and launch the editor and try to create a target data under mouse

07:32.150 --> 07:34.700
node in our gameplay ability?

07:36.670 --> 07:42.370
Okay, so let's get that game play ability open and right at the beginning, as soon as we activate

07:42.370 --> 07:52.240
the ability, I'm going to right click right here and type in target data under mouse, it's under ability

07:52.270 --> 07:53.320
tasks.

07:53.320 --> 07:54.160
So here it is.

07:54.160 --> 07:57.930
Let's click on that and it's pretty bare, right?

07:57.940 --> 08:00.010
But notice it has the little clock right there.

08:00.010 --> 08:03.940
That means it's a latent node or an asynchronous node.

08:04.060 --> 08:12.880
Now all it does so far is just return the instance of the target data under mouse object.

08:12.880 --> 08:14.020
That's all it does.

08:14.020 --> 08:16.510
And we can't really do much with that, can we?

08:16.510 --> 08:18.670
Because it's a pretty empty class.

08:18.700 --> 08:21.910
We can get its name, we can call get object name.

08:22.690 --> 08:24.800
And we can print it to the screen.

08:24.820 --> 08:27.830
That's pretty much the only thing we can do.

08:27.850 --> 08:29.930
So let's just do it.

08:29.950 --> 08:35.110
Print string, passing in that name, and let's go ahead and just click.

08:35.110 --> 08:38.110
And it's a target data under mouse object.

08:38.620 --> 08:40.590
Okay, so that's pretty boring.

08:40.600 --> 08:43.210
But what is this task supposed to do?

08:43.240 --> 08:46.180
It's supposed to get the target data under the mouse, right?

08:46.180 --> 08:48.100
So I'll go ahead and hook that up.

08:48.100 --> 08:50.620
But we need this to return something.

08:50.620 --> 08:53.230
We need it to get some data.

08:53.350 --> 08:55.690
So let's continue our work on this.

08:55.690 --> 09:03.340
I'm going to close and save all, and this is now an asynchronous blueprint node, which means it can

09:03.340 --> 09:06.370
have multiple output execution pins.

09:06.370 --> 09:12.490
And the way that we create those multiple output execution pins is by broadcasting delegates.

09:12.490 --> 09:19.480
So any output execution pin needs to exist as a delegate variable on this class.

09:19.480 --> 09:23.980
So we can create a new delegate, we can declare one up here.

09:23.990 --> 09:25.970
So I'm going to declare one.

09:25.970 --> 09:31.910
I'm going to use declare dynamic multicast.

09:33.440 --> 09:42.860
Delegate and I'm going to use one param because I'd like to broadcast the value of the mouse cursor

09:42.860 --> 09:43.730
location.

09:43.730 --> 09:45.050
Just an f vector.

09:45.050 --> 09:45.830
Why not?

09:46.010 --> 09:52.700
I'm going to call this delegate f mouse target data delegate.

09:52.730 --> 10:02.000
We could also call it actually signature for the type and we're going to have it broadcast a const F

10:02.000 --> 10:07.250
vector called data and we'll make a variable of this type.

10:07.250 --> 10:13.040
It's going to be right here in the public section and we're going to call it valid data, and we'll

10:13.040 --> 10:16.370
make this a new property with blueprint.

10:16.370 --> 10:19.850
Assignable, not blueprint callable blueprint, assignable.

10:19.850 --> 10:25.520
And this will now become an output execution pin on the node.

10:25.760 --> 10:29.990
So now that we have this delegate, let's just compile and run the engine.

10:29.990 --> 10:32.510
I want to see how this changes the node.

10:33.510 --> 10:35.880
And it looks like I have a typo.

10:35.910 --> 10:38.070
I forgot a comma.

10:38.070 --> 10:43.810
So these types need to be separated from the name of that parameter with a comma.

10:43.830 --> 10:45.840
For dynamic multicast delegates.

10:45.870 --> 10:48.390
Okay, now let's compile and launch.

10:49.890 --> 10:50.430
Okay.

10:50.430 --> 10:52.050
Opening our ability.

10:52.080 --> 10:53.610
Now look at this.

10:53.640 --> 11:01.440
Not only does our node have more stuff on it, it has a valid data and it also has this data which is

11:01.440 --> 11:02.460
an F vector.

11:02.460 --> 11:04.500
It's a vector type by reference.

11:04.530 --> 11:05.580
Perfect.

11:05.610 --> 11:08.100
Now, this is never going to be executed.

11:08.100 --> 11:08.460
Why?

11:08.490 --> 11:14.190
Because the only way to execute this is to broadcast this delegate.

11:14.190 --> 11:16.110
That's how these get executed.

11:16.110 --> 11:17.310
Kind of cool, right?

11:17.370 --> 11:25.500
So why don't we broadcast a value As soon as we broadcast valid data, then data will have some valid

11:25.500 --> 11:26.100
data.

11:26.130 --> 11:34.860
So the last thing I'd like to do in this video is for valid data to be broadcast and for data to give

11:34.860 --> 11:37.170
me the location under the mouse.

11:37.290 --> 11:39.810
Now I'm going to close the editor saving all.

11:39.810 --> 11:47.910
And in order to do that, we have to override the ability tasks, activate function, and as soon as

11:47.910 --> 11:52.330
this node is executed, ID activate will be called.

11:52.360 --> 11:57.280
Now this is a private function, so we'll make a private section and this is virtual.

11:57.280 --> 12:01.810
We're going to say virtual void activate override.

12:01.900 --> 12:10.030
And here in Activate, let's generate the definition and we don't have to call super Activate because

12:10.030 --> 12:16.780
if we did that would call the ability tasks activate and if we go to the ability task by the way here's

12:16.780 --> 12:18.580
the new ability task.

12:19.030 --> 12:20.770
If we find activate.

12:22.270 --> 12:24.490
If we search for it, it won't be there.

12:24.490 --> 12:28.840
But if we go all the way into the gameplay task class.

12:31.910 --> 12:34.520
Here's virtual void activate.

12:34.550 --> 12:39.680
So as you can see, it's not even overridden in ability task.

12:39.710 --> 12:48.980
Now here in gameplay task CP if we search for Activate, we'll see here that it just does you vlog.

12:49.010 --> 12:49.970
Vlog.

12:50.120 --> 12:53.210
Basically performing a log and nothing else.

12:53.210 --> 12:55.220
So we really we don't care about that.

12:55.250 --> 12:59.030
Go ahead and call super if you want to, but it's not going to do much.

12:59.030 --> 13:01.160
So I'm going to close gameplay task.

13:01.190 --> 13:06.170
I'm going to close ability task and back to our class here is Activate.

13:06.650 --> 13:12.680
Now we just want to get data and broadcast our delegate valid data.

13:12.680 --> 13:19.280
So once we get the mouse hit location under the mouse and broadcast it, then we can go back into our

13:19.280 --> 13:24.050
blueprint and see if it's working by drawing a debug sphere or something like that.

13:24.050 --> 13:26.930
So this is going to be your quest.

13:27.440 --> 13:31.440
I'd like you to get that valid data and broadcast it.

13:31.440 --> 13:36.420
So this is going to involve getting the location under the mouse cursor.

13:36.450 --> 13:38.790
There should be something you know how to do.

13:38.790 --> 13:46.920
And once you get that broadcast, that valid data delegate and from within your ability, get that data

13:46.920 --> 13:50.040
and draw the debug sphere at the location.

13:50.040 --> 13:52.920
So do that from within our firebolt ability.

13:53.100 --> 13:56.580
So pause the video and conquer this quest now.

13:59.270 --> 14:00.050
All right.

14:00.050 --> 14:05.660
So from here in Activate, we need to figure out how to get that player controller.

14:05.690 --> 14:08.930
That's how we get the hit results under the mouse cursor.

14:09.230 --> 14:14.870
So we need to figure out how we can get that from within the activate function.

14:14.870 --> 14:21.770
So this might have been a bit of a stumping point for you, but remember, ability tasks know which

14:21.800 --> 14:23.750
ability they belong to.

14:23.870 --> 14:33.650
In fact, they have an ability member variable and from ability we can access the actor info with get

14:33.650 --> 14:36.320
current actor info.

14:36.590 --> 14:44.720
Now get current actor info returns gameplay ability actor info and that has a number of variables on

14:44.720 --> 14:48.860
it, including the player controller so we can get it from that.

14:48.890 --> 14:56.780
Now the player controller here is a weak object pointer, so we're going to need to call, get on that.

14:56.780 --> 15:03.570
So this is how we can get the player controller and we can store this in an a player controller pointer.

15:03.960 --> 15:05.580
And I'm just going to call it PC.

15:06.060 --> 15:11.010
Now we can call get hit result on the cursor, which takes an F hit result.

15:11.010 --> 15:17.730
So this will be called, we'll call it cursor hit and we'll take the player controller and call get

15:17.760 --> 15:23.010
hit Results under cursor specifying a E collision channel.

15:23.760 --> 15:26.040
I'm just going to trace against visibility.

15:26.070 --> 15:28.380
We're going to not trace complex.

15:28.380 --> 15:32.940
We're going to trace only against simple collision and pass in that cursor hit.

15:33.570 --> 15:36.360
So now we should have a hit result.

15:36.390 --> 15:42.870
So now all that's left is to broadcast that data, the location of this hit result.

15:43.020 --> 15:52.350
And our delegate is valid data so we can call broadcast on it using our cursor hit dot location or impact

15:52.350 --> 15:53.010
point.

15:53.340 --> 15:54.900
Either of those will work.

15:55.050 --> 16:01.950
So as soon as we activate this ability, then we're going to broadcast that delegate, which means that

16:01.950 --> 16:06.110
valid data execution pin will be executed.

16:06.120 --> 16:13.320
So it just so happens that as soon as we activate the ability, that valid data pin will be executed.

16:13.320 --> 16:15.490
But it doesn't have to be right away.

16:15.510 --> 16:17.220
This is an asynchronous task.

16:17.220 --> 16:24.160
So depending on the gameplay mechanics for some ability tasks we may wish to broadcast those delegates

16:24.190 --> 16:25.450
later in time.

16:25.660 --> 16:28.680
But for this case, we're broadcasting right away.

16:28.690 --> 16:30.610
So let's run in debug mode.

16:33.740 --> 16:36.260
And we'll open up our ability.

16:36.290 --> 16:43.490
Here's target data under mouse and we know that as soon as we reach this node, activate will be called

16:43.490 --> 16:46.190
and valid data will be broadcast right away.

16:46.190 --> 16:48.470
So we're not going to use this node.

16:48.470 --> 16:54.260
We're going to use valid data because as soon as valid data is broadcast, then we should have some

16:54.260 --> 16:57.260
valid data in that data vector.

16:57.260 --> 17:03.230
So I'm going to draw a debug sphere or debug box or anything else really, right?

17:03.410 --> 17:04.850
I'm going to do a sphere.

17:07.340 --> 17:12.950
So I'm going to move these up out of the way and we're going to draw it at the location of data.

17:13.800 --> 17:17.070
I'll give it a radius of 100 line color white.

17:17.070 --> 17:17.790
That's fine.

17:17.790 --> 17:18.420
For duration.

17:18.420 --> 17:23.430
I'll give it 20s and we can test this out.

17:24.650 --> 17:25.160
All right.

17:25.160 --> 17:27.620
Saving all pressing play.

17:27.650 --> 17:28.730
Clicking.

17:29.370 --> 17:32.700
And actually, I have to click on an enemy, right?

17:33.320 --> 17:35.180
In order to activate it.

17:35.180 --> 17:39.560
And I can only activate it once unless I end the ability.

17:43.070 --> 17:46.400
Now I can activate it as many times as I want.

17:47.060 --> 17:50.630
And as long as I'm hovering over an enemy, then boom.

17:52.220 --> 17:55.580
We're getting our target data, so this is great.

17:55.580 --> 18:01.430
But remember, we mentioned we're going to see its limitations, particularly when it comes to multiplayer.

18:01.490 --> 18:07.100
So if I increase the number of players to two and press play, let's see what happens.

18:07.100 --> 18:12.620
If I do this on a client, I'm going to click and look at this on the client.

18:12.620 --> 18:14.270
I clicked way over here.

18:14.270 --> 18:21.500
It's probably hard to see, but I clicked way over here on an enemy and I got my debug sphere in the

18:21.500 --> 18:22.460
correct location.

18:22.460 --> 18:28.460
I can do it for all of these enemies here and it looks great on the client locally, but look at the

18:28.460 --> 18:30.170
server on the server.

18:30.170 --> 18:36.770
It's just showing the debug sphere right here for some reason and I have the sneaking suspicion that

18:36.770 --> 18:43.310
that is the world origin and that would mean that data just has all zeros in it.

18:43.340 --> 18:45.050
It's not being set.

18:45.320 --> 18:47.720
So that's a problem right now.

18:47.720 --> 18:53.550
It makes sense that the server wouldn't know where we're clicking because that's something we're doing

18:53.550 --> 18:54.420
locally.

18:54.450 --> 18:59.250
That's something we're doing here on the client and only the client knows where its mouse cursor is

18:59.250 --> 19:03.090
because that's not data that's being sent up to the server.

19:03.540 --> 19:09.420
If we want the server to know where we're clicking, we have to tell the server where we're clicking.

19:09.420 --> 19:14.250
And so that's going to involve more concepts that we have to learn.

19:14.370 --> 19:22.710
So we've seen the limitations of our new ability task and how yes, we can get valid data and yes,

19:22.710 --> 19:29.550
we can draw a debug sphere for it locally, but the server does not have valid data.

19:29.550 --> 19:33.630
It's not getting that specific piece of information.

19:33.630 --> 19:34.380
Right.

19:34.380 --> 19:36.870
So a couple things are happening here.

19:36.870 --> 19:44.280
Activate ability is being executed locally on the client and because abilities are replicated, then

19:44.280 --> 19:47.880
activate ability is being called on the server as well.

19:48.060 --> 19:55.560
But on the server we're getting this delegate broadcast even though we don't really know where that

19:55.560 --> 19:56.940
mouse cursor is.

19:57.210 --> 20:05.220
So our next steps are to figure out how we can get data from the client up to the server.

20:05.220 --> 20:10.440
And specifically we want that mouse cursor location sent up to the server.

20:10.440 --> 20:14.990
How do we do that and how do we do it in a way that will work reliably?

20:15.000 --> 20:16.940
That's what we're going to do next.

20:16.950 --> 20:18.330
So I'll see you soon.
