WEBVTT

00:06.830 --> 00:08.030
Welcome back.

00:08.240 --> 00:16.670
Now that we have our own ability system globals class and it's overriding Alec gameplay effect context,

00:16.700 --> 00:22.610
we know that every time we create a gameplay effect context at least using make effect context like

00:22.610 --> 00:24.890
we're doing in aura projectile spell.

00:24.890 --> 00:31.670
We know that the object created is an aura gameplay effect context.

00:31.670 --> 00:37.760
So now we need to know how exactly we can utilize our new effect context.

00:37.790 --> 00:42.590
How can we set the values of the booleans on the context?

00:42.620 --> 00:48.980
Well, we're going to know when it's a blocked hit and a critical hit in our damage execution calculation.

00:48.980 --> 00:51.110
So that would be the place to do it.

00:51.230 --> 00:53.810
So why don't we head over to that class?

00:54.020 --> 00:56.750
I'm going to go ahead and just close all tabs.

00:57.620 --> 01:07.790
And go into ability system exec calc and exec calc damage dot CP and here I know whether or not I got

01:07.790 --> 01:14.070
a critical hit and whether or not I got a blocked hit as we perform those calculations here.

01:14.090 --> 01:16.340
Now I'm going to scroll up to our constable.

01:16.370 --> 01:20.420
Be blocked here as soon as I know that this is a blocked hit.

01:20.450 --> 01:27.650
I'd like to access the gameplay effect context associated with this gameplay effect that's using this

01:27.650 --> 01:31.280
exec calc and set its blocked boolean.

01:31.400 --> 01:32.870
So how do we do that?

01:33.350 --> 01:37.760
Well, first we need to access the gameplay effect context, right?

01:37.910 --> 01:43.990
And because we have access to the gameplay effect spec, it's called spec here, we can get that.

01:44.000 --> 01:49.340
So we can type spec dot and here's the function get context.

01:49.550 --> 01:59.220
Now get context returns an F gameplay effect context handle so we can create a local f gameplay effect

01:59.370 --> 02:08.820
context handle called effect context handle and handle should be uppercase there.

02:08.850 --> 02:09.780
There we go.

02:09.930 --> 02:15.240
Now we have the effect context handle, but this is the context handle.

02:15.240 --> 02:15.600
Right?

02:15.600 --> 02:18.210
How do we get that effect context from it?

02:18.270 --> 02:24.390
Well, if we type effect context handle dot, then we have a get function.

02:24.540 --> 02:31.130
If we call get this returns a pointer to the gameplay effect context itself.

02:31.140 --> 02:40.140
So that gives us an F gameplay effect context pointer and we can call it context if we like.

02:40.290 --> 02:42.540
And now we have access to the context.

02:42.570 --> 02:49.290
Now if we use the arrow operator and take a look at all the stuff built in to the gameplay effect context

02:49.290 --> 02:50.160
class.

02:50.280 --> 02:54.960
Well, where's our setters and getters for our new booleans?

02:54.960 --> 02:59.550
Remember we had a set Is blocked hit.

02:59.760 --> 03:00.920
I don't see that here.

03:00.930 --> 03:03.510
Writer isn't showing me with autocomplete.

03:03.540 --> 03:04.350
Why is that?

03:04.350 --> 03:08.040
Because context is not an aura gameplay effect context.

03:08.070 --> 03:10.650
It's an gameplay effect context.

03:10.650 --> 03:14.460
And that's because get returns a gameplay effect context.

03:14.460 --> 03:19.080
But what we need is an aura gameplay effect context.

03:19.380 --> 03:20.910
So how do we get one?

03:20.910 --> 03:25.080
Well, we have to cast and we have to specifically static cast.

03:25.200 --> 03:34.350
So what we can do is make an F aura gameplay effect context pointer and call this aura context.

03:34.380 --> 03:41.070
Now this type is in our header file that we created called aura ability type.

03:41.070 --> 03:42.630
So we have to include that.

03:42.630 --> 03:47.490
I can just hit alt enter and include that here and now.

03:47.490 --> 03:51.270
We can set this equal to the result of a static cast.

03:51.300 --> 03:55.950
Now this is a regular C plus plus style static cast.

03:55.950 --> 04:05.130
So in the angle brackets, we have to have F aura gameplay effect context with the star, the cast function,

