WEBVTT

00:07.470 --> 00:08.730
Welcome back.

00:08.730 --> 00:14.730
Now that we're applying damage effect well we're not applying it, but our apply damage effect function

00:14.730 --> 00:18.870
is now setting our radial damage parameters.

00:18.870 --> 00:25.500
We can harvest these at any point along the damage pipeline where we can access the context handle.

00:25.500 --> 00:29.100
And I'd like to access it from within the exec calc.

00:29.100 --> 00:37.620
So I'm going to close all tabs and go into my exec calc and Ability system exec calc damage right here.

00:37.980 --> 00:45.120
And here's where all the magic is happening with damage, where looping through all damage types to

00:45.120 --> 00:49.740
resistances that map that exists in or a gameplay tags.

00:49.740 --> 00:51.480
And what are we doing?

00:51.480 --> 00:59.550
Well, we're getting our resistance that corresponds to that damage type and where decreasing the damage

00:59.550 --> 01:01.470
based on that resistance.

01:01.970 --> 01:03.320
So that's all fine.

01:03.320 --> 01:04.490
That's all good.

01:04.490 --> 01:13.190
But after we've done that, what we need to do with that damage is determine if we have radial damage.

01:13.190 --> 01:20.750
Because if this is radial damage, then we need to scale it down based on the distance of the victim

01:20.750 --> 01:23.870
from the origin of damage.

01:23.870 --> 01:31.490
So at this point, after we've checked and reduced our damage based on resistances, we can then see

01:31.490 --> 01:38.840
if we need to lower it even more based on the distance, if it's radial, and we can do this per damage

01:38.840 --> 01:39.770
type.

01:39.770 --> 01:44.930
So if this is radial damage, we're going to be scaling the damage down.

01:44.930 --> 01:50.810
Now if we're doing this per damage type then we have a damage type value.

01:50.810 --> 01:56.390
And we can scale that damage type value down before adding it to the damage total.

01:56.390 --> 02:04.850
So before incrementing damage for this given damage type but after we've taken resistances into account,

02:04.850 --> 02:08.090
we can then check to see if we need to apply radial damage.

02:08.090 --> 02:09.800
That's the order I'm going to do it in.

02:09.800 --> 02:13.550
You could do it before taking resistances into account.

02:13.550 --> 02:14.690
It's up to you.

02:14.690 --> 02:16.130
So how are we going to do it?

02:16.130 --> 02:18.200
Well, we need to check our context.

02:18.200 --> 02:21.680
We need our gameplay effect context, don't we?

02:21.830 --> 02:29.030
Now if we search here for context, we'll see that we have f gameplay effect, context handle spec dot

02:29.030 --> 02:30.170
get context.

02:30.170 --> 02:32.540
So here's our effect context handle.

02:32.540 --> 02:33.650
It's right there.

02:33.650 --> 02:34.850
And we're getting it.

02:34.850 --> 02:38.090
It looks like below where we're calculating damage.

02:38.090 --> 02:44.180
But that's not to say that we can't just get it higher up before we need it so that it's in scope.

02:44.270 --> 02:50.780
So I'm going to control X to cut it and move it up towards the beginning of the function way up towards

02:50.780 --> 02:51.470
the top.

02:51.470 --> 02:57.110
We'll just do it as soon as we have the spec right here, we can get our gameplay effect context handle

02:57.110 --> 02:57.770
then.

02:58.360 --> 03:05.440
And now when we're checking damage, we can check that context handle to see if we have radial damage.

03:05.470 --> 03:16.600
So I'm going to say if you aura ability system library is radial damage passing in that effect context

03:16.600 --> 03:17.350
handle.

03:18.300 --> 03:22.650
If it is radial damage, then what are we going to do?

03:22.680 --> 03:29.250
You see, we could apply radial damage with falloff using the U gameplay statics function, but that's

03:29.250 --> 03:35.190
just going to result in that actor that we damage having its take damage function called.

03:35.190 --> 03:40.110
But how are we going to know the result of that once that happens?

03:40.140 --> 03:42.810
Well, that's what delegates are good for.

03:42.870 --> 03:47.490
If we get a delegate we can bind to, we can even bind a lambda to it right here.

