WEBVTT

00:06.860 --> 00:07.890
Welcome back.

00:07.910 --> 00:14.150
In this video, we're going to take a look at the effect context and make sure that we understand completely

00:14.150 --> 00:17.480
what's going on with the gameplay effect context.

00:17.510 --> 00:23.600
Now, the effect context is something that lives with a gameplay effect and seems to carry along some

00:23.600 --> 00:30.200
information, but thus far it isn't really all that clear to us exactly what information is being carried

00:30.200 --> 00:30.840
along.

00:30.860 --> 00:36.350
So we're going to take a deeper dive into the effect context in this video and see what it can do for

00:36.350 --> 00:43.190
us and find its limitations and start brainstorming about how we can get around those limitations.

00:43.220 --> 00:49.790
Now I'm here in the aura attribute set, set effect properties function, and we know that we have the

00:49.790 --> 00:52.370
effect context handle here.

00:52.370 --> 00:58.930
In this function, we're setting it on our props parameter, an input of type F effect properties.

00:58.940 --> 01:04.670
So here in set effect properties, we're setting that props dot effect context handle.

01:04.700 --> 01:11.340
By getting it from the effect spec which we have in our gameplay effect mod callback data so we can

01:11.340 --> 01:15.450
always get that effect context handle using get context.

01:15.600 --> 01:20.520
Now we know that the effect context handle has the effect context inside of it.

01:20.520 --> 01:25.080
So what I'd like to do is sort of pause execution right here.

01:25.110 --> 01:32.880
We can pause execution right here as soon as this property is being set and see exactly what that effect

01:32.880 --> 01:34.200
context has.

01:34.230 --> 01:37.740
By the time we've made it this far into the attribute set.

01:37.770 --> 01:38.850
So I'd like to do that.

01:38.850 --> 01:46.380
I'm going to click the debug button and what I think I'll do is launch a fireball as our fireball is

01:46.380 --> 01:47.760
applying a gameplay effect.

01:47.760 --> 01:49.950
It's our G damage effect.

01:49.950 --> 01:57.540
So I'd like to see basically what the context handle is carrying along by the time we apply that gameplay

01:57.540 --> 01:58.200
effect.

01:58.200 --> 02:04.110
So I'm going to press play and I'm going to come back into the editor and place a breakpoint here.

02:04.140 --> 02:11.400
I press play and then placed the breakpoint here just because I don't want to have to hit resume for

02:11.400 --> 02:12.990
the first time it gets called.

02:12.990 --> 02:16.740
So now that we have the game running, we have our breakpoint here.

02:16.830 --> 02:19.320
I'm going to launch a fireball at one of the enemies.

02:19.440 --> 02:26.010
And as soon as we apply that gameplay effect, we have our breakpoint reached and we have our effect

02:26.010 --> 02:27.810
context handle set.

02:27.840 --> 02:36.540
Now this has some data so we can take a look at it either by hovering over or taking a look down here

02:36.540 --> 02:38.160
at the bottom right.

02:38.400 --> 02:39.780
And we know that effect.

02:39.780 --> 02:47.610
Context handles have a data property and that data is the gameplay effect context itself.

02:47.610 --> 02:51.810
It's a shared pointer, but we can see all that the data has.

02:51.840 --> 02:58.110
And we're going to notice if we take a look at data and look at all the fields, we'll see that some

02:58.110 --> 03:01.740
of them are set and some of them are not set.

03:01.770 --> 03:06.870
A lot of these are empty or null pointer So what exactly is set?

03:06.870 --> 03:09.300
That's the first question we'd like to answer.

03:09.300 --> 03:11.180
And the second question is why?

03:11.190 --> 03:15.540
Why are those properties set and how come the others are not?

03:15.540 --> 03:18.630
So we're going to answer both of those questions in this video.

03:18.990 --> 03:23.580
So looking at these fields under data, we see that there's an instigator.

03:23.580 --> 03:27.630
And if we expand that, we can see what the instigator is.

03:27.660 --> 03:30.540
The instigator is an actor itself.

03:30.630 --> 03:38.010
We can see that it has a player state, an ability system component and an attribute set.

03:38.010 --> 03:39.600
And these seem to be set.

03:39.600 --> 03:42.930
So we have the BP or a player state here.

03:43.110 --> 03:47.190
We have the ability system component and attribute set.

03:47.710 --> 03:50.890
And we seem to see that there is a level set to one.

03:51.590 --> 03:58.130
We also see that there is an effect causer and the effect causer seems to be set to BP or a character.

03:58.130 --> 04:05.330
So something is setting our instigator to or a player state and the effect causer to or a character

04:05.330 --> 04:06.620
for some reason.

04:06.800 --> 04:14.000
And after these two instigator and effect causer, we have a bunch of other things that seem to be not

04:14.000 --> 04:15.080
set to anything.

04:15.080 --> 04:18.530
We have ability S.d.o set to null pointer.

04:18.560 --> 04:25.580
We have ability instance not replicated set to null pointer ability level seems to be set to one, but

04:25.580 --> 04:27.680
that must be some kind of default.

04:27.710 --> 04:31.250
We also have the source object and now we've seen source object before.

