WEBVTT

00:00.230 --> 00:02.360
Welcome to the next quest.

00:02.720 --> 00:05.930
In this quest, you're going to implement critical hits.

00:06.050 --> 00:12.440
Now, this means you're going to need to capture some attributes and determine whether the hit is critical.

00:12.470 --> 00:18.860
Now, you can use the critical hit chance for this and use critical hit resistance to reduce that effective

00:18.860 --> 00:19.800
chance.

00:19.820 --> 00:26.250
And if you get a critical hit, double the damage and add a critical hit bonus for critical hit damage.

00:26.270 --> 00:33.650
Now, if you want a bonus challenge, you can add a critical hit resistance coefficient and we have

00:33.650 --> 00:36.800
a curve table for our damage calculation coefficients.

00:36.800 --> 00:42.890
So if you feel so inclined, make that a parameter and then you can scale your critical hit resistance

00:42.890 --> 00:50.390
by a coefficient that changes based on level and you're going to have to decide whether these attributes

00:50.390 --> 00:53.050
are captured on the source or the target.

00:53.060 --> 00:58.370
So there are a few steps to this quest, but I think you're capable of handling it.

00:58.370 --> 01:02.940
So go ahead and pause the video and conquer this quest now.

01:05.800 --> 01:06.370
All right.

01:06.370 --> 01:11.920
I'm back in my exec calc damage class and I'm going to scroll up to the top because we're now going

01:11.920 --> 01:14.620
to need to capture a couple more attributes.

01:14.650 --> 01:20.410
Now for critical hit calculations, we obviously need our three critical hit attributes.

01:20.440 --> 01:22.360
We're going to need critical hit chance.

01:22.390 --> 01:25.860
Now, this is going to be captured from the source, obviously.

01:25.870 --> 01:33.580
So let's declare attribute capture Def and we'll pass in critical hit chance.

01:33.790 --> 01:38.140
And we're also going to add a define attribute capture def.

01:38.930 --> 01:48.320
So define attribute capture def and for s we're passing in you or an attribute set for P, that's the

01:48.320 --> 01:54.650
attribute that's going to be critical hit chance not def.

01:54.830 --> 02:01.370
We're going to capture critical hit chance from the source and we're not going to snapshot any of these.

02:01.400 --> 02:07.550
Now in addition to critical hit chance, we need critical hit resistance and critical hit damage.

02:07.550 --> 02:12.950
Let's go ahead and just add those macro calls for both of them.

02:12.950 --> 02:17.630
We have critical hit resistance and critical hit damage.

02:17.630 --> 02:25.040
And we'll make two more macro calls here in the constructor for a damage statics specifying critical

02:25.040 --> 02:26.270
hit resistance.

02:26.270 --> 02:30.620
Now critical hit resistance is going to be on the target, isn't it?

02:30.620 --> 02:34.460
And critical hit damage that should be from the source.

02:34.550 --> 02:37.490
And it looks like I have a typo.

02:37.520 --> 02:41.940
This should be critical hit damage not critical hit chance damage.

02:42.030 --> 02:44.250
So we'll go ahead and fix that.

02:44.250 --> 02:49.530
So it's very important to make sure that we have the right parameters in our capture def we want to

02:49.530 --> 02:54.480
capture from the target or the source, depending on what it is we're calculating.

02:54.480 --> 02:55.950
So that's very important.

02:55.950 --> 03:02.580
So now that we've defined these, we need to add these attributes to relevant attributes to capture.

03:03.030 --> 03:10.410
So I'm going to add three copies of this line and change the capture def first, we're going to have

03:10.410 --> 03:12.690
critical hit chance def.

03:12.690 --> 03:20.610
Next we'll have critical hit resistance def and then we'll have critical hit damage def.

03:20.640 --> 03:24.930
Now that we have those three, we know that we can capture those values.

03:25.020 --> 03:28.800
So let's do our critical hit calculation way down here.

03:28.800 --> 03:36.270
We want our out execution output down at the bottom and after we've just ignored a percentage of incoming

03:36.270 --> 03:39.390
damage, we can do critical hit calculations.

03:39.390 --> 03:47.460
Now we're going to make a float and I'm going to call this source critical hit chance and initialize

03:47.460 --> 03:48.420
it to zero.

03:48.420 --> 03:55.050
But then we're going to call execution params dot attempt.

03:56.110 --> 04:00.670
Calculate captured attribute magnitude.

04:02.950 --> 04:04.330
So first we pass in.

04:04.330 --> 04:09.550
We're going to use damage statics dot critical hit chance def.

04:10.390 --> 04:13.450
We need to pass in evaluation parameters

04:16.690 --> 04:25.930
and we need to pass in source critical hit chance the float and we'll make sure that it's not negative.