03:47.490 --> 03:51.090
Then we can call apply radial damage with falloff.

03:51.090 --> 03:55.920
And in the character's take damage function we could broadcast the final damage amount.

03:55.920 --> 03:59.310
So it's kind of a roundabout way, but it's also a clever way.

03:59.310 --> 04:03.330
So I'm going to map this out because that might have sounded a little confusing.

04:03.330 --> 04:05.490
First I'm going to say one.

04:05.490 --> 04:06.870
Let's put some pseudo code here.

04:06.870 --> 04:15.630
One we're going to override take damage, and we'll do this in the base character class in our character

04:15.630 --> 04:17.820
base.

04:18.450 --> 04:33.030
Two we're going to create delegates and we can call it on damage delegate and broadcast damage received

04:33.030 --> 04:34.440
and take damage.

04:36.910 --> 04:43.420
Three we're going to bind to on damage delegate on the.

04:43.420 --> 04:44.830
We'll call it the victim.

04:46.460 --> 04:47.390
Here.

04:49.120 --> 04:50.170
For?

04:50.470 --> 04:50.920
What?

04:50.920 --> 04:51.940
Are we going to bind it?

04:51.940 --> 04:54.220
Let's just say we're going to bind a lambda.

04:55.150 --> 05:02.320
And then in four we'll say call apply radial damage with falloff.

05:03.570 --> 05:12.360
That's you gameplay statics you gameplay statics apply radial damage with falloff to cause damage and

05:12.360 --> 05:13.380
parentheses.

05:13.380 --> 05:20.940
This will result in take damage being called on the victim.

05:22.630 --> 05:28.210
Which will then broadcast on damage delegate.

05:29.760 --> 05:31.140
And five.

05:31.890 --> 05:42.780
In Lambda here in our response, set damage type value to the damage received from the broadcast.

05:44.070 --> 05:48.270
So now these steps are planned out and it's a little bit more clear what to do.

05:48.270 --> 05:49.500
And we have a list.

05:49.590 --> 05:52.290
So this is how we're going to implement this.

05:52.350 --> 05:58.980
Now how are we going to bind to that delegate from right here without say casting to or a character

05:58.980 --> 06:06.390
base, which is a practice that I tend to shy away from because it makes the exact calc very specific.

06:06.390 --> 06:13.770
I like to use interface functions instead, so we're going to probably end up using an interface, but

06:13.770 --> 06:20.370
it's nice when we have a set of steps like this, because then we can just follow the steps and it makes

06:20.370 --> 06:22.020
the task a lot easier.

06:22.020 --> 06:24.180
So let's take this one step at a time.

06:24.180 --> 06:27.300
Let's override take damage in or a character base.

06:27.890 --> 06:34.400
So we'll go ahead and open our public folder, go to Character Get or a character base open.

06:34.400 --> 06:38.300
And we'll just do it right here in the public section.

06:38.300 --> 06:42.350
Virtual void take damage.

06:43.280 --> 06:47.780
Now it's not auto completing for me because it's actually not a void function.

06:47.780 --> 06:49.550
Take damage returns a float.

06:49.550 --> 06:56.480
That's also one of the reasons why it's so useful, because whatever take damage receives as a result

06:56.480 --> 07:01.850
of gameplay statics calling it, or anything else in the damage system it receives, the amount of damage

07:01.850 --> 07:08.840
taken, and then whatever we decide to return here is returned, so we can return that damage as well.

07:08.840 --> 07:12.020
So take damage takes in a float.

07:12.020 --> 07:15.770
In fact, we should be able to get auto complete to work for us.

07:15.770 --> 07:17.930
Now I'm just going to type it again.

07:17.930 --> 07:19.280
Virtual float.

07:20.480 --> 07:21.440
Take damage.

07:21.440 --> 07:22.250
There we go.

07:22.340 --> 07:24.170
Now writer auto completes it.

07:24.170 --> 07:25.040
So take damage.

07:25.040 --> 07:32.540
Takes in damage amount as a float and if damage event const called damage event and a controller called

07:32.540 --> 07:38.000
instigator event instigator rather and an a actor called damage causer.

07:38.300 --> 07:43.130
So with that we can go ahead and generate a definition.