04:31.250 --> 04:35.630
We've set this before on our effect context for some of our effects.

04:35.660 --> 04:41.930
Now the effect that we're applying here that we currently have, we can tell what that effect is by

04:41.930 --> 04:43.610
hovering over effect spec.

04:43.610 --> 04:44.420
And here it is.

04:44.420 --> 04:46.580
It's GE damage, right?

04:46.580 --> 04:53.550
So we're applying GE damage and we know that we're creating the effect context in our projectile spell

04:53.550 --> 04:54.420
ability.

04:54.510 --> 05:03.090
So back to data here we see that source object is null instigator ability system component looks like

05:03.090 --> 05:04.260
that's being set.

05:04.260 --> 05:12.270
So that's one of the ones that is set actors looks like a t array of t weak object pointers.

05:12.300 --> 05:14.460
This array appears to be empty.

05:14.490 --> 05:17.100
We also have a hit result set to null.

05:17.100 --> 05:20.190
It's a pointer t shared pointer to a hit result.

05:20.220 --> 05:28.560
We have a world origin all zeroed out and for booleans has world origin replicate source object, replicate

05:28.560 --> 05:31.560
instigator and replicate effect causer.

05:31.560 --> 05:37.500
And we're going to see exactly why these have the values that they have here as well.

05:37.590 --> 05:42.720
So the first question is what's setting these properties that are set?

05:42.750 --> 05:46.250
We know that source object won't be set unless we set it ourselves.

05:46.260 --> 05:47.520
We've done that before.

05:47.520 --> 05:54.210
But instigator effect, causer and instigator ability system component seem to be getting set somehow.

05:54.210 --> 05:56.520
So it's time to investigate.

05:56.520 --> 05:59.640
So I'm going to hit stop and we're going to answer these questions.

05:59.640 --> 06:04.800
Now, the first thing we should look at is where we're creating the effect context that we just looked

06:04.800 --> 06:05.400
at.

06:05.460 --> 06:11.430
We can go to private ability system abilities and open aura projectile spell.

06:11.460 --> 06:15.690
I'm going to go ahead and close all tabs and open aura projectile spell.

06:15.690 --> 06:22.950
And here we can see where we're making the effect context for our G damage effect we're applying here.

06:22.980 --> 06:27.690
We see that we're calling make outgoing spec, which requires the effect context.

06:27.690 --> 06:33.840
And for that context we're passing in whatever we get returned from make effect context.

06:33.840 --> 06:39.330
So whatever make effect context is doing for us, whatever it's setting by default, that's what we're

06:39.330 --> 06:41.760
getting and we've seen what it's doing for us.

06:41.760 --> 06:48.600
We've seen that it's set the effect causer and instigator as well as instigator ability system component

06:48.600 --> 06:53.970
so we can investigate what this function is doing exactly by peeking that definition.

06:53.970 --> 06:56.250
I'm going to go to the definition for it.

06:56.430 --> 06:57.660
Here it is.

06:57.660 --> 07:05.310
And we see that it's making a context handle using the gameplay effect context, handle constructor

07:05.310 --> 07:09.390
and passing in whatever is returned from this function.

07:09.390 --> 07:14.460
U ability system globals Alec Gameplay effect Context.

07:14.490 --> 07:15.990
Now this is pretty simple.

07:15.990 --> 07:20.160
If we go to this declaration, we see that it's just calling new here.

07:20.160 --> 07:21.630
That's all that it's doing.

07:21.990 --> 07:26.730
Really nice function ability system globals, lots of hard work you're doing for us.

07:26.730 --> 07:33.090
So that's what it's doing and it's passing that into the constructor, creating a new context.

07:33.090 --> 07:37.710
It's taking the ability actor info, which is a member variable of this class.

07:37.710 --> 07:38.870
What class are we in?

07:38.880 --> 07:40.740
We're in the ability system component.

07:40.760 --> 07:43.440
That's where make effect context is.

07:43.440 --> 07:48.900
So we're checking that this ability system components, ability actor info is valid here.

07:48.900 --> 07:53.340
So in other words, we can't make an effect context if we don't have valid info.

07:53.340 --> 07:57.210
And then we're taking that context and calling add instigator.

07:57.210 --> 08:05.190
So the gameplay effect context handle class has this add instigator and it looks like it takes two inputs

08:05.220 --> 08:08.400
in instigator and in effect causer.

08:08.610 --> 08:15.690
And for the instigator input parameter, we're getting our ability actor info and getting the owner

08:15.690 --> 08:20.370
actor from it for the effect causer to this function.

08:20.370 --> 08:24.960
The second input we're passing in ability actor info Avatar actor.

08:24.960 --> 08:30.270
So this is why those properties are set because we're calling add instigator and then this function

08:30.270 --> 08:32.310
simply returns the context.

08:32.310 --> 08:34.920
So let's see what Add instigator is doing for us.

08:34.920 --> 08:42.180
I'm going to go to that definition, and this is a function on the effect context handle, right?

08:42.180 --> 08:49.740
So it makes sense that the effect context handle is going to reach into its own data property and simply

08:49.770 --> 08:51.060
set something on that.

