WEBVTT

00:06.810 --> 00:07.950
Welcome back.

00:07.950 --> 00:10.950
Now we have our damage damage effect.

00:10.950 --> 00:17.970
And so far we've added a custom execution calculation called exit calc damage.

00:17.970 --> 00:24.000
And it also still has a modifier modifying the incoming damage attribute.

00:24.000 --> 00:25.530
It's set to add.

00:25.530 --> 00:32.460
And if we expand the modifier magnitude, it's set by caller expanding the set by caller magnitude,

00:32.460 --> 00:34.530
we see that it's set to damage.

00:34.530 --> 00:36.690
That's the damage gameplay tag.

00:36.900 --> 00:45.630
So if this gameplay effect has a set by caller magnitude assigned with the damage tag, then we're going

00:45.630 --> 00:52.380
to modify incoming damage on whatever gets hit by this effect by that amount.

00:52.680 --> 00:59.220
But now we're going to be using our damage execution calculation and I'd like to be able to get that

00:59.220 --> 01:06.090
set by caller magnitude in our exec calc damage rather than through a modifier here on the gameplay

01:06.090 --> 01:06.880
effect.

01:06.880 --> 01:11.260
So here on modifiers, I'm going to hit the trashcan icon.

01:11.260 --> 01:13.420
So we no longer have modifiers.

01:13.420 --> 01:20.560
We've seen that we can have modifiers and we can have an exec calc, but I'm going to remove the modifier

01:20.560 --> 01:27.250
and just have the exec calc and I'd like our exec calc to be set up to get that set by caller magnitude

01:27.250 --> 01:33.550
and use that to affect the target's incoming damage meta attribute.

01:33.550 --> 01:35.830
So let's just quickly set that up.

01:36.620 --> 01:39.890
I'm going to go ahead and save all and close the editor.

01:40.310 --> 01:43.560
And we're going to get that set by caller magnitude.

01:43.580 --> 01:47.360
So here in execute implementation, let's do that.

01:47.720 --> 01:53.810
I'm going to consider all of this stuff up here, more or less pretty much boilerplate.

01:53.810 --> 01:57.820
And then everything down here is where our calculation will begin.

01:57.830 --> 02:09.290
I'm going to put a comment here that says get damage set by caller magnitude and I'm going to make a

02:09.290 --> 02:16.070
float, not a const float, but just a float, because we're going to be doing calculations to change

02:16.070 --> 02:16.400
this.

02:16.400 --> 02:18.140
This is going to be damage.

02:18.290 --> 02:21.560
Now, how are we going to get that set by caller magnitude?

02:21.560 --> 02:30.500
Well, we can always get that if we have the effect spec and we do we have spec spec has get set by

02:30.500 --> 02:31.970
caller magnitude.

02:31.970 --> 02:35.030
And this of course can take a game play tag.

02:35.030 --> 02:43.500
It can take an F name, but I prefer gameplay tags over F names as they're less prone to errors as we

02:43.500 --> 02:47.850
don't have to type in a name with a string literal and an f name object.

02:47.880 --> 02:56.640
We can just get a gameplay tag now we can get the gameplay tags from f or a gameplay tags.

02:56.880 --> 03:04.560
Now there was a little pause there because writer went and found our gameplay tags and included it for

03:04.560 --> 03:05.040
me.

03:05.070 --> 03:12.690
Now if I get the or gameplay tags and call the static get and hit dot, well there's the damage gameplay

03:12.690 --> 03:13.260
tag.

03:13.260 --> 03:21.720
So now I can get the set by caller magnitude for that and we see that the next couple of inputs for

03:21.720 --> 03:23.340
this function are optional.

03:23.460 --> 03:27.180
A boolean called warn if not found set to true by default.

03:27.210 --> 03:28.080
We'll get a warning.

03:28.080 --> 03:34.470
If we can't find that tag and then a float default if not found set to zero by default.

03:34.470 --> 03:42.360
So we'll get a zero if we can't find this set by caller magnitude and then damage will just be zero.

03:43.150 --> 03:49.480
So after calling this function damage should get that set by caller magnitude if there is one.