07:43.130 --> 07:46.310
And now we've overridden take damage.

07:47.450 --> 07:48.020
Perfect.

07:48.020 --> 07:49.310
That was step one.

07:49.310 --> 07:50.990
Let's go back and look at our step.

07:50.990 --> 07:52.580
We can add a check mark.

07:52.580 --> 07:55.970
I'll just use an asterisk to say we're done with this step.

07:55.970 --> 08:02.510
Next create a delegate on damage delegate broadcast damage received and take damage.

08:02.510 --> 08:08.210
So we need a delegate so we can go back to our character base and we can declare a delegate.

08:08.210 --> 08:13.820
We can go all the way up to the top above our includes and just declare one here, and I'm just going

08:13.820 --> 08:15.200
to make it multicast.

08:15.200 --> 08:18.410
I only plan on binding to it and C plus plus.

08:19.280 --> 08:21.170
So declare multicast delegate.

08:22.750 --> 08:28.930
And it needs to broadcast one param, which is going to be the damage amount.

08:28.930 --> 08:33.460
So I'm going to call this F on damage signature.

08:33.940 --> 08:40.540
It's going to broadcast a float and I'm going to just put here damage amount.

08:42.170 --> 08:44.630
So it's clear that that's what that float is for.

08:44.660 --> 08:48.590
Then we can add a public variable here for this.

08:48.590 --> 08:53.240
I'll put it down here with our delegates and I'll call this on damage delegate.

08:53.780 --> 08:55.640
And then let's look at our list.

08:55.640 --> 09:01.400
It says create the damage delegate on damage delegate broadcast damage received and take damage.

09:01.400 --> 09:10.640
So here in our character base, what I'm going to do is after super has calculated take damage, I'm

09:10.640 --> 09:13.490
going to store that in a float called Damage Taken.

09:14.600 --> 09:22.010
And I'm going to broadcast that on damage delegate dot broadcast damage taken.

09:24.560 --> 09:27.200
And then this function can return damage taken.

09:27.890 --> 09:29.210
So pretty simple.

09:29.210 --> 09:33.770
And this can even be, you guessed it, a cost.

09:33.770 --> 09:38.450
So take damage as simple, it just takes damage and broadcast the delegate.

09:38.450 --> 09:42.710
So now in exact calc damage that step is done.

09:42.710 --> 09:44.180
We can go on to the next one.

09:44.180 --> 09:47.450
Bind a lambda to on damage, delegate on the victim here.

09:47.450 --> 09:52.490
And this is where interfaces come in, because we don't want to have to cast to or a character based

09:52.490 --> 09:53.960
just to get that delegate.

09:53.960 --> 09:58.220
I'd like a function in the combat interface that returns it.

09:58.220 --> 10:03.260
So let's go to combat interface and Interaction and we'll create one.

10:03.260 --> 10:09.110
And just like our other interface functions that return a delegate, we should return a reference.

10:09.110 --> 10:13.100
So we return the actual delegate without making a copy of it.

10:13.340 --> 10:20.690
So I'm going to just make a pure virtual function called f on.

10:21.410 --> 10:22.760
Damage signature.

10:22.760 --> 10:24.320
And you know what?

10:24.320 --> 10:32.540
I'm just now realizing that I declared this in or a character base if I use it here as a reference.

10:33.970 --> 10:36.280
I'm going to have to forward declare it, which I can.

10:36.280 --> 10:37.960
Actually, it's a reference.

10:37.960 --> 10:45.670
I can forward declare it here and I'm going to call this function get on damage signature.

10:47.690 --> 10:49.460
And this will be pure virtual.

10:49.460 --> 10:56.390
That should work and I can forward declare it up at the top, since that's the convention I've been

10:56.390 --> 11:00.200
using for this project, and it's good to stick to conventions.

11:00.200 --> 11:01.190
So we'll do that.

11:01.190 --> 11:03.320
And now we don't need to forward declare there.

11:03.770 --> 11:08.750
And now we can override F on damage signature and or a character base.

11:08.750 --> 11:09.800
Let's do that.

11:09.800 --> 11:21.230
So right here virtual F on damage signature ref get on damage signature override.