08:51.060 --> 08:51.180
So.

08:51.260 --> 08:57.370
Was just calling an instigator, passing in those inputs that we passed in to add instigator.

08:57.370 --> 09:03.190
So what does the effect context class itself do when calling add instigator?

09:03.190 --> 09:07.990
Let's go one level deeper and here we can see that it's doing a few things.

09:08.080 --> 09:14.980
For one, the gameplay effect context is setting a member variable instigator to the instigator passed

09:14.980 --> 09:15.130
in.

09:15.130 --> 09:17.230
Remember what was passed into this?

09:17.230 --> 09:17.770
Right?

09:17.770 --> 09:22.360
We can see by going to the ability system component make effect context, we can see that we're passing

09:22.360 --> 09:24.250
in the owner actor.

09:24.250 --> 09:30.370
So if this were, say, Aura's ability system component, this would be the player state.

09:30.370 --> 09:37.060
And of course for the second input parameter, that Avatar actor is the aura character itself, right?

09:37.210 --> 09:43.420
So we can see here that we're setting the instigator on the effect context to this in instigator, which

09:43.450 --> 09:45.850
for Aura's case is going to be the player state.

09:46.000 --> 09:53.230
Now it's also calling can actor reference be replicated passing that instigator in and if we scroll

09:53.230 --> 09:58.900
up just a little bit we can see that function and how it's determining the result of this.

09:58.900 --> 10:05.200
It's taking the actor making sure it isn't null it's calling is full name stable for networking which

10:05.200 --> 10:07.570
dig deeper if you want to see what that does.

10:07.570 --> 10:10.840
And then it's seeing if the actor is supported for networking.

10:10.840 --> 10:16.510
Again, dig deeper if you want to see what that does, and it also checks to see if the actor is replicated.

10:16.510 --> 10:22.390
So it's doing a few things and after it calls that function, it sets a boolean on the effect context

10:22.390 --> 10:24.160
called replicate instigator.

10:24.160 --> 10:29.920
So this is how it determines that that instigator is a replicated variable.

10:29.920 --> 10:33.280
Now that is why we saw that particular boolean.

10:33.280 --> 10:38.890
I don't know if you looked at those values, but this particular boolean is definitely set, right?

10:38.890 --> 10:45.310
So those two properties on the effect context are already set just from us making one.

10:45.310 --> 10:47.920
Now it also has set effect causer.

10:47.920 --> 10:55.340
If we peek the definition of this, we can see that set effect causer is setting the effect causer variable.

10:55.340 --> 11:02.000
So apparently the gameplay effect context has an effect causer and then it's setting this be replicate

11:02.000 --> 11:07.970
effect causer and it's calling that same function that determines whether or not that actor is a replicated

11:07.970 --> 11:08.330
actor.

11:08.330 --> 11:13.730
So we have that also set for us that explains why that property is set.

11:13.730 --> 11:20.330
So the instigator in effect causer, those are set by default for us just by making an effect.

11:20.330 --> 11:21.380
Context.

11:21.470 --> 11:26.660
Now the gameplay effect context has an instigator ability system component pointer.

11:26.660 --> 11:28.820
It's a weak object pointer.

11:28.820 --> 11:32.030
These are all weak object pointers and we'll see why in a second.

11:32.060 --> 11:39.590
And what it does is it first nulls it out before using ability system globals and calling get ability

11:39.590 --> 11:45.740
system component from actor a ability system globals function and then it sets that instigator ability

11:45.740 --> 11:47.180
system component to that.

11:47.180 --> 11:51.290
So that's another property that was already set for us.

11:51.290 --> 11:58.400
So this add instigator function sets those properties for us and that's why in aura projectile spell,

11:58.400 --> 12:03.650
just calling make effect context results in those properties being set.

12:03.650 --> 12:10.070
And that's why we saw those when we placed a breakpoint and paused execution right there in our attribute

12:10.070 --> 12:10.610
set.

12:10.880 --> 12:15.290
Okay, so we've seen why those properties that were set are set.

12:15.290 --> 12:18.860
That's because make effect context sets those for us.

12:18.860 --> 12:22.070
So the question is, what about all those other properties?

12:22.070 --> 12:26.900
How come make effect context doesn't just fill in the whole effect context?

12:26.930 --> 12:31.580
Well, the effect context doesn't necessarily need to be fully filled out.

12:31.580 --> 12:33.950
It doesn't need all of its properties filled out.

12:33.950 --> 12:41.630
But there are other variables in the effect context struct that we could set if we wanted to notice

12:41.630 --> 12:46.760
that the effect context constructor sets the ability level to a default value of one.

12:46.760 --> 12:52.460
That's why we saw that one when we were checking out that effect context.

12:52.490 --> 12:59.660
We see that world origin is forced to zero force in it to zero and we have booleans that are set to

12:59.660 --> 13:00.620
false here.

13:01.130 --> 13:07.700
Now the effect context also has a constructor that can take in an instigator and effect causer.

13:07.700 --> 13:14.990
And all that really does is zeros out and falses out some of these properties and then calls add instigator.

13:14.990 --> 13:17.840
So we've seen what Add instigator does for us.