03:49.720 --> 03:56.500
So now that we have damage, I don't really want to do anything with armor at the moment, so I'm just

03:56.500 --> 04:01.960
going to remove those lines where we're doing something with armor and instead I'm going to make our

04:01.960 --> 04:09.080
evaluated data, modify the incoming damage meta attribute on the target.

04:09.100 --> 04:18.700
So this first input to the constructor for evaluated data can take an attribute, a gameplay attribute,

04:18.700 --> 04:26.380
and we saw that damage statics can provide that for us for any of our captured attribute capture definitions,

04:26.380 --> 04:30.160
but we're not capturing incoming damage on the target, are we?

04:30.490 --> 04:36.700
But we do know that the getters for our attributes are static functions.

04:36.700 --> 04:45.290
We can use you or attribute set get incoming damage attribute and that will satisfy that input.

04:45.320 --> 04:53.930
Now we just have to specify the mod op whether that's additive we're going to use additive and the magnitude

04:53.930 --> 05:00.020
that we're going to add to that, we're going to add damage because damage is that set by color, magnitude

05:00.020 --> 05:01.480
value that we got.

05:01.490 --> 05:08.390
So now that we've removed the modifier that was previously causing the damage, now we're going to be

05:08.420 --> 05:17.870
setting that incoming damage meta attribute on the target because we're setting that output modifier

05:17.870 --> 05:19.930
with our evaluated data.

05:19.940 --> 05:23.660
Now we should just test this out and see if we're still causing damage.

05:23.660 --> 05:26.150
So I'm going to go ahead and hit the debug button.

05:29.810 --> 05:30.350
All right.

05:30.350 --> 05:35.150
So I'm going to go ahead and open up g damage and just make sure that we understand what's going on

05:35.150 --> 05:35.640
here.

05:35.660 --> 05:37.470
We have no modifiers.

05:37.490 --> 05:39.740
Modifiers is an empty array.

05:39.770 --> 05:47.750
What we are doing is using exec calc damage and exec calc damage should be getting our set by caller

05:47.750 --> 05:51.980
magnitude from this gameplay effect associated with damage.

05:51.980 --> 05:55.010
So before the modifier was capturing that.

05:55.040 --> 06:03.590
Now our exec calc is getting that value and then we've set our evaluated data to modify incoming damage

06:03.590 --> 06:04.940
that's going to be on the target.

06:04.970 --> 06:06.950
We're adding damage to that.

06:06.950 --> 06:09.290
So we should get the same effect as before.

06:09.290 --> 06:12.150
We should be seeing about 16 damage being caused.

06:12.170 --> 06:17.900
Let's launch a fireball and there's that 16 So we're causing 16 damage.

06:17.900 --> 06:21.230
And again, that's from our exec calc.

06:21.230 --> 06:25.430
Now, no longer using the modifier with a set by caller magnitude.

06:25.820 --> 06:26.180
Okay.

06:26.180 --> 06:31.260
So now that we understand that, we can now start using our exec calc, because right now it's just

06:31.260 --> 06:33.540
behaving as a glorified modifier.

06:33.540 --> 06:38.970
It's doing exactly what our modifier was doing before getting a set by caller magnitude.

06:38.970 --> 06:42.480
But we want to do something a little more special than that.

06:42.510 --> 06:48.600
We want to start using our combat related attributes such as O block chance.

06:48.600 --> 06:57.900
For example, I'd like to capture the block chance of the target and use that to see if we got a successful

06:57.900 --> 06:58.520
block.

06:58.530 --> 07:03.210
I'm going to add just a comment here and say capture.

07:04.210 --> 07:14.860
Block chance on target and determine if there was a successful block.

07:15.100 --> 07:24.610
Now, we'll also say if block half the damage, we'll have the damage.

07:24.610 --> 07:26.890
In other words, cut the damage in half.

07:27.280 --> 07:30.730
So now that we know what we want to do with block chance.

07:30.760 --> 07:32.530
Now we just need to use it.

07:33.060 --> 07:36.090
And you knew this would be your quest, didn't you?