11:22.400 --> 11:22.730
Okay.

11:22.730 --> 11:25.490
So we're not going to be able to override this.

11:25.490 --> 11:33.500
And that's because we're overriding a function that has an incomplete type over in the combat interface.

11:33.500 --> 11:40.730
To make this work, what we should do is we should instead declare the delegate.

11:41.500 --> 11:43.060
In the combat interface.

11:44.440 --> 11:51.160
So I'm going to move that declaration into the combat interface and remove that forward declaration

11:51.160 --> 11:51.700
here.

11:52.750 --> 11:57.190
And it's not going to need that forward declaration here.

11:57.190 --> 12:01.060
Instead, we're going to use the forward declaration in or a character base.

12:02.210 --> 12:03.710
So we'll say struct.

12:04.780 --> 12:08.920
F on damage signature.

12:18.470 --> 12:24.980
So we're not actually going to even need to forward declare it here in our character base.

12:25.640 --> 12:34.160
And with that, we are now overriding a valid function and we can go ahead and provide the definition.

12:34.160 --> 12:40.100
By the way, if you were wondering if you could just define these on the same line like this return

12:40.100 --> 12:41.510
on damage delegate.

12:41.510 --> 12:42.770
Sure you could.

12:42.770 --> 12:43.550
Of course.

12:43.550 --> 12:47.600
Now it looks weird having this one and the others are not doing it.

12:47.600 --> 12:53.570
So rather than do that, I'm just going to be consistent and we'll return it here.

12:53.570 --> 12:54.560
Return.

12:56.110 --> 12:57.640
On damage.

12:57.670 --> 12:58.690
Delegate.

12:58.840 --> 12:59.380
Okay.

12:59.380 --> 13:03.250
So now our our character base is implementing that.

13:03.250 --> 13:06.340
And what we can do in exec calc damage is we can do.

13:06.340 --> 13:11.680
Step three bind a lambda to on damage delegate on the victim here.

13:11.740 --> 13:13.390
That's going to be right here.

13:13.390 --> 13:15.850
So how are we going to do that.

13:15.940 --> 13:18.820
Well we should have access to the victim.

13:19.060 --> 13:22.150
So if we scroll up what is our victim.

13:22.150 --> 13:23.950
Well that's going to be the target.

13:23.950 --> 13:26.560
And we have the target avatar right here.

13:26.710 --> 13:28.420
That's pretty convenient.

13:28.420 --> 13:31.480
This is the thing getting damaged, right?

13:31.480 --> 13:33.760
The target here in Exec Calc.

13:33.760 --> 13:39.250
So what we can do is we can cast the target avatar to our interface.

13:39.250 --> 13:41.470
We can say I combat interface.

13:41.500 --> 13:42.820
Combat interface.

13:42.820 --> 13:45.730
As long as we haven't used combat interface already.

13:45.820 --> 13:47.710
Let me just search for it.

13:49.680 --> 13:53.820
Okay, so we're checking if Source Avatar implements it up here.

13:55.410 --> 13:58.740
But this is actually the only place where we're casting to it.

13:58.740 --> 14:00.150
So this is fine.

14:00.150 --> 14:02.010
So we're going to cast to it.

14:03.180 --> 14:06.660
Cast to AI combat interface.

14:06.690 --> 14:07.380
Casting.

14:07.410 --> 14:07.860
Target.

14:07.860 --> 14:08.760
Avatar.

14:08.880 --> 14:10.440
And we'll go ahead.

14:10.440 --> 14:12.600
Wrap that in an if statement.

14:14.510 --> 14:23.330
And then we can take our combat interface and we can call the function get on damage signature.

14:23.330 --> 14:25.130
Now this returns that delegate.

14:25.130 --> 14:26.840
So we can just bind to it.

14:26.840 --> 14:31.610
And I'd like to bind a lambda just like my steps here are telling me to do.

14:31.700 --> 14:32.390
So.

14:32.390 --> 14:34.100
For that I can use add lambda.

14:35.510 --> 14:37.460
And I can make my lambda here.

14:37.460 --> 14:40.940
Square parentheses squigglies.

14:40.940 --> 14:43.880
And what am I going to do in here?