13:17.840 --> 13:21.140
So nothing really too spectacular there.

13:21.320 --> 13:24.350
So let's take a look at what else the effect context has.

13:24.350 --> 13:31.490
It has a virtual void Get owned gameplay tags which says returns a list of gameplay tags applicable

13:31.490 --> 13:37.160
to this object, defaults to the owner's tabs and we can always take a look at this.

13:37.160 --> 13:44.930
Get owned gameplay tags function if we want and we can see that it casts the instigator to an AI gameplay

13:44.930 --> 13:51.190
tag asset interface, which does have a couple of functions for getting owned gameplay tags in fact.

13:51.350 --> 13:53.570
It has jet owned gameplay tags.

13:53.570 --> 14:00.710
So what this function does is it sees if the instigator implements the gameplay tag asset interface

14:00.710 --> 14:03.080
and calls, get own gameplay tags on it.

14:03.110 --> 14:08.570
Otherwise, if it doesn't implement that interface, we just get the instigator ability system component

14:08.570 --> 14:11.030
and then get own gameplay tags from that.

14:11.030 --> 14:14.060
So that's all that get own gameplay tags does for us.

14:14.090 --> 14:15.200
Add instigator.

14:15.200 --> 14:16.780
We've seen what that does.

14:16.790 --> 14:18.280
What about set ability?

14:18.290 --> 14:20.150
Let's take a look at set ability.

14:20.920 --> 14:21.850
So here we go.

14:21.850 --> 14:29.530
It's checking the ability that we pass in so it takes one in by a const pointer and then it sets three

14:29.530 --> 14:31.570
variables on the effect context.

14:31.570 --> 14:35.170
So set ability sets, ability instance not replicated.

14:35.170 --> 14:37.240
And what is it setting it with?

14:37.240 --> 14:41.830
Well, it's taking the ability passed in and it's performing a const cast.

14:41.860 --> 14:45.880
We've seen what const casts do in previous sections.

14:45.880 --> 14:50.170
The const cast casts away the const ness.

14:50.200 --> 14:56.950
That's kind of a tongue twister, but we're passing in a const pointer, const, cast, un const.

14:56.980 --> 14:57.370
It.

14:57.370 --> 15:03.370
It casts away the constness and then the function makes a weak object pointer and then sets ability

15:03.370 --> 15:06.100
instance not replicated to that.

15:06.100 --> 15:09.550
So basically this is just a setter for this variable.

15:09.550 --> 15:11.510
It also sets the ability cd0.

15:11.680 --> 15:18.220
So it's taking this game play ability, calling Getclass on it and calling get default object on it.

15:18.220 --> 15:22.510
And this is going to return the class default object for that CDO.

15:22.520 --> 15:26.270
And then we're calling it ability level and setting ability level.

15:26.270 --> 15:29.840
So that sets that property on the effect context.

15:29.840 --> 15:33.320
So set ability sets these three properties for us.

15:33.560 --> 15:36.320
Moving on, we have a getter for the instigator.

15:36.380 --> 15:39.830
It just calls get on the instigator and returns it.

15:39.860 --> 15:47.330
We have a get ability function and if we go to this definition, we see that it does basically the same

15:47.330 --> 15:47.540
thing.

15:47.540 --> 15:50.990
It gets the ability CDO calls get on it.

15:50.990 --> 15:57.110
So why get instigator is defined here but get ability is defined in the CPP file.

15:57.290 --> 15:58.430
Who knows?

15:58.430 --> 16:04.940
I can only imagine it's because this has been worked on by multiple people and some people have different

16:04.940 --> 16:05.870
styles.

16:05.870 --> 16:07.760
So we've seen what get ability does.

16:07.760 --> 16:13.070
We have get ability instance not replicated, which as you can imagine going to the definition, we

16:13.070 --> 16:16.280
can see that it just calls get on that variable.

16:16.280 --> 16:19.730
We also have ability level just returns the ability level.

16:19.730 --> 16:25.760
We also have a getter for the ability system component of the instigator, also for the effect causer.

16:25.760 --> 16:28.070
And then we have a setter for the effect causer.

16:28.070 --> 16:33.770
And by setting the effect causer, we see that we're setting be replicate effect causer so we don't

16:33.770 --> 16:35.660
have to set that manually.

16:35.690 --> 16:38.420
This setter is going to take care of that for us.

16:38.450 --> 16:42.050
Get original instigator is just going to return the instigator.

16:42.050 --> 16:43.250
That's all it does.

16:43.280 --> 16:44.390
This is virtual.

16:44.390 --> 16:50.030
So keep in mind that the virtual versions of these can be overridden if we subclass this.

16:50.180 --> 16:56.390
So again, some more getters we've seen what Add source object does and there's a getter for that.

16:56.420 --> 17:03.410
Now add actors is interesting because it takes in a array of weak object pointers to actors and there's

17:03.410 --> 17:07.250
a B reset that has the default value of false.

17:07.250 --> 17:15.500
So basically add actors is going to check be reset and make sure that the actors array passed in isn't

17:15.500 --> 17:22.160
empty and it's going to reset the array so it'll be emptied out and then actors will have this array