04:05.130 --> 04:10.590
the unreal engine specific cast function doesn't require the star, but static cast does.

04:10.620 --> 04:19.140
This will perform a compile time static cast and we're going to cast that gameplay effect context pointer.

04:19.680 --> 04:26.820
So after doing this cast, we now have the aura context and then we can call functions on it like set

04:26.850 --> 04:34.560
is blocked hit, so we can take Aura context call set is blocked, hit perfectly fine and we can set

04:34.560 --> 04:36.720
it because we know be blocked.

04:36.720 --> 04:40.830
Whatever that value is, we can set that passing that in.

04:40.830 --> 04:44.850
We now know that set is blocked hit, we'll set that value.

04:44.850 --> 04:50.760
So if we want to access those properties that we've added to aura gameplay effect context, this is

04:50.760 --> 04:52.440
how we use a static cast.

04:52.470 --> 04:55.170
Now this is kind of a lot of work just to call.

04:55.170 --> 04:56.490
Set is blocked hit.

04:56.490 --> 05:04.950
So for convenience it'd be nice if we had some ability system blueprint library functions that can set

05:04.950 --> 05:12.360
these properties and that would also give us the opportunity to expose the ability to get these properties

05:12.360 --> 05:13.590
in Blueprint.

05:13.590 --> 05:18.300
So why don't we open our aura ability system library?

05:18.450 --> 05:22.920
I'll get the CP and the dot h file open here.

05:22.920 --> 05:26.340
And why don't we create a couple of functions for this?

05:26.790 --> 05:34.260
Now, some people would prefer to only expose getters to blueprint, and if you want to set those properties

05:34.260 --> 05:41.040
they would say you should only do that here in C plus plus perform the static cast like we did and call

05:41.040 --> 05:42.810
the setter, etcetera.

05:43.050 --> 05:47.010
But if you wanted to, you could expose the setter to blueprint as well.

05:47.040 --> 05:48.570
We'll go ahead and do both.

05:48.630 --> 05:51.870
Now I'm going to create a static function.

05:52.870 --> 05:58.000
This will be a bool returning function and this will be for getting whether or not we have a blocked

05:58.000 --> 05:58.460
hit.

05:58.480 --> 06:07.270
So I'll call this is blocked hit and the function itself can take in the gameplay effect context handle.

06:07.630 --> 06:10.720
That's pretty easily accessible from within blueprint.

06:10.840 --> 06:15.160
So it's going to take an F gameplay effect context handle.

06:15.490 --> 06:21.070
I'll pass it in by const reference and I'll call this effect context handle.

06:21.580 --> 06:23.410
Now this can be a new function.

06:23.410 --> 06:28.630
We can expose it to blueprint and if it's just going to be a simple getter, it can be a blueprint,

06:28.630 --> 06:29.500
pure function.

06:29.500 --> 06:31.180
So we'll make it blueprint pure.

06:31.750 --> 06:39.310
We can give it a category and I'm going to put it in the category Aura ability system library and the

06:39.310 --> 06:43.630
sub category can be gameplay effects.

06:43.990 --> 06:45.260
So is blocked.

06:45.280 --> 06:47.440
Hit is going to be relatively simple.

06:47.440 --> 06:52.850
I'm going to go ahead and just generate the definition and have it here in the CPP file and and what

06:52.850 --> 06:59.660
it's going to do is it's going to access the boolean on the aura gameplay effect context, which means

06:59.660 --> 07:01.080
we're going to need to cast.

07:01.100 --> 07:05.930
So I'm going to make an aura gameplay effect context pointer.

07:05.940 --> 07:12.770
I'm going to let Rider include the header for that call this aura effect context and set it equal to

07:12.770 --> 07:14.870
the result of a static cast.

07:15.200 --> 07:20.180
And I'm going to cast to this type F aura gameplay effect context.

07:20.420 --> 07:22.610
Go ahead and paste that in the angle brackets.

07:22.610 --> 07:29.360
And since we're passing in the effect context handle, I can take the effect context, handle and call

07:29.360 --> 07:32.540
get to get the effect context itself.

07:32.690 --> 07:36.650
Now if we're calling effect context handle dot get.

07:36.680 --> 07:40.970
This returns a const F gameplay effect context pointer.