07:36.120 --> 07:36.960
Yeah, you did.

07:36.960 --> 07:39.050
You're going to implement blockchains.

07:39.060 --> 07:41.160
So here's what you need to do.

07:41.190 --> 07:45.450
You need to capture blockchains, capture it from the target.

07:45.480 --> 07:51.090
Now, don't snapshot, even though you know it's not going to be snapshotted anyway and check for a

07:51.090 --> 07:52.340
successful block.

07:52.350 --> 07:58.980
So figure out how you're going to use that block chance and if successful, cut the damage in half and

07:58.980 --> 08:05.700
then go ahead and playtest see if you can hit an enemy and get a successful block on an enemy.

08:05.730 --> 08:07.920
This is a chance to block, right?

08:07.920 --> 08:12.870
So we're not going to always get a block and we're not always going to not get a block.

08:12.900 --> 08:15.240
There's a chance that we should get a block.

08:15.240 --> 08:17.880
So sometimes we'll get a block, sometimes we won't.

08:17.910 --> 08:18.780
Test that out.

08:18.780 --> 08:26.130
You can even go in and change that block chance for the enemy that you're shooting fireballs at.

08:26.130 --> 08:27.060
If you want to try that.

08:27.060 --> 08:31.530
So pause the video and implement block blockchains now.

08:34.470 --> 08:35.010
Okay.

08:35.010 --> 08:37.740
So this should be relatively straightforward.

08:37.740 --> 08:43.440
This is one of the more simple types of calculations for our damage execution calc.

08:43.440 --> 08:49.680
Now we need to capture block chance, which means we need to declare an attribute capture def.

08:49.680 --> 08:50.880
So we're going to do that.

08:50.910 --> 08:52.800
We're already capturing armor.

08:52.830 --> 08:54.150
We're going to get block chance.

08:54.150 --> 09:00.750
We're going to call this capture Def Block Chance and we're going to go ahead and use the define attribute

09:00.750 --> 09:04.890
capture def so that we can have it defined here.

09:04.890 --> 09:11.310
We're going to pass in block chance instead of armor and we're capturing the block chance on the target

09:11.310 --> 09:13.920
and false for no snapshotting.

09:13.920 --> 09:21.600
So now that we've defined our capture def we need to add that to the relevant attributes to capture

09:21.600 --> 09:23.280
here in the constructor.

09:23.280 --> 09:28.860
So we're going to go ahead and do that passing in block chance def there.

09:28.860 --> 09:36.160
So now that we can capture block chance, let's capture that value here and we're going to do it right

09:36.160 --> 09:43.960
after getting our damage set by caller magnitude so we can create a float called block chance.

09:43.960 --> 09:49.660
Now we can be specific here because this is the block chance on the target.

09:49.660 --> 09:58.540
So I think it's probably best if we make the float called Target block chance and we set it to zero,

09:58.690 --> 10:06.010
but we're going to use the execution params to call attempt calculate.

10:07.350 --> 10:11.010
Captured attribute magnitude.

10:11.400 --> 10:13.850
So we need to pass in the capture def.

10:13.860 --> 10:16.110
We can get that from damage statics.

10:16.730 --> 10:22.250
So damage statics dot and that's the block chance def that we're interested in here.

10:22.340 --> 10:27.320
Now we need to pass in evaluate parameters or evaluation parameters.

10:28.010 --> 10:34.130
And we need to pass in by reference our target blockchains variable.

10:34.640 --> 10:41.510
And after we've successfully gotten that captured blockchains, we can then make sure that it's not

10:41.510 --> 10:43.250
a negative value.

10:43.280 --> 10:44.930
So we'll use Max for that.

10:44.930 --> 10:53.150
So we'll say target blockchains equals F math max specifying the float type.

10:53.150 --> 10:58.190
And we're going to take the max of target blockchains and zero.

11:00.320 --> 11:03.140
And we need a comma right there, of course.

11:03.380 --> 11:05.500
So now we have target blockchain.

11:05.510 --> 11:09.710
So how do we determine if this was a successful block?

11:09.950 --> 11:11.840
Well, it's a chance, right?