17:22.160 --> 17:23.090
tacked on to it.

17:23.090 --> 17:28.460
So in effect, context has an array of actors that can be set for any reason.

17:28.460 --> 17:35.060
So if you have an effect and you want to stick an array of actors into it, you can stick that in the

17:35.060 --> 17:36.380
gameplay effect context.

17:36.380 --> 17:39.500
And then later on down the pipeline you can access it.

17:39.500 --> 17:45.920
Same thing with the hit result and there's an add hit result that allows you to reset the hit result

17:45.920 --> 17:47.420
with an optional boolean.

17:47.420 --> 17:54.680
And if you do pass in true for that it'll reset the hit result and also set has world origin to false

17:54.680 --> 18:00.110
and then it takes that hit result and sets the hit result variable to that.

18:00.110 --> 18:02.870
And this is creating a shared pointer.

18:02.870 --> 18:08.210
So the effect context stores the hit result as a pointer and we'll see why very shortly.

18:08.210 --> 18:16.340
But if we've reset that hit result, then it's going to add the world origin and add origin.

18:16.340 --> 18:21.560
It's just going to set this world origin vector equal to that hit result trace start.

18:21.710 --> 18:27.530
And then we have net serialize and we're going to talk more about net serialize in a future video when

18:27.530 --> 18:31.070
we have to create some of this stuff on our own.

18:31.070 --> 18:40.130
But this just specifies how this gameplay effect context struct will be serialized when it has to be

18:40.130 --> 18:41.690
sent across the network.

18:41.690 --> 18:49.760
And lastly, we have a to string which really just gets the instigator and returns its name if it's

18:49.760 --> 18:51.980
not null, otherwise it returns none.

18:51.980 --> 18:59.450
And we have a is locally controlled effect context which checks the instigator casts it to a pawn and

18:59.450 --> 19:06.650
if the pawn cast fails, it then tries to cast the effect causer to a pawn and sets that to this local

19:06.650 --> 19:07.670
pawn variable.

19:07.670 --> 19:12.410
And if that's valid, then it calls is locally controlled on that pawn.

19:12.410 --> 19:14.210
So it first tries the instigator.

19:14.210 --> 19:16.880
If that fails, then it tries the effect causer.

19:16.910 --> 19:20.450
If that fails, this function returns false.

19:20.790 --> 19:27.180
And if it doesn't fail, we return is locally controlled on the Pon is locally controlled player does

19:27.180 --> 19:33.090
the same thing, except it then takes the pawn and gets its controller and then calls is local player

19:33.090 --> 19:34.080
controller.

19:34.080 --> 19:41.190
Here's the Add origin which just sets this world origin variable, which happens to be an f vector equal

19:41.190 --> 19:43.260
to whatever we pass in here and then it sets.

19:43.260 --> 19:46.470
This B has world origin boolean to true.

19:46.830 --> 19:50.010
Now we've seen get owned gameplay tags, we know what that does.

19:50.040 --> 19:54.630
And after that, in this file we see net serialized for the context handle.

19:54.630 --> 19:57.360
So we're starting to see things for the context handle.

19:57.360 --> 20:04.140
So at this point we've seen all of the gameplay effect, context, struct and now we know the types

20:04.140 --> 20:09.360
of information that can be stored on it if we want to pass that information along.

20:09.360 --> 20:11.550
So that's pretty cool.

20:11.550 --> 20:17.760
We can create one of these in or a projectile spell and fill it in with more data if we'd like, and

20:17.760 --> 20:23.980
then test this system out, see what those values are equal to in our attribute set.

20:24.010 --> 20:25.480
If we like to do that.

20:25.480 --> 20:32.500
And then we'll go ahead and wrap this video up and discuss possible ways to make our effect context

20:32.500 --> 20:34.030
even more useful.

20:34.030 --> 20:38.560
If we'd like to pass along more interesting data that doesn't exist in it yet.

20:38.560 --> 20:44.890
So rather than calling make effect context right here and make outgoing spec directly, I'd like to

20:44.890 --> 20:46.990
make an effect context right here.

20:47.260 --> 20:55.120
So this will be an F gameplay effect context and actually this is a context handle that we need to make.

20:55.120 --> 21:02.920
So we're going to make effect, context, handle and set it equal to the result of source ask, make

21:02.950 --> 21:04.300
effect context.

21:04.930 --> 21:11.830
And now we have an effect context handle that we can pass in right here into the function make outgoing

21:11.860 --> 21:18.070
spec and now that we have an effect context handle, let's think about the different properties on here

21:18.070 --> 21:19.510
that we can pass along.

21:19.510 --> 21:26.470
So back to gameplay effect types, let's scroll down a little bit to the variables that exist in this

21:26.470 --> 21:27.040
class.

21:27.040 --> 21:28.450
They're all protected.

21:28.600 --> 21:31.600
And let's take a look at this comment right here.

21:31.600 --> 21:34.930
It says, The object pointers here have to be weak.

21:34.930 --> 21:42.220
So weak object pointers because contexts aren't necessarily tracked by garbage collection in all cases.

21:42.280 --> 21:46.120
Now, it would help if you understood what a weak object pointer does.