14:43.910 --> 14:47.600
Well this delegate broadcast afloat the damage amount.

14:47.600 --> 14:53.210
So I'm going to go ahead and use a float damage amount as my input parameter.

14:53.210 --> 14:59.090
And all I need to do in this is set my damage type value.

15:01.500 --> 15:03.270
Equal to damage amount.

15:05.730 --> 15:11.970
Now I can't set damage type value unless it's captured and I can't capture it by value.

15:11.970 --> 15:13.980
I have to capture it by reference.

15:13.980 --> 15:18.690
So by the way, you can just put a ampersand in here.

15:18.690 --> 15:21.600
And now you're capturing everything in here by reference.

15:21.600 --> 15:27.390
So setting damage type value in here will set damage type value out here.

15:27.810 --> 15:29.070
Pretty nifty.

15:29.100 --> 15:36.000
Now we're not just overwriting damage type value and getting rid of the work we've done here for resistances.

15:36.000 --> 15:37.830
Why are we not doing that?

15:37.860 --> 15:45.030
Well because this all happens in response to the character's take damage function.

15:45.030 --> 15:53.700
And take damage is going to receive the amount of our damage type value, but after taking the radial

15:53.700 --> 15:55.440
damage distance into account.

15:55.440 --> 15:59.970
So it's going to start off with damage type value and then nerf it based on distance.

15:59.970 --> 16:01.200
How is it going to do that?

16:01.200 --> 16:04.770
Well, we have to call apply radial damage with falloff.

16:04.770 --> 16:05.670
That's our next step.

16:05.670 --> 16:07.560
So we've bound the lambda.

16:07.560 --> 16:09.930
We can check off that part of the list.

16:09.930 --> 16:12.690
And now we're going to call you gameplay statics.

16:12.690 --> 16:16.890
Apply radial damage with falloff to cause damage.

16:16.890 --> 16:22.680
This will result in take damage being called on the victim, which will then broadcast the on damage

16:22.680 --> 16:25.020
delegate which we have lambda bound to here.

16:25.380 --> 16:29.820
And then in Lambda set damage type value to the damage received from broadcast.

16:29.820 --> 16:33.990
So we actually jumped the gun here and we did that step a little early.

16:33.990 --> 16:35.880
Now we just need to call number four.

16:35.880 --> 16:44.100
So what we do here is after we've bound the lambda here after that if statement there we're going to

16:44.100 --> 16:46.830
call apply radial damage with falloff.

16:46.830 --> 16:50.130
That's a you gameplay statics function.

16:50.820 --> 16:54.270
And I'm going to go ahead and make that include happen.

16:54.270 --> 16:55.710
So I can get auto complete.

16:55.710 --> 16:58.440
So apply radial damage with falloff.

16:58.440 --> 17:00.870
And this takes a ton of parameters.

17:00.870 --> 17:02.880
We need a world context object.

17:02.880 --> 17:05.520
I'm just going to pass in the target avatar.

17:05.520 --> 17:07.560
We need the base damage amount.

17:07.560 --> 17:12.840
And that's why I said that damage type value isn't just thrown out the window.

17:12.870 --> 17:20.730
We're passing in damage type value to this function now because we have a ton of input parameters.

17:20.730 --> 17:23.340
Let's start getting these on their own lines here.

17:23.790 --> 17:27.090
And after damage type value we have a minimum damage.

17:27.090 --> 17:28.950
I'm just going to use zero.

17:28.980 --> 17:31.140
I mentioned earlier that I would.

17:31.140 --> 17:38.970
So if outside of the damage radius will actually not receive any damage outside of that damage outer

17:38.970 --> 17:40.020
radius, that is.

17:40.020 --> 17:41.700
Now we need the origin.

17:41.700 --> 17:46.530
And this is where our handy ability system library functions come in.

17:46.530 --> 17:53.940
We're going to call you or Ability system library get damage origin or get radial damage origin.

17:53.940 --> 18:00.300
And we have to pass in our effect context handle in addition to that.

18:00.300 --> 18:03.990
Next we have damage inner radius and damage outer radius.

18:03.990 --> 18:12.600
So back to our ability system blueprint library functions get radial damage inner radius passing in