07:41.120 --> 07:47.510
And if we're static casting then we have to store the result in a const because we're getting a const

07:47.540 --> 07:48.740
version of this.

07:48.770 --> 07:55.130
If we wanted to store this in a non const, we'd have to const cast to cast away the const ness.

07:55.130 --> 08:02.780
And we also have to make sure that we're casting to specifically a const F or a gameplay effect context

08:02.780 --> 08:03.650
pointer.

08:03.770 --> 08:12.260
Now, if this effect context is a valid pointer, then we can access the is blocked hit getter function.

08:12.260 --> 08:19.940
So I'll simply place an if statement here and wrap this whole expression in an if statement and this

08:19.940 --> 08:29.960
function can return the aura effect context is blocked hit and if the static cast fails, we can return

08:29.960 --> 08:30.770
false.

08:30.770 --> 08:32.690
So now we have a blueprint.

08:32.690 --> 08:40.610
Pure is blocked hit function that can just take in a gameplay effect context handle and do that static

08:40.610 --> 08:42.560
cast here on the C plus plus side.

08:42.560 --> 08:48.470
So it's sort of insulating all of this stuff from the blueprint developer we can do the same thing for

08:48.500 --> 08:49.690
is critical hit.

08:49.700 --> 08:52.070
I can basically copy this function.

08:53.720 --> 08:58.220
And paste it and call this one is critical hit.

08:59.480 --> 09:02.590
And for this it's going to be almost the same.

09:02.600 --> 09:10.340
We can go ahead and generate the definition and just take the same exact function body from is blocked

09:10.340 --> 09:10.520
hit.

09:10.520 --> 09:14.060
The only difference is we're going to call is critical hit.

09:16.440 --> 09:20.700
So that right there exposes these two functions to blueprint.

09:20.730 --> 09:23.340
Now we can see what these look like in Blueprint.

09:23.370 --> 09:28.920
If we just run in debug mode, we can create a couple of these nodes in a blueprint.

09:30.220 --> 09:35.140
So what I'd like to do is just create those nodes and see how they look in blueprint.

09:35.290 --> 09:42.310
So I'm going to go to blueprints, Ability system, gameplay abilities, Fire Firebolt and open the

09:42.310 --> 09:43.300
Firebolt.

09:43.300 --> 09:46.570
And right here I'd like to just see what those nodes look like.

09:46.570 --> 09:50.980
So I'm just going to right click and call is critical hit.

09:51.310 --> 09:52.450
Here it is.

09:52.480 --> 09:55.900
Let's get that node and here's the blueprint pure node.

09:56.080 --> 10:03.190
I'm also going to right click and get is blocked hit and these take in effect context handle structure.

10:03.190 --> 10:10.330
Now from here within an ability, there are some functions to get effect context there's an get effect

10:10.330 --> 10:12.250
context function.

10:12.250 --> 10:19.420
It requires an effect spec handle but we see that it returns a gameplay effect context handle and as

10:19.420 --> 10:22.900
we can see, our blueprint pure function can easily accept that.

10:22.900 --> 10:26.650
So that's what our ability system library is.

10:26.650 --> 10:30.370
Critical hit blueprint pure function looks like.

10:30.370 --> 10:33.550
I'm going to go ahead and close down the editor.

10:33.550 --> 10:34.510
I can save all.

10:34.510 --> 10:35.350
That's fine.

10:35.350 --> 10:38.020
And let's see what some setters would look like.

10:38.020 --> 10:40.720
Let's say we'd like to set is blocked hit.

10:40.750 --> 10:47.560
Now for this one, I'll make a static void function called set is blocked hit.

10:47.680 --> 10:54.370
Now for this we're not only going to take in a gameplay effect context handle, we're also going to

10:54.370 --> 10:55.870
take in a boolean, right?

10:55.930 --> 11:02.290
And we're not going to pass in the gameplay effect context handle as a const reference because we can't

11:02.290 --> 11:06.340
call a setter that will change this context handle.

11:06.340 --> 11:10.450
If it's a const reference, it has to be a non const reference.

11:10.630 --> 11:15.400
So this has to be a gameplay effect context handle.

11:16.250 --> 11:25.820
By Non-const reference called effect context handle and we'll have a bool called b n is blocked hit.