21:46.600 --> 21:48.880
Weak object pointers are smart pointers.

21:48.880 --> 21:57.190
They're wrappers that can store pointers and a weak object pointer has the property of not taking ownership

21:57.190 --> 22:00.070
of the pointer that it stores.

22:00.070 --> 22:04.150
In other words, it does not participate in reference counting.

22:04.150 --> 22:13.000
You see, smart pointers are reference counted as soon as an object no longer has any references to

22:13.000 --> 22:17.350
it, any pointers that point to it, it's automatically deleted.

22:17.350 --> 22:20.230
That's why smart pointers are useful now.

22:20.260 --> 22:27.160
Weak object pointers have the property of not being reference counted, so reference counting to delete

22:27.160 --> 22:33.850
an object or extend its lifetime for that matter is not affected by a weak object pointer.

22:34.030 --> 22:40.630
And the reason these are weak pointers is because well, it says right here not all effect contexts

22:40.630 --> 22:43.390
are necessarily tracked by garbage collection.

22:43.960 --> 22:47.290
In fact, ours is not here in or a projectile spell.

22:47.290 --> 22:48.880
This is a local variable.

22:48.880 --> 22:51.610
It's not tracked by garbage collection.

22:51.760 --> 22:57.070
And here we can see our different properties and we already know about these.

22:57.070 --> 23:01.090
But here are some useful comments that give us more information.

23:01.090 --> 23:02.080
Here's the instigator.

23:02.080 --> 23:06.910
It says instigator actor, the actor that owns the ability system component.

23:07.090 --> 23:10.540
And we've seen that this gets set for us automatically.

23:10.540 --> 23:16.750
And in the case of Aura, we saw that it was set to the player state which owns our aura ability system

23:16.750 --> 23:17.260
component.

23:17.260 --> 23:18.340
So that's correct.

23:18.370 --> 23:24.610
The effect causer is the physical actor that actually did the damage can be a weapon or a projectile.

23:24.610 --> 23:30.010
In our case it was aura because that was set to the avatar actor.

23:30.280 --> 23:36.610
We have the ability CDO that says the CDO that is responsible for this effect context in parentheses

23:36.610 --> 23:37.690
replicated.

23:37.870 --> 23:41.860
So we've seen that there are different instancing policies for gameplay abilities.

23:41.860 --> 23:44.120
Some are instanced, some are not.

23:44.120 --> 23:52.190
And the class default object is we've seen the result of that get default object function call.

23:52.430 --> 23:56.780
The ability instance not replicated is a pointer to a gameplay ability.

23:56.960 --> 24:03.140
It specifically has the not replicated value property and it says the ability instance that is responsible

24:03.140 --> 24:05.360
for this effect context not replicated.

24:05.360 --> 24:08.390
So we have replicated and not replicated.

24:08.390 --> 24:12.530
We've seen that the ability level is just set to one by default.

24:12.560 --> 24:19.730
We've seen the source object and we can set that, although now we know that if we set this equal to,

24:19.760 --> 24:24.920
say, the Avatar actor, well, we already know that the effect causer is set to that.

24:24.920 --> 24:27.320
So that would be redundant, wouldn't it?

24:27.350 --> 24:33.050
The ability system component that's bound to the instigator is the instigator ability system component.

24:33.050 --> 24:34.970
We've seen that that is set for us.

24:34.970 --> 24:37.040
It's not replicated as well.

24:37.310 --> 24:42.920
We have a array of weak object pointers to actors, which is empty.

24:42.920 --> 24:45.020
We've seen that nothing happens to this array.

24:45.020 --> 24:48.680
It's not set, but it says actors referenced by this context.

24:48.680 --> 24:50.840
So that's for whatever reason we want.

24:50.870 --> 24:52.040
Same for this hit result.

24:52.040 --> 24:54.920
It just has a hit result right there for us.

24:54.950 --> 24:59.390
It says trace information may be null pointer In many cases, yes.

24:59.390 --> 25:04.760
In all cases unless we set it same with the world origin if we set the hit result.

25:04.760 --> 25:09.560
Interestingly the world origin will be set to the trace start of that hit result.

25:09.560 --> 25:14.750
And then we have these Uint eight which are treated like booleans.

25:14.750 --> 25:16.160
We call this a bit field.

25:16.160 --> 25:26.210
Essentially this guarantees that a bit array of contiguous bits will be populated by these variables

25:26.210 --> 25:32.090
which can be checked as if they're booleans, they can be treated like booleans, but they just take

25:32.090 --> 25:34.220
up a single bit altogether.

25:34.220 --> 25:38.690
They all take up at least a minimum of eight bits in a row.

25:38.690 --> 25:45.620
So just because there's four of them here doesn't mean that it only takes up four bits at least one

25:45.650 --> 25:53.480
uint, eight worth of memory is taken, but this allows us to not have one, two, three, four booleans,

25:53.480 --> 25:55.670
each of which would be one byte.

25:55.700 --> 25:57.110
A byte is eight bits.

25:57.110 --> 26:01.790
So as you can see, this is a good deal smaller than using booleans.

26:01.790 --> 26:03.320
It's just an optimization.