11:11.840 --> 11:15.860
It's kind of like the percentage out of 100.

11:15.890 --> 11:22.370
If we were to take a random number between 1 and 100, and if that random number is less than target

11:22.370 --> 11:25.670
block chance, let's say target block chance is 25%.

11:25.850 --> 11:34.550
If we take a random value between 1 and 100, there's a 25% chance that it'll be between 1 and 25.

11:35.170 --> 11:43.180
So we can make a const bool called Be Blocked and we can get a random value.

11:43.510 --> 11:46.690
F Math has those random number functions.

11:46.690 --> 11:53.890
We have rand range in which we can specify that we'd like a number between 1 and 100 inclusive.

11:54.010 --> 11:57.250
So this will give us a random value between 1 and 100.

11:57.280 --> 12:00.490
We can check to see if that's less than target block chance.

12:00.760 --> 12:07.060
If it is, then this expression will return true and we'll have a successful block.

12:07.360 --> 12:13.210
So this tells us if we have a successful block now, if we do, we want to cut the damage in half.

12:13.210 --> 12:16.660
We could use a simple if statement if be blocked.

12:17.800 --> 12:24.930
Then damage times equals 0.5 F.

12:24.970 --> 12:26.770
That's one way to do it.

12:27.070 --> 12:33.250
Or damage divided equals to point F, right.

12:33.250 --> 12:34.780
Divided by two.

12:34.960 --> 12:44.200
Or if you want it to be really explicit, you could say if B blocked damage equals damage divided by

12:44.230 --> 12:45.440
two point F.

12:45.460 --> 12:50.470
How you express this is really a matter of personal preference and style.

12:50.500 --> 12:53.740
I kind of like the compactness of the ternary operator.

12:53.740 --> 12:58.950
I like saying things like damage equals B blocked question mark.

12:58.960 --> 13:06.520
And if it is true, then damage divided by two point F colon damage.

13:06.520 --> 13:10.360
So set it equal to itself if blocked is false.

13:10.390 --> 13:13.300
I personally like this expression.

13:13.300 --> 13:15.640
It's nice and sort of compact.

13:16.350 --> 13:21.930
So now we have successfully implemented a block chance, we get the block chance of the target.

13:21.930 --> 13:29.310
And if it's lucky if our random value is less than its target block chance, it gets the block and it

13:29.310 --> 13:30.510
takes half the damage.

13:30.510 --> 13:35.760
So sometimes we should see a block in which we're getting half what we expected.

13:36.120 --> 13:39.060
So the last thing to do is test it out.

13:41.130 --> 13:41.550
Okay.

13:41.550 --> 13:42.990
So we can test this out.

13:43.020 --> 13:48.330
We can just start throwing fireballs and seeing if some of them are half the value.

13:48.360 --> 13:52.590
That's maybe what I'd like to do at first and see if we can just get a couple of blocks.

13:52.590 --> 13:54.990
There's 16, which is what we've been getting.

13:55.380 --> 13:57.090
Let's see if we can get any blocks.

13:57.090 --> 13:57.900
There was an eight.

13:57.900 --> 14:06.510
Yes, we got a block and I don't really know what the block chance is, but I can find out by debugging.

14:06.510 --> 14:08.880
I can see what the target block chance is.

14:08.880 --> 14:14.190
By the time we get down to say here, let's see what it is, let's go ahead and.

14:15.080 --> 14:17.240
Cause damage hit the break point.

14:17.270 --> 14:19.940
Here's the target block chance.

14:20.150 --> 14:30.050
And it is for target block chances for which means that be blocked is going to be false most of the

14:30.050 --> 14:37.700
time because a random value between 1 and 100 will be for not that often 4% of the time.

14:37.700 --> 14:38.270
Right.

14:38.690 --> 14:45.770
So it's kind of amazing that we even saw an eight instead of a 16 because there isn't that high of a

14:45.770 --> 14:46.670
block chance.

14:46.670 --> 14:51.200
But anyway, in that case, we get a block, we cut the damage in half.

14:51.200 --> 14:52.580
Now that's pretty cool.