04:25.930 --> 04:33.460
So we'll say source critical hit chance equals F math max.

04:35.330 --> 04:36.830
Specifying float.

04:38.340 --> 04:42.030
And will max between source critical hit chance and zero.

04:45.360 --> 04:48.220
So we now have source critical hit chance.

04:48.240 --> 04:54.720
I'm going to need both the resistance and the damage, so I'm going to copy these three lines and paste

04:54.720 --> 04:55.170
them.

04:55.170 --> 05:01.470
But this is now going to be called target critical hit resistance.

05:01.470 --> 05:03.990
And we're going to change this capture.

05:03.990 --> 05:11.610
Def passed in to critical hit resistance def and we're going to change what we pass into this.

05:11.640 --> 05:18.540
Our float is going to be the target critical hit resistance and then we're going to use target critical

05:18.540 --> 05:23.910
hit resistance with our max call passing in the target critical hit resistance and zero.

05:23.910 --> 05:29.190
And finally, we need our source critical hit damage.

05:29.190 --> 05:35.580
So we're going to change this to source critical hit damage.

05:36.570 --> 05:39.690
We're going to change the capture def here to critical hit.

05:39.720 --> 05:46.680
Damage def and the float passed in will be source critical hit damage and we're going to change this

05:46.680 --> 05:48.690
line to use source critical hit damage.

05:48.690 --> 05:52.890
Now we have our three captured attribute values.

05:53.160 --> 05:55.630
So how are we going to do the math here?

05:55.650 --> 05:58.300
Well, we have a critical hit chance, right?

05:58.320 --> 06:04.230
This should be a value that has to do with our chance to get a critical hit.

06:04.230 --> 06:09.000
I'd like to just treat it like a percentage and see if we got a critical hit.

06:09.000 --> 06:12.690
But I'd like it to be affected by critical hit resistance.

06:12.690 --> 06:16.470
Critical hit resistance should reduce the critical hit chance.

06:16.470 --> 06:23.610
So just like we had a effective armor up here, I'd like to have an effective critical hit chance as

06:23.610 --> 06:24.180
well.

06:24.180 --> 06:30.060
So I'd like a const float called Effective critical hit Chance.

06:30.600 --> 06:38.500
So what I'd like is to take my source critical hit chance and subtract my critical hit resistance from

06:38.500 --> 06:38.950
the target.

06:38.950 --> 06:43.450
So target critical hit resistance like so.

06:43.450 --> 06:49.300
And we can even scale this by a factor like 0.15, for example.

06:49.510 --> 06:57.430
And that way, critical hit resistance is not as effective as if we hadn't scaled this so critical hit

06:57.430 --> 07:03.280
resistance will scale down by this factor and then we'll subtract that from the critical hit chance.

07:03.280 --> 07:07.780
So critical hit chance is just a little bit lower and then we can roll the dice.

07:07.780 --> 07:14.770
We can see what a random value between 1 and 100 will be and see if it's less than this effective,

07:14.770 --> 07:16.060
critical hit chance.

07:16.270 --> 07:26.740
So I'm going to make a const bool called Be Critical Hit and we'll do an F math rand range.

07:29.020 --> 07:34.030
Between 1 and 100 and see if that's less than our effective.

07:38.050 --> 07:39.340
Critical hit chance.

07:39.970 --> 07:45.310
So we'll know if we have a critical hit at this point and then we can scale our damage.

07:45.310 --> 07:51.310
So we're going to take our damage and set it equal to and I'd like to use the ternary operator again.

07:51.310 --> 07:54.700
So we'll say be critical hit question mark.

07:54.700 --> 07:59.260
If it is a critical hit, then I'd like to scale my damage by two.

07:59.560 --> 08:02.560
So 2.5 times damage.

08:03.100 --> 08:05.530
So we're scaling damage by two.

08:05.530 --> 08:10.210
But I'd also like to add my critical hit damage.

08:10.210 --> 08:13.630
This is going to be a bonus critical hit damage value.

08:13.630 --> 08:20.770
So we're going to say plus source critical hit damage and then colon damage.

08:20.770 --> 08:25.240
So if critical hit is false, then we set damage equal to itself.

08:25.630 --> 08:27.250
That's just how I'd like to do it.

08:27.250 --> 08:31.600
And we can put a comment here that says.

08:32.300 --> 08:33.350
Critical.

08:34.180 --> 08:48.370
Hit resistance reduces critical hit chance by a certain percentage and we can say that double damage

08:48.370 --> 08:49.270
plus.

08:50.490 --> 08:53.100
A bonus if critical hit.

08:54.330 --> 08:56.640
Okay, so we're scaling.