26:03.320 --> 26:08.570
Sometimes you'll see it in the engine, sometimes you may even use it yourself and that's it.

26:08.570 --> 26:10.400
That's all of these properties.

26:10.400 --> 26:15.770
And just for fun, let's set some of these, at least the ones we know that aren't already set.

26:15.800 --> 26:22.700
We know instigator and effect causer are already set, and if we want to jog our memories, we can go

26:22.700 --> 26:30.950
back into the attribute set and we can run in debug mode and pause execution right here and see exactly

26:30.950 --> 26:33.950
which properties are not already set for us.

26:36.760 --> 26:37.030
Okay.

26:37.030 --> 26:38.260
I'm going to press play.

26:38.870 --> 26:44.240
Before I launch a fireball, I'm going to place that breakpoint and then launch the fireball.

26:46.260 --> 26:50.190
And let's take a look at our effect context in the handle.

26:50.220 --> 26:55.830
Here's data We know that instigator is set effect causer is set ability.

26:55.860 --> 27:03.480
CTO is not set, but we saw that this could be set automatically if we go into gameplay effect types

27:03.480 --> 27:09.240
and scroll up a bit, we can see that set ability will set ability for us.

27:09.240 --> 27:14.400
So all we need to do is pass in a new gameplay ability into set ability.

27:14.760 --> 27:23.640
So right here in aura projectile spell, we can take our effect context handle and call set ability

27:23.640 --> 27:28.830
and we can pass in the ability well we're inside of our ability or a projectile spell.

27:28.830 --> 27:35.760
So if we pass in this then set ability will take that pointer and what's it going to do with it.

27:35.760 --> 27:40.200
It's going to set ability instance, not replicated ability.

27:40.590 --> 27:43.200
Oh, and even ability level.

27:43.200 --> 27:46.780
So just calling that takes care of three of those.

27:46.960 --> 27:47.350
Okay.

27:47.350 --> 27:52.600
So back to aura attribute set, let's go back to looking at the data here.

27:52.600 --> 27:55.810
We know that ability will be set for us.

27:55.840 --> 27:59.860
So will ability instance not replicated and ability level.

27:59.860 --> 28:01.420
What about source object?

28:01.420 --> 28:03.370
Well, we've seen that before.

28:03.370 --> 28:08.770
We were setting this to the avatar, but that's actually what effect Causer is set to, isn't it?

28:08.770 --> 28:14.110
So if we wanted to, we can set the source object to the avatar.

28:14.110 --> 28:18.550
We could also set it to anything that we'd like to call the source object.

28:18.550 --> 28:26.200
If we go back to Aura projectile spell, we could even set the source object to the projectile itself

28:26.200 --> 28:28.840
so we could take effect.

28:28.840 --> 28:35.200
Context handle call add source object and pass in projectile.

28:36.300 --> 28:39.450
Let's go back and look at our data here.

28:40.430 --> 28:43.460
So we see that we're now going to be setting the source object.

28:43.490 --> 28:47.750
We know that instigator ability system component is set.

28:47.780 --> 28:49.350
What about the actor's array?

28:49.370 --> 28:55.460
Well, at this point, we're just kind of filling things in because we can I don't know if Aura Projectile

28:55.460 --> 29:03.350
spell really has really enough actors to add to the array, but if we like, we could we could take

29:03.350 --> 29:10.610
effect context, handle dot add actors and we could pass in a T array.

29:10.640 --> 29:12.860
We could make a T array.

29:13.520 --> 29:16.340
And we know this is t week object pointers.

29:17.930 --> 29:21.530
And the type is a actor.

29:23.350 --> 29:25.480
We can make this actors here.

29:27.490 --> 29:29.680
And we could add something to the actors.

29:29.680 --> 29:30.900
What are we going to add?

29:30.910 --> 29:32.380
Anything we want.

29:33.610 --> 29:38.290
I'll just pass in projectile just because I can and pass actors in.

29:40.400 --> 29:40.760
Okay.

29:40.760 --> 29:41.630
What else can we set?

29:41.660 --> 29:44.480
We're running out of things here, but let's just see.

29:44.480 --> 29:46.640
We have a hit result right now.

29:46.640 --> 29:47.600
A hit result.

29:47.630 --> 29:50.660
This is a shared pointer to a hit result.

29:50.660 --> 29:52.670
So how are we going to set that?

29:52.670 --> 29:56.860
Well, we've seen how it was done in gameplay effect types.

29:56.870 --> 30:01.820
We can see that it's making a shared pointer here and storing that in hit result.

30:01.820 --> 30:06.260
But add hit result just takes in a hit result and an optional boolean.

30:06.260 --> 30:16.010
So we could just pass one in f hit result hit result and take the effect context handle dot add hit

30:16.010 --> 30:16.760
result.

30:18.300 --> 30:23.580
And pass in hit results, which we know is empty anyway.

30:24.060 --> 30:24.500
Okay.

30:24.510 --> 30:30.360
Looking at data, world origin will be set because we're adding a hit result and then the rest of these

30:30.360 --> 30:33.360
will be set as a result of setting the others.

30:33.360 --> 30:37.980
So we basically set all we can here on this effect context handle.