18:12.600 --> 18:14.370
the effect context handle.

18:16.310 --> 18:18.140
Next is the outer radius.

18:18.140 --> 18:19.460
So we'll get that.

18:23.280 --> 18:24.810
So radial damage.

18:24.810 --> 18:27.930
Outer radius passing in the effect context handle.

18:28.020 --> 18:29.550
Now damage falloff.

18:29.550 --> 18:33.810
We've seen that we'll get a nice linear falloff if that's one.

18:33.810 --> 18:39.330
And a faster sharper falloff exponentially if it's larger than one.

18:39.720 --> 18:49.560
Now for damage type class we can just use you damage type static class just to satisfy that input.

18:50.490 --> 18:53.640
Now we need an array of ignore actors.

18:53.640 --> 18:58.890
And I'm not going to ignore any actors here, so I'll pass in an empty array.

19:00.510 --> 19:01.320
Of a actor.

19:01.320 --> 19:02.070
Pointers.

19:04.510 --> 19:06.160
Now for the damage causer.

19:06.160 --> 19:07.660
We have a source actor.

19:09.450 --> 19:11.940
And that is not exactly what I wanted.

19:11.940 --> 19:14.490
Source actor is what I wanted.

19:16.880 --> 19:20.150
Oh, and it's auto completing because there is no source actor.

19:20.150 --> 19:21.740
It's called Source Avatar.

19:21.740 --> 19:25.820
So just like we have a target avatar, we have a source avatar.

19:25.820 --> 19:27.170
I'm going to pass that in.

19:27.170 --> 19:31.250
And finally an instigated by controller.

19:31.250 --> 19:35.780
Well, if we wanted to pass in a controller and use it, I don't have any use for it.

19:35.780 --> 19:45.050
But we could go on and say CoStar, source Avatar, and target avatar to characters.

19:45.050 --> 19:46.640
I don't think I need to do that.

19:46.640 --> 19:48.680
I'm going to pass in a null pointer.

19:48.680 --> 19:50.120
I don't plan on using that.

19:50.120 --> 19:53.960
So with that we're calling Apply radial damage with falloff.

19:54.440 --> 19:55.790
Now here's the trick.

19:55.790 --> 19:57.620
It's like a sleight of hand trick.

19:57.620 --> 19:57.950
Right.

19:57.950 --> 20:00.980
Because what we're doing is we're being sneaky here.

20:00.980 --> 20:05.300
We're taking our target actor that's getting damaged.

20:05.300 --> 20:10.490
We're getting its combat interface and getting the on damage signature and binding a quick little lambda

20:10.490 --> 20:16.040
to it and saying, hey, whenever you broadcast this delegate, my lambda is going to respond and it's

20:16.040 --> 20:21.800
going to set my damage type value to the damage amount, and then it turns around and causes damage

20:21.800 --> 20:22.730
to that actor.

20:22.730 --> 20:23.210
Right.

20:23.210 --> 20:25.040
And this happens right away.

20:25.040 --> 20:25.550
Gameplay.

20:25.550 --> 20:31.190
Static says, hey, calculate radial damage with falloff, then apply damage.

20:31.190 --> 20:37.670
And then of course, this actor that we just bound a lambda to instantly gets take damage called and

20:37.670 --> 20:38.660
it broadcasts this.

20:38.660 --> 20:41.690
So it's kind of a funny little loop that happens right here.

20:41.690 --> 20:43.790
But it causes radial damage.

20:43.790 --> 20:44.630
Pretty cool right.

20:44.630 --> 20:47.270
So that's pretty amazing.

20:47.630 --> 20:54.800
So with that we have just completed that step in our radial damage capability.

20:54.800 --> 20:57.410
We've added radial damage to our pipeline.

20:57.410 --> 21:02.420
All we have to do is set those radial damage params and then we'll get radial damage.

21:02.420 --> 21:03.740
So pretty exciting.

21:03.740 --> 21:06.830
And we're going to go ahead and just compile this.

21:06.830 --> 21:12.050
And then we'll get all this working in the next video where we tie it all together and set our damage

21:12.050 --> 21:15.530
params for our arcane shards.

21:15.530 --> 21:18.110
Excellent job and I'll see you in the next video.