08:56.670 --> 08:59.270
Target critical hit resistance by 0.15.

08:59.280 --> 09:02.430
But we could easily make this data driven.

09:02.430 --> 09:04.490
That was the bonus part of the challenge.

09:04.500 --> 09:11.940
So why don't we go ahead and launch the editor and then we can go ahead and tackle this bonus part of

09:11.940 --> 09:17.010
the challenge by adding a curve to our curve table for damage coefficients.

09:18.930 --> 09:25.920
So I'm going to go ahead and open up my CT damage calculation coefficients and add a curve and rename

09:25.920 --> 09:30.540
the curve to critical hit resistance.

09:30.840 --> 09:33.810
And we can specify what this should be.

09:34.020 --> 09:40.610
Now, as the levels go up, critical hit resistance, I think should be less and less effective.

09:40.620 --> 09:46.080
So I'm going to start at 0.15 for level one, but we'll reduce that down to 0.1.

09:46.080 --> 09:54.090
For level ten, we'll say 0.8 for level 20 and actually I should say 0.08 here.

09:54.180 --> 09:58.260
And for level 40, we'll say 0.06.

09:58.930 --> 10:01.030
So we can see what that curve looks like.

10:01.030 --> 10:01.930
Here it is.

10:03.290 --> 10:05.360
So just throwing some values out there.

10:05.360 --> 10:08.840
But we could change that as we test the game.

10:08.930 --> 10:16.430
But now that we have this, we should be able to retrieve this value in our damage execution calculation.

10:16.430 --> 10:24.020
So I'm going to save and close and take a look by scrolling up and seeing how we got our curve values

10:24.020 --> 10:26.990
for armor penetration and effect of armor here.

10:27.020 --> 10:33.020
Really, it just has to do with these two lines where we get the real curve, we get our damage calculation

10:33.020 --> 10:39.650
coefficients, we find the curve specifying the name of that curve, and then we evaluate that curve

10:39.650 --> 10:41.060
at the player level.

10:41.090 --> 10:45.230
Now we need to know which player, the source or the target, right?

10:45.440 --> 10:46.850
So we'll determine that.

10:46.850 --> 10:48.020
Let's copy these two lines.

10:48.020 --> 10:53.030
We'll go down here to just before our calculation, we'll paste them.

10:53.030 --> 11:01.700
And this is going to be critical hit resistance curve and we're going to find the curve for critical

11:01.700 --> 11:04.490
hit resistance.

11:04.490 --> 11:07.220
We're going to call this const float.

11:07.920 --> 11:11.610
Critical hit resistance coefficient.

11:12.550 --> 11:19.540
And we're going to evaluate the curve at the Target combat interface, get player level, because it's

11:19.540 --> 11:24.270
the resistance, it's the thing getting hit that we're checking the resistance for.

11:24.280 --> 11:28.360
And that's going to depend on the level of that character or target.

11:28.360 --> 11:35.560
And then we can take critical hit resistance coefficient and replace that magic 0.15 with that value.

11:35.920 --> 11:42.910
So the only thing left to do is to see if we can get a critical hit and boost that damage by our critical

11:42.940 --> 11:43.840
hit damage.

11:43.900 --> 11:51.550
And I've made one mistake, and I can tell because Ryder's telling me that this curve is not being used.

11:51.550 --> 11:53.630
And that's because I copied and pasted.

11:53.650 --> 11:58.210
So we're still getting the value here from effective armor curve.

11:58.360 --> 12:01.450
I need to change that to critical hit resistance curve.

12:01.450 --> 12:02.900
And now this should work.

12:02.920 --> 12:07.480
So with that, we can play test and see if we can get some critical hits.

12:08.620 --> 12:11.260
Okay, so we have our curve.

12:11.290 --> 12:16.000
We know that this curve is already set in our data asset for character class info.

12:16.000 --> 12:24.130
And we also know that we're initializing the attributes for our enemies using a gameplay effect.

12:24.160 --> 12:27.020
Let's go to that gameplay effect and see what it looks like.

12:27.040 --> 12:32.170
We're going to go to blueprints, Ability system, gameplay effects, default attributes and we have

12:32.170 --> 12:39.880
a G attributes test, secondary attributes test, and we can make sure that we're using that by going

12:39.910 --> 12:41.350
to the data folder.

12:41.350 --> 12:49.510
Character, class info and secondary attributes is using this test attribute so we can pump up the values

12:49.510 --> 12:51.520
of some of our attributes.

12:51.550 --> 12:56.620
Now, really, the only thing we can change here is our critical hit resistance.

12:56.740 --> 13:04.480
If we wanted to guarantee a critical hit, we'd have to modify ora's secondary attributes.

13:04.480 --> 13:05.050
Right?