30:37.980 --> 30:41.100
And really a lot of these are just kind of silly.

30:41.100 --> 30:48.030
We're just adding them because we can, but this allows us to check to see if that information is being

30:48.030 --> 30:49.170
passed along.

30:49.500 --> 30:57.270
So just to prove that this hit result is working, we're going to take hit result dot location and set

30:57.270 --> 30:59.670
that because we do have that here.

30:59.670 --> 31:01.740
It's the projectile target location.

31:01.740 --> 31:04.320
We'll set that location here in the hit result.

31:04.350 --> 31:05.070
Why not?

31:05.700 --> 31:11.940
So now we can run in debug mode and just see how much of this data we can take a look at by placing

31:11.940 --> 31:12.690
a breakpoint.

31:14.670 --> 31:14.910
Okay.

31:14.910 --> 31:16.110
I'm going to press play.

31:17.710 --> 31:23.120
I'm going to stick a breakpoint in the attribute set after we get the effect context handle.

31:23.140 --> 31:24.760
I'm going to launch a fireball.

31:25.790 --> 31:28.520
And we're going to hover over context handle.

31:29.010 --> 31:31.230
And take a look at the data here.

31:31.380 --> 31:34.560
And we're going to see that we have a lot more information.

31:34.860 --> 31:41.790
First of all, the four booleans down here all have true or one set for their value.

31:41.790 --> 31:46.110
Here we see that the instigator is set to or a player state.

31:46.140 --> 31:52.350
The effect causer is set to or a character the ability CTO is set to default to firebolt.

31:52.380 --> 31:55.590
Now we have access to the class here.

31:55.590 --> 32:00.540
We've seen how much we can get information from the class default object.

32:00.540 --> 32:04.110
And because this is a firebolt, it has a projectile class.

32:04.110 --> 32:05.670
That's the firebolt there.

32:05.910 --> 32:08.460
We have the ability instance not replicated.

32:08.460 --> 32:10.650
There's that Firebolt ability instance.

32:10.650 --> 32:15.420
We have the ability level now set to the actual level of the ability.

32:15.420 --> 32:16.650
Here's the source object.

32:16.650 --> 32:22.590
We set that to the projectile itself and we can see that that's Bpy Firebolt cool.

32:22.590 --> 32:26.310
And there are lots of properties that we have access to there.

32:26.310 --> 32:31.390
Now here's the instigator ability system component that's set actors.

32:31.390 --> 32:38.260
We have an array and if we take a look the Firebolt itself, we added that projectile to that actor's

32:38.290 --> 32:39.800
array just because we could.

32:39.820 --> 32:40.990
Here's the hit result.

32:40.990 --> 32:43.090
And if we take a look at the location.

32:43.120 --> 32:48.400
Here's the location we passed through the location of the projectiles target.

32:48.400 --> 32:49.480
So that's there.

32:49.480 --> 32:52.960
And it looks like world origin was set to zero.

32:52.960 --> 32:55.420
That's because it was taken from that hit result.

32:55.420 --> 32:58.090
And that's not something that we set on the hit result.

32:58.090 --> 33:03.910
And then, of course, these four booleans, we've seen that setting these properties with the setters

33:03.940 --> 33:09.190
results in the effect context, setting these properties for us automatically.

33:09.370 --> 33:10.240
Okay, cool.

33:10.240 --> 33:18.550
So now we've seen basically the extent of the usefulness of the gameplay effect context struct, and

33:18.550 --> 33:21.550
it probably has more inside of it than you realized.

33:21.550 --> 33:22.240
Right?

33:22.270 --> 33:27.940
It's good to know about all these things because it's better to take advantage of what's already there

33:27.940 --> 33:35.020
rather than trying to add more code to do something that you want to do if you needed to do something

33:35.020 --> 33:35.980
in addition to this.

33:35.980 --> 33:38.710
But there are some limitations, right?

33:38.740 --> 33:42.880
What if we want to send across information that's not in here?

33:43.180 --> 33:50.800
For one, I'd like to know in my aura attribute set by the time we get to post gameplay effect, execute

33:50.830 --> 33:56.410
whether or not we got a critical hit, whether or not we got to block our gameplay effect.

33:56.410 --> 34:01.120
Context doesn't have a boolean here for whether it was a critical hit.

34:01.120 --> 34:04.840
It does not have a boolean for whether it was a block.

34:05.260 --> 34:08.680
So those are limitations of the effect context.

34:08.950 --> 34:12.490
It doesn't have custom things that we want inside of it.

34:12.520 --> 34:20.040
However, it has a lot of virtual functions which seems to indicate that we could subclass this struct

34:20.050 --> 34:28.300
and that is what I'd like to do in the videos to come so that we can have even more information set

34:28.300 --> 34:30.460
in our gameplay effect context.

34:30.460 --> 34:34.510
So that's what's on the menu and we'll get into that in the videos to come.

34:34.510 --> 34:42.790
So nice informative video, great job sticking through with all of our investigations and studying of

34:42.790 --> 34:45.190
how this class works and what it does.

34:45.220 --> 34:48.160
And I'll see you in the next video.