11:26.690 --> 11:29.870
Now this one won't be a blueprint pure function.

11:29.870 --> 11:35.630
It should be blueprint callable because it's really causing side effects, right?

11:35.630 --> 11:41.690
It's going to actually change something and blueprint pure functions are not suitable for that.

11:41.690 --> 11:47.810
We're going to use a blueprint callable and we can go ahead and generate the definition and this one

11:47.810 --> 11:49.250
will be similar.

11:49.250 --> 11:51.450
But there are a couple of differences.

11:51.470 --> 11:54.350
For one, we're not going to use const, right?

11:54.350 --> 12:00.620
We're going to take the effect context, handle and cast to a non-const So we're going to say F or a

12:00.620 --> 12:03.140
gameplay effect context.

12:03.170 --> 12:04.100
That's a pointer.

12:04.100 --> 12:06.530
We're going to call it ora effect context.

12:08.360 --> 12:15.990
We're going to set it equal to the result of a static cast to this type F or a gameplay effect context.

12:15.990 --> 12:24.030
We're going to cast effect, context handle, dot get and we're going to check this in an if statement.

12:24.030 --> 12:26.240
So notice no const here at all.

12:26.250 --> 12:31.920
All of these are non const and that's because the effect context handle is non const.

12:31.950 --> 12:38.070
If we had this passed in by const reference, we get errors all over the place so we can't pass it in

12:38.070 --> 12:40.170
by a const reference.

12:40.620 --> 12:48.570
Now, once we have the effect context, we can take it ora effect context and we can call set is blocked

12:48.600 --> 12:53.970
hit, which takes a boolean and we can pass in b in is blocked hit.

12:55.770 --> 12:59.700
So a pretty simple function and it's exposed a blueprint.

12:59.700 --> 13:06.090
And we can look at what this looks like in the blueprint event graph, and we're going to find out that

13:06.090 --> 13:12.990
because this is a non-const reference, we're going to find that there's a little bit of a problem with

13:12.990 --> 13:15.300
this blueprint exposed function.

13:15.420 --> 13:19.890
Let's go ahead and run and debug mode and create one of these nodes in blueprint.

13:22.190 --> 13:29.420
Okay, so I'm going to open up my firebolt ability and I'm going to right click and type set is blocked.

13:30.170 --> 13:31.040
Hit.

13:31.220 --> 13:33.000
Here's my new function.

13:33.020 --> 13:36.920
Now there's a problem, and I'm sure you see it right away.

13:37.160 --> 13:41.150
The effect context handle is an output pin.

13:41.390 --> 13:47.930
How are we going to pass in the effect context handle if it's not an input pin but an output pin and

13:47.930 --> 13:48.860
we can't.

13:49.100 --> 13:53.530
And that's because this is a non-const reference in Unreal engine.

13:53.540 --> 14:01.090
If a function input is a non-const reference, that means that it's typically an out parameter.

14:01.100 --> 14:02.900
It's meant to be passed in.

14:02.930 --> 14:10.030
Yes, but the function fills it out and then it's a output execution pin.

14:10.040 --> 14:11.720
Now that's by default.

14:11.750 --> 14:17.510
If we want this to be an input execution pin, then there's an important step that we have to do to

14:17.510 --> 14:20.630
tell the blueprint node that that's what we want.

14:20.660 --> 14:26.130
So I'm going to close the editor and go back to set is blocked hit.

14:26.130 --> 14:34.260
And the way that we tell the function that this is going to be an input parameter in the blueprint is

14:34.260 --> 14:40.230
that we use you param and inside of its parentheses we put ref ref.

14:40.230 --> 14:42.750
So this is a input parameter.

14:42.750 --> 14:44.690
That's a non-const reference.

14:44.700 --> 14:50.220
If we put this in the function signature, then it's going to know that this should be an input and

14:50.220 --> 14:51.420
not an output.

14:51.420 --> 14:55.950
So with just that little change, let's run a debug mode again.

14:57.590 --> 15:02.080
And opening back up our gameplay ability.

15:02.090 --> 15:06.290
We see that our set is blocked, hit Node has changed.

15:06.320 --> 15:13.280
We now have an input execution pin for the effect context handle and notice that it's now a diamond