13:05.050 --> 13:07.690
But let's just see if we can get a critical hit.

13:07.690 --> 13:13.630
If I can get my damage doubled in some circumstances, then I'll be happy.

13:13.640 --> 13:15.410
So I'm getting a four.

13:16.230 --> 13:17.430
There was a 21.

13:17.430 --> 13:18.270
There was an eight.

13:18.300 --> 13:21.540
So that 21, I believe, was a critical hit.

13:27.530 --> 13:30.980
And it looks like a critical hit is pretty rare.

13:31.160 --> 13:34.490
And we're getting a block quite frequently.

13:34.490 --> 13:37.490
And I think that's because our block chance is high.

13:37.520 --> 13:39.900
Yes, our block chance is set to 100.

13:39.920 --> 13:46.240
So I can set that to say 12% and we'll get a lot less blocks.

13:46.250 --> 13:52.460
And of course, we could just set that gameplay effect back to the regular one and not the test gameplay

13:52.460 --> 13:55.730
effect so we can see the actual values.

13:56.650 --> 14:03.070
But every once in a while we do get a critical hit and that is manifested as 21.

14:03.070 --> 14:05.590
Now this is all great.

14:05.620 --> 14:10.870
We know that we're sometimes getting blocks and sometimes getting critical hits, which is great, but

14:10.870 --> 14:18.190
it would be awesome if we could get some kind of visual feedback and know when we get a block and when

14:18.190 --> 14:19.600
we get a critical hit.

14:19.630 --> 14:26.800
This is kind of common in games like this where you'll see some kind of feedback here that shows whether

14:26.800 --> 14:30.430
this was a blocked hit, a critical hit and what have you.

14:30.460 --> 14:37.810
The way that I'd like to show that is with our damage number, I'd like to change the color of it if

14:37.810 --> 14:39.550
it's a block or a critical hit.

14:39.550 --> 14:45.520
And I'd also like to show some kind of message, just like a little flashing message, just like our

14:45.520 --> 14:52.330
damage number that pops up and fades away that says block or critical hit or perhaps even blocked critical

14:52.360 --> 14:52.900
hit.

14:52.930 --> 14:55.880
The way that we've coded this, we can have both.

14:55.900 --> 15:01.040
We can get a block first, cut that damage in half and then see if we got a critical hit.

15:01.040 --> 15:08.390
And if we did, then that half damage would then be doubled and added to with a critical hit damage

15:08.390 --> 15:09.220
bonus.

15:09.230 --> 15:15.920
So we have several different scenarios that can occur here and I'd like visual feedback for that.

15:15.920 --> 15:17.450
So the question is how?

15:17.450 --> 15:21.980
How do we know whether or not we got a critical hit or a block?

15:22.100 --> 15:28.130
Because that's determined here in the exec calc in the execution calculation.

15:28.130 --> 15:33.320
But we're not showing that damage number until we get to post gameplay effect execute.

15:33.320 --> 15:36.980
That's in the attribute set dot CP here.

15:37.130 --> 15:45.710
So we need a way to know here by the time we're showing that damage number whether or not this damage

15:45.710 --> 15:50.420
was critical or blocked or both, we need to know that information.

15:50.420 --> 15:56.900
And so in order to get that damage information, by the time we're here in post gameplay effect execute,

15:56.930 --> 16:04.040
we need a few more skills and we're going to work on developing those skills in the videos to come so

16:04.040 --> 16:12.560
that we can show more feedback when some of these different phenomena occur in our RPG damage calculations.

16:12.770 --> 16:14.870
So this is a great milestone.

16:14.870 --> 16:22.820
We now have a damage calculation that captures our secondary attributes that are related to combat and

16:22.820 --> 16:27.260
changes the outcome of the damage done depending on those.

16:27.260 --> 16:34.550
So this is a really great step because it's very common when you're just starting out and making games

16:34.550 --> 16:42.620
to implement a very rudimentary form of combat where you have a damage value and you're subtracting

16:42.620 --> 16:44.180
it from health and that's it.

16:44.210 --> 16:52.070
Now that we have multiple attributes at play here, damage is a lot more interesting and it's a lot

16:52.070 --> 17:00.160
more tied to power levels of both target and source of player and enemy.

17:00.160 --> 17:05.410
And this is a lot more along the lines of how RPGs behave.

17:05.410 --> 17:12.130
So it's actually really interesting and this is one of my most favorite aspects of RPG games is the

17:12.130 --> 17:14.860
mathematics behind damage calculations.

17:14.860 --> 17:16.330
So excellent job.

17:16.330 --> 17:20.800
And we're going to continue our journey developing this RPG in the videos to come.

17:20.800 --> 17:22.870
I'll see you in the next video.