14:52.580 --> 15:01.460
We can also force a block for testing purposes by setting the block chance to 100% or 100.

15:01.520 --> 15:06.740
And we can do that because we know the class that these enemies are.

15:06.740 --> 15:14.180
This one's the goblin spear and we have data related to their initial starting attributes, of course.

15:14.180 --> 15:16.710
Block Chance is derived, right?

15:16.710 --> 15:25.800
It's a derived attribute, but we could go to ability system data and go to character class info and

15:25.800 --> 15:28.230
take a look at our warrior.

15:28.230 --> 15:34.260
That's what the spear is and take a look at its primary attributes warrior.

15:34.260 --> 15:40.590
In fact, what we could do instead of messing with primary attributes and doing math, is we could set

15:40.590 --> 15:43.020
the secondary attribute directly here.

15:43.050 --> 15:45.300
G Secondary attributes enemy.

15:45.300 --> 15:51.570
We can go to that gameplay effect and we can just override block charts, right?

15:51.600 --> 16:00.720
We're overriding it with an attribute based modifier backed by look at this, we're backing it by armor

16:00.840 --> 16:06.180
with a coefficient of 0.25 and a post multiply additive value of four.

16:06.510 --> 16:13.020
We could switch this if I switch it from attribute based to scalable float and just set it to a value

16:13.020 --> 16:16.500
of 100, then we'll have 100% block chance.

16:16.500 --> 16:19.050
So now we should always see eights.

16:20.210 --> 16:23.930
There's an eight, There's an eight, there's an eight.

16:23.930 --> 16:26.900
Everybody gets an eight because it's always a block.

16:26.930 --> 16:30.620
Now I'm going to go back and just change that back.

16:30.650 --> 16:35.000
If I set this back to Attribute Based, it remembers those values.

16:35.000 --> 16:40.340
Thankfully, I don't have to go back and look those up in my notes and put that back.

16:40.370 --> 16:41.740
That's totally fine.

16:41.750 --> 16:47.090
Now for testing, sometimes what I like to do is create a test gameplay effect.

16:47.090 --> 16:51.350
So I'll come in here for my secondary attributes.

16:51.350 --> 17:01.130
I'll duplicate it and call this one G Secondary attributes underscore test, and then I can modify the

17:01.130 --> 17:06.560
test attribute and not have to worry about what my real values are supposed to be.

17:06.560 --> 17:10.550
I can come into the test attribute and use this one instead.

17:10.550 --> 17:14.870
So here for block chance I can set this one to scalable float with 100.

17:14.870 --> 17:15.230
Look at that.

17:15.230 --> 17:17.870
It remembered the 100 that's really handy.

17:17.870 --> 17:23.790
And then I can go back and change my data asset to use instead of secondary attributes.

17:23.790 --> 17:32.550
Enemy I can use secondary attributes test and now I can always test 100% block chance and whatever else

17:32.550 --> 17:33.780
I'd like to change.

17:33.960 --> 17:35.850
So that's nice and handy there.

17:35.850 --> 17:42.810
We can use that if we want to continue testing for our damage execution calculations that take these

17:42.840 --> 17:44.460
attributes into account.

17:44.580 --> 17:47.490
For now, I'm just going to set this back to what it was before.

17:47.490 --> 17:49.020
Secondary attributes enemy.

17:49.020 --> 17:53.910
But now we have this test secondary attributes, gameplay effect to test things out.

17:54.090 --> 17:56.130
All right, So excellent job.

17:56.130 --> 18:03.990
This is a really great milestone because damage execution calculations are pivotal to RPGs.

18:03.990 --> 18:09.960
They're one of my favorite things to implement in a project because now we get to do all the fun math

18:09.960 --> 18:14.610
behind RPG combat that really makes an RPG what it is.

18:14.610 --> 18:22.110
So in the videos to come, we're going to implement more damage calculations in our execution calculation.

18:22.110 --> 18:27.210
It's really the heart of our combat here, and it's going to get a lot more interesting.

18:27.420 --> 18:28.140
Great job.

18:28.140 --> 18:30.540
And I'll see you in the next video.