15:13.280 --> 15:16.790
shape and not a circle for the input pin.

15:16.790 --> 15:20.740
So if you've ever seen that diamond shape, now you know what that means.

15:20.750 --> 15:26.300
We have a non-const reference set to be an input, not an output pin.

15:26.300 --> 15:29.720
And now we have this nice handy set is blocked hit function.

15:29.800 --> 15:34.760
We don't have to worry that our effect context handle is not the aura type.

15:34.790 --> 15:38.900
We know that the object is, but the type in blueprint is not.

15:38.900 --> 15:42.290
But we can pass in an effect context, handle and set.

15:42.320 --> 15:47.210
Whether or not that context is blocking hit boolean is true.

15:47.390 --> 15:56.030
Now that's just setting the is blocking hit boolean we can create one for is critical hit by basically

15:56.060 --> 15:57.570
doing the same thing.

15:57.570 --> 16:06.060
I'm going to duplicate the function but this one will be called set is critical hit the input parameter

16:06.060 --> 16:13.790
for in is blocked hit should be renamed to in is critical hit and we have the new param.

16:13.800 --> 16:21.060
So this is an input pin and we can generate the definition and I'm going to just copy the definition

16:21.060 --> 16:23.640
from set is blocked hit.

16:23.670 --> 16:33.690
The difference is we're going to call set is critical hit and pass in be in is critical hit and now

16:33.690 --> 16:39.810
we have those blueprint callable setter functions that can set these properties from blueprint.

16:39.810 --> 16:45.450
So now that we have these getters and setters in aura ability system library, this makes our lives

16:45.480 --> 16:48.540
a whole lot easier when we need to set these properties.

16:48.570 --> 16:54.030
For one here in exit calc damage, we don't have to go through all this trouble to do the static cast

16:54.030 --> 16:54.990
and all that.

16:55.020 --> 17:01.290
All we need to do is get our effect context, handle with spec, dot get context, and we can simply

17:01.290 --> 17:09.780
call the aura ability system library function you aura ability system library, colon colon set is blocked

17:09.810 --> 17:13.710
hit so we can pass in effect context handle.

17:13.710 --> 17:19.560
And we also need a boolean for whether or not this is a blocked hit that's going to be the value of

17:19.590 --> 17:20.790
be blocked.

17:21.660 --> 17:29.160
So that's how we can set is blocked hit and we can do the same thing for the critical hit by scrolling

17:29.160 --> 17:36.210
down to our critical hit calculation here, we're setting be critical hit we can use you or a ability

17:36.210 --> 17:43.380
system library set is critical hit and we still have that effect context handle that we got up here

17:43.380 --> 17:45.570
it's called effect context handle.

17:45.570 --> 17:53.190
We can pass that in and we can pass in the Boolean, be critical hit like so now because we're doing

17:53.190 --> 18:00.330
this, by the time we get all the way over to the attribute set in post gameplay effect, execute here,

18:00.330 --> 18:07.680
we can query whether or not that was a critical hit so we can get all the way down to perhaps where

18:07.680 --> 18:09.900
it matters here in show floating text.

18:09.900 --> 18:16.380
This I think is where it matters because this is where we want to know if we got a critical hit or not.

18:16.500 --> 18:23.620
I think our show floating text function should take in two booleans for whether or not we got blocked

18:23.620 --> 18:24.700
or critical hits.

18:24.700 --> 18:32.710
So I'm just going to go to show floating text in the H file and after passing in props and damage,

18:32.710 --> 18:43.030
I'm going to also pass in a bool called be blocked hit and bool be critical hit.

18:45.110 --> 18:48.130
I'm going to add those to the function definition.

18:48.140 --> 18:52.760
So going back to the CPP file, we're going to add those in right here.

18:52.790 --> 18:56.410
Now, what we do with those, we'll handle those soon.

18:56.420 --> 19:03.950
I just want to pass them in for now and we can pass those in by accessing our functions from Ability

19:03.950 --> 19:05.000
System library.

19:05.000 --> 19:15.140
I'm just going to make a const bool called be block equals you or a ability system library is blocked

19:15.140 --> 19:21.950
hit and we need our game play effect context, don't we.

19:22.100 --> 19:29.870
Well we have a bunch of things in props props including our effect context handle.

19:30.200 --> 19:31.970
Now this requires an effect.

19:31.970 --> 19:39.320
Context handle right so props dot effect context handle can be just popped right in there.

19:39.410 --> 19:41.060
And now we have be block.

19:41.060 --> 19:48.120
We can pass that in right here be block and of course we need be critical hit so let's make another

19:48.120 --> 19:58.650
one const bool be critical hit and we'll use you or ability system library is critical hit passing in

19:58.650 --> 20:06.630
props dot effect context handle and we can pass in be critical hit right on in to show floating text

20:06.660 --> 20:14.040
now show floating text will have those values All right so that's a great stopping point in the next

20:14.040 --> 20:18.630
video we can handle what we do with these Boolean values.

20:18.630 --> 20:26.340
But before we go on any further, we can just test this out by causing some damage and seeing that those

20:26.370 --> 20:30.060
be block and be critical hit values are being set.

20:30.060 --> 20:33.060
So let's go ahead and just run in debug mode.

20:33.180 --> 20:39.330
And what I'd like to do is make sure our block chance is 100 so we at least get a successful block.

20:41.190 --> 20:42.750
Now I'm back in the editor.

20:42.750 --> 20:47.430
I'll go ahead and open up my firebolt ability and get rid of these.

20:47.430 --> 20:51.660
I can just quickly make sure set is critical.

20:51.690 --> 20:54.030
Hit is there and it looks good.

20:54.030 --> 20:55.410
And there it is.

20:55.500 --> 20:56.370
Okay, cool.

20:56.370 --> 21:01.680
So I'm going to close firebolt and let's just cause some damage.

21:01.680 --> 21:03.840
I'm going to go ahead and just launch a fireball.

21:04.550 --> 21:07.810
And here in show floating text, we've made it this far.

21:07.820 --> 21:08.960
We have damage.

21:08.960 --> 21:10.010
We have blocked hit.

21:10.010 --> 21:10.880
That's false.

21:10.880 --> 21:12.110
We have be critical hit.

21:12.110 --> 21:12.710
That's false.

21:12.710 --> 21:13.640
Okay, cool.

21:13.670 --> 21:21.800
But let's just change our block chance to 100% in our test secondary attributes effect so we'll go to

21:21.800 --> 21:26.960
ability system gameplay effects, default attributes, secondary attributes test.

21:26.960 --> 21:35.930
This is what's being used by our enemies and we'll set our block chance to 100 so we have 100% chance

21:35.930 --> 21:39.710
to block and we'll go ahead and cause some damage.

21:41.080 --> 21:46.180
And by the time we get to show floating text be blocked, hit is true and be critical.

21:46.210 --> 21:47.140
Hit is false.

21:47.170 --> 21:53.200
It's very rare to get a critical hit because, well, if you go and look at the attributes and take

21:53.200 --> 21:55.750
a look at critical hit chance, it's three.

21:55.750 --> 21:59.560
And that's basically almost never right.

21:59.560 --> 22:02.650
So we could always change that.

22:02.650 --> 22:05.050
We can make it a little bit easier to get a critical hit.

22:05.050 --> 22:08.620
But anyway, the point is that things are working.

22:08.620 --> 22:15.880
We're now using our custom gameplay effect context or a gameplay effect context.

22:15.910 --> 22:19.900
We created some ability system library functions.

22:19.900 --> 22:23.950
These static functions, they're exposed to blueprint and they just require an effect.

22:23.950 --> 22:26.200
Context handle and booleans.

22:26.200 --> 22:27.460
In the case of the setters.

22:27.460 --> 22:35.680
And now our lives are easier because whenever we're wanting to set those, we call those very easy to

22:35.680 --> 22:36.850
use functions.

22:36.850 --> 22:41.720
And when we want to get those values, we get those wherever we have our effect.

22:41.720 --> 22:42.830
Context handle.

22:42.830 --> 22:46.550
And now that show floating text is receiving those values.

22:46.550 --> 22:52.790
Whenever we get a block or a critical hit, we can decide how to show that visually to the user.

22:52.790 --> 22:54.590
So excellent job.

22:54.590 --> 22:57.440
We're doing some nice, cool, advanced stuff here.

22:57.440 --> 23:00.530
It's really exciting and I'll see you in the next video.
