WEBVTT

00:06.880 --> 00:08.010
Welcome back.

00:08.020 --> 00:13.540
Now we're concerned with activating and deactivating our passive abilities.

00:13.570 --> 00:17.190
Now we've discussed in the last video what that means.

00:17.200 --> 00:23.350
If we equip one of these to our passive slot down here, it's going to activate.

00:23.350 --> 00:29.170
If we push it out by replacing it with a new passive ability, it's going to deactivate.

00:29.170 --> 00:31.570
So we need to figure out how to do that.

00:31.570 --> 00:36.850
And on top of that we need to know when an ability has been activated and deactivated.

00:36.850 --> 00:43.690
And for that reason, I'm going to open up my passive gameplay abilities and use event activate ability

00:43.690 --> 00:46.060
and event on end ability.

00:46.090 --> 00:51.580
So we're going to print strings here so we know when an ability has been activated.

00:51.760 --> 00:57.610
Another thing I'd like to change is right down here in the details panel, our net execution policy.

00:57.610 --> 01:01.120
Now we're going to be doing this from the server.

01:01.120 --> 01:08.800
So earlier in the course I mentioned that server initiated is an ability instantiated by the server

01:08.800 --> 01:12.220
but will also be run on the local client if one exists.

01:12.220 --> 01:18.400
So this is one of those rare cases where you'd actually want to initiate the ability on the server.

01:18.400 --> 01:25.690
As the server makes the determination to equip an ability, and equipping an ability is directly related

01:25.690 --> 01:27.850
to activation for passive abilities.

01:27.850 --> 01:34.450
So strangely it's appropriate for server initiated for the net execution policy.

01:34.480 --> 01:39.880
We're going to do that for all three, and we're going to have a print string to know when the ability

01:39.880 --> 01:41.080
has been activated.

01:41.080 --> 01:46.090
So I'm going to make the print string I'm going to change its color to green.

01:47.910 --> 01:53.520
And it's going to say Halo of protection activated.

01:54.610 --> 01:58.490
We'll give it more of a duration, say four seconds.

01:58.510 --> 02:06.250
I'm going to duplicate that node and use on end ability and say Halo of protection deactivated.

02:06.410 --> 02:07.480
We'll just say ended.

02:07.510 --> 02:09.880
Ended is more appropriate.

02:09.880 --> 02:12.220
And we'll make this red.

02:12.250 --> 02:13.510
In that case.

02:14.190 --> 02:22.380
Now I'm going to copy these two Ctrl C and open up life siphon and life siphon can do the same thing

02:22.500 --> 02:28.920
on activate, but we're going to say life siphon instead of halo of protection.

02:28.920 --> 02:34.320
So we're going to say life siphon activated and life siphon ended.

02:34.440 --> 02:35.880
Life siphon.

02:37.060 --> 02:38.260
We'll connect those.

02:38.290 --> 02:42.160
I'll go to my class defaults and set my.

02:42.190 --> 02:45.460
Net execution policy to server initiated.

02:45.490 --> 02:46.230
Compile.

02:46.240 --> 02:48.310
Save and compile save.

02:48.310 --> 02:49.550
We're done with those.

02:49.570 --> 02:51.970
But we want mana siphon as well.

02:51.970 --> 02:53.740
So control V here.

02:54.630 --> 02:55.710
Hooking these up.

02:55.920 --> 02:58.590
These will say, man a siphon.

03:02.760 --> 03:04.920
Activated and ended.

03:05.310 --> 03:09.390
And we'll go ahead and set in the class defaults.

03:09.420 --> 03:15.780
Net execution policy to server initiated for this compile save and close.

03:16.880 --> 03:18.350
We can save all now.

03:19.010 --> 03:22.240
So the question is how are we going to activate these?

03:22.250 --> 03:23.780
I'm going to go to one player.

03:23.780 --> 03:25.820
How are we going to activate them.

03:25.820 --> 03:30.710
When we equip one of our abilities we want it activated.

03:30.710 --> 03:32.660
When it's unequipped we want to push it out.

03:32.660 --> 03:34.250
So let's think about this.

03:34.280 --> 03:37.130
We're going to need to go back to the C plus plus side.

03:37.130 --> 03:40.460
So I'm going to open our ability system component.

03:40.460 --> 03:42.500
We're back to server equip ability.

03:42.500 --> 03:44.840
This is where it's all going to happen.

03:44.840 --> 03:51.350
And I'm going to move this over to the right and get my header file right there just next to it.

03:51.350 --> 03:55.160
So we are going to need to think about what's going on here.

03:55.190 --> 03:59.180
Now the first thing we're doing is we're getting our gameplay tags.

03:59.180 --> 04:00.200
That's good.

04:00.230 --> 04:07.460
We're storing the previous slot, but this is actually the previous slot in a sense of what slot did

04:07.460 --> 04:13.490
this particular ability have before before we went in and changed things.

04:13.490 --> 04:13.970
Right.

04:13.970 --> 04:17.750
So this is really just the previous slot that we're remembering.

04:17.750 --> 04:24.200
If we're equipping an ability that had a different slot in the first place, so we can go and clear

04:24.200 --> 04:25.700
that previous slot.

04:26.420 --> 04:31.430
We also have the status of the ability, and we're checking that status to make sure it's valid here.

04:31.520 --> 04:36.110
We're seeing if the status is equipped or unlocked if that's the case.

04:36.140 --> 04:41.500
We can then move on and we don't want to do anything if the status isn't valid.

04:41.510 --> 04:43.340
So that's all good.

04:43.490 --> 04:45.110
Then we do all this stuff.

04:45.110 --> 04:51.650
We mark the ability spec dirty and then call client equip ability so the spell menu can update itself.

04:52.640 --> 04:55.160
Now it's this stuff that I'm concerned with.

04:55.190 --> 05:02.050
We're going to need to basically replace this because this all has to do with offensive abilities.

05:02.060 --> 05:05.900
It doesn't really take anything into account for passive abilities.

05:05.930 --> 05:10.370
It clears all the abilities of this given slot.

05:10.400 --> 05:16.640
It clears the current selected ability of its slot, which basically means that after calling these

05:16.640 --> 05:21.320
two functions, we don't know which abilities are associated with which slots.

05:21.320 --> 05:27.680
We don't know which ability might have been there before and how are we going to deactivate it if it

05:27.680 --> 05:29.790
was passive in that case?

05:29.880 --> 05:30.320
Right.

05:30.320 --> 05:37.940
So all of this stuff is going to be moved on down, and we're going to actually comment it out for now

05:38.030 --> 05:39.620
and get it out of the way.

05:39.650 --> 05:45.350
We don't want to just delete it because, you know, as a general rule, I don't delete all my hard

05:45.350 --> 05:50.420
work that I know works until I have something else that I know works, that I'm going to replace it.

05:50.600 --> 05:52.670
Until then, we comment it out.

05:53.490 --> 05:54.900
Okay, so what are we going to do?

05:54.930 --> 06:04.080
We're going to handle activation slash deactivation for passive abilities.

06:04.470 --> 06:06.540
That's on our menu here.

06:06.750 --> 06:09.120
So we need some pseudocode.

06:09.120 --> 06:16.440
We need to know first of all as we're clicking right we have an ability selected from our spell tree.

06:16.470 --> 06:18.570
Either it's offensive or passive.

06:18.570 --> 06:23.190
And we're clicking on our spell globes down in our equipped row.

06:23.340 --> 06:27.910
If we're clicking on one is it empty or is it not empty?

06:27.930 --> 06:31.790
In other words, is there an ability in this slot already?

06:31.800 --> 06:34.860
Now, I'd like a function to check that.

06:34.860 --> 06:37.080
I want to check if there's a slot.

06:37.080 --> 06:44.610
In other words, I want a slot is empty function that returns a boolean that can take in a slot.

06:45.310 --> 06:47.560
So why don't we go ahead and make that function?

06:47.560 --> 06:53.950
We're going to be making a lot of little ease of use utility functions as we change this code so that

06:53.950 --> 06:57.490
our code stays readable and looks good.

06:57.760 --> 07:01.690
So right here these are basically our utility functions.

07:01.690 --> 07:07.210
We're going to add more to these I'm going to have a bool returning function called slot is empty.

07:08.050 --> 07:11.530
And it's going to take a const f gameplay tag reference.

07:12.760 --> 07:14.530
And we'll call it slot.

07:15.140 --> 07:21.720
And I think I'd like to refer to input tags as slots basically in all of these functions.

07:21.740 --> 07:27.500
So even though we have something like get input tag from ability tag, I'd kind of like this function

07:27.500 --> 07:30.160
to be called get slot from ability tag.

07:30.170 --> 07:37.190
We can easily rename it by right clicking on it, going to refactor, selecting rename.

07:37.190 --> 07:40.400
And we can call this get slot from Ability Tag.

07:42.140 --> 07:43.190
Click next.

07:43.760 --> 07:46.730
And now it's called get slot from ability tag.

07:46.940 --> 07:49.580
So anyway we have a slot is empty function.

07:49.580 --> 07:57.110
We need to generate the definition for it and decide how we're going to figure out whether or not a

07:57.110 --> 08:01.380
given input tag is occupied with a gameplay ability.

08:01.400 --> 08:03.500
How do we know that?

08:03.590 --> 08:08.450
Well, we're going to need to check all of the gameplay abilities in our activatable abilities.

08:08.450 --> 08:19.730
So we're going to say for gameplay ability, spec, reference ability, spec in get Activatable abilities.

08:20.450 --> 08:26.390
Now, we've mentioned before that whenever we loop over Activatable abilities, we should make a scope

08:26.390 --> 08:29.930
lock as we're doing here and get spec from ability tag.

08:29.930 --> 08:32.020
We should make an active scope lock.

08:32.030 --> 08:38.600
We should do that here, and we should also just make sure that everywhere we're looping through activatable

08:38.600 --> 08:42.710
abilities, we're doing this because I know there are some cases where we're not.

08:42.920 --> 08:46.430
So I'm just going to search for get activatable.

08:47.860 --> 08:52.210
Abilities and just search through the entire file.

08:52.570 --> 08:55.690
As here we have ability input tag pressed.

08:55.690 --> 08:57.040
We're looping over it.

08:57.070 --> 09:02.920
That's dangerous to not place a scope lock because abilities can be added and removed.

09:02.920 --> 09:06.130
So we don't want that to happen in the middle of this.

09:06.310 --> 09:08.050
So we'll place that lock there.

09:08.050 --> 09:11.000
We see the same thing in ability input tag held.

09:11.020 --> 09:13.300
We'll place a lock here as well.

09:15.840 --> 09:19.070
And here in ability input tag released.

09:19.080 --> 09:19.770
Same thing.

09:19.770 --> 09:21.090
We'll place a lock there.

09:22.100 --> 09:26.930
And then it looks like the rest of the file is behaving.

09:26.930 --> 09:30.680
So I don't see any other loops without those locks.

09:30.680 --> 09:37.520
But we definitely did a good thing there, making sure to place a scope lock for all of those loops

09:37.520 --> 09:39.560
over get activatable abilities.

09:39.650 --> 09:41.600
Now for slot is empty.

09:41.630 --> 09:47.750
I need to know if this particular ability spec has a slot, right?

09:47.750 --> 09:53.690
It has this slot we're passing in and its dynamic ability tags.

09:53.750 --> 09:59.870
So in other words, we can return ability spec dot dynamic ability tags.

10:00.900 --> 10:08.370
And we can check has tag exact because these containers have functions like that has tag exact needs

10:08.370 --> 10:09.630
to know what tag.

10:09.630 --> 10:11.040
We're going to check the slot.

10:11.040 --> 10:17.760
And this right here alone could be a pretty useful function called ability has slot.

10:18.180 --> 10:20.640
So I'm going to make that a function as well.

10:20.880 --> 10:26.940
One that returns a bool ability has slot.

10:26.940 --> 10:30.510
And it's going to take in the ability spec by const reference.

10:30.510 --> 10:31.370
So f.

10:31.470 --> 10:32.970
Gameplay.

10:35.280 --> 10:36.390
Ability spec.

10:36.780 --> 10:42.480
Const reference called spec and a const gameplay tag.

10:42.480 --> 10:44.310
Reference called slot.

10:44.520 --> 10:45.030
Important.

10:45.030 --> 10:48.860
When you're passing in an ability spec, you don't want to make a copy of it.

10:48.870 --> 10:52.660
You want the original, so a const reference is a good way.

10:52.680 --> 10:54.540
A pointer is another good way.

10:55.740 --> 11:00.150
So ability has slot is just going to return this.

11:01.160 --> 11:05.870
Dynamic ability tags that has tag exact only.

11:05.870 --> 11:07.740
We're going to use RSpec here.

11:07.760 --> 11:10.730
And now we have this nice function ability has slot.

11:10.730 --> 11:12.200
And I'd like to check that here.

11:12.200 --> 11:16.580
What I'm going to do is say if ability has slot.

11:19.290 --> 11:26.850
And we'll pass in that ability spec and we'll pass in the slot and we'll return true.

11:27.180 --> 11:30.120
And at the very end of here, we'll return false.

11:30.450 --> 11:32.520
If we don't ever make it there.

11:33.120 --> 11:39.120
So this allows us to break out of this loop early, as soon as we find an ability that has this slot.

11:39.820 --> 11:44.500
Okay, so now we have a slot is empty and we can use this.

11:44.500 --> 11:46.810
So we can go back to where we were.

11:47.750 --> 11:48.890
Right here.

11:49.540 --> 11:50.170
We've made.

11:50.170 --> 11:51.880
Our slot is empty.

11:51.910 --> 11:53.100
How are we going to use it?

11:53.110 --> 11:59.650
Well, I'd like to check to see if there's an ability in this slot already that we're dealing with that

11:59.650 --> 12:01.090
we've passed up to the server.

12:01.090 --> 12:04.870
So I'm going to say if not, slot is empty.

12:06.700 --> 12:08.440
Now we're going to pass that slot in.

12:09.130 --> 12:17.200
So if not slot is empty, we're going to say in a little side comment here, there is an ability in

12:17.200 --> 12:23.710
this slot already deactivate and clear its slot.

12:24.550 --> 12:27.610
So that means that we have an ability selected.

12:27.610 --> 12:31.280
And we're clicking on a slot that's already got an ability there.

12:31.300 --> 12:32.680
So we know the slot.

12:32.710 --> 12:34.330
We know that it's not empty.

12:34.360 --> 12:40.330
We also need to know what ability is there so we can deactivate it, at least if it's a passive ability.

12:40.330 --> 12:40.900
Right.

12:40.900 --> 12:47.410
And if we want to deactivate the ability, it would help if we knew which one it was so we can identify

12:47.410 --> 12:48.910
it with the ability spec.

12:49.090 --> 12:58.380
So I'm going to need a function that can return whatever ability spec is associated with a given slot.

12:58.390 --> 13:05.710
In other words, we need some kind of function like get spec with slot, which can take in a slot and

13:05.710 --> 13:07.420
return an ability spec.

13:07.690 --> 13:13.810
So I'm going to make that function and I'm going to make it return a gameplay ability spec pointer.

13:13.840 --> 13:20.230
That way we can always check if the pointer is null, and if it's null, then there is no ability spec

13:20.230 --> 13:21.520
with this slot, right?

13:21.520 --> 13:26.680
So I'm going to return an gameplay ability spec pointer from this function.

13:26.680 --> 13:33.670
It's going to be called Get Spec with slot, and it's going to take a const gameplay tag by reference

13:33.670 --> 13:34.960
called slot.

13:36.100 --> 13:38.140
So let's make this function.

13:39.390 --> 13:42.700
And how are we going to return the correct spec?

13:42.720 --> 13:47.910
Well, we need to loop through the abilities and see which one has this spec.

13:48.150 --> 13:53.130
So that means we need an EF scoped ability list lock.

13:53.340 --> 13:59.670
We'll call it Active Scope Lock and it needs the ability System component.

14:00.700 --> 14:04.280
So we dereference this and pass it in and now we can loop.

14:04.300 --> 14:09.640
We're going to loop over F gameplay ability spec references.

14:11.760 --> 14:19.530
Ability spec and get activatable abilities and I want to check in each abilities.

14:19.560 --> 14:26.910
Ability tags and its dynamic ability tags, and I want to see if it has this given slot.

14:26.940 --> 14:27.540
Right.

14:27.540 --> 14:29.640
So we can take ability spec.

14:31.220 --> 14:33.710
Dot ability tags.

14:34.100 --> 14:35.870
Dynamic ability tags.

14:35.870 --> 14:36.680
That is.

14:37.250 --> 14:43.400
And we can see if it has a specific tag has tag exact and we can pass in the slot.

14:44.100 --> 14:48.450
So as we're looping over the ability specs, we'll say if.

14:49.790 --> 14:53.710
Ability spec dynamic ability tags has tag exact.

14:53.720 --> 14:57.110
If that's the case, yes, then we'll return the ability spec.

14:57.110 --> 15:00.710
But we have to return a pointer an address in other words.

15:00.710 --> 15:03.620
So we're going to return the address of ability spec.

15:04.160 --> 15:08.270
Now, if we make it to the end of the for loop, we return nothing.

15:08.270 --> 15:15.230
We return a null pointer as dynamic ability tags doesn't have the slot for every single ability spec

15:15.230 --> 15:17.060
in Activatable abilities.

15:17.390 --> 15:21.670
So now we have get spec with slot a nice utility function.

15:21.680 --> 15:23.750
Let's go back to what we were doing.

15:24.080 --> 15:25.790
So let's get the spec.

15:25.790 --> 15:33.410
I'm going to make an F game play ability spec pointer, and I'll call this spec with slot.

15:33.710 --> 15:37.700
And I'll set it equal to get spec with slot passing in the slot.

15:37.700 --> 15:43.220
So here we know that the slot that we're trying to occupy is already occupied.

15:43.220 --> 15:43.690
Right.

15:43.730 --> 15:49.730
And this is the pesky ability sitting in that slot that we want to push out.

15:49.760 --> 15:52.010
Now this could be a null pointer.

15:52.010 --> 15:54.050
So we're going to make sure that it's not.

15:54.610 --> 16:02.590
So if spec with slot is not a null pointer, then at this point we know we have a valid slot there.

16:02.620 --> 16:08.620
We're trying to replace it with a slot in our hand, and this would be a good time to see if they're

16:08.620 --> 16:09.670
not the same ability.

16:09.670 --> 16:16.330
Because if they are, well, there's nothing needed at this point and we can return out of this whole

16:16.330 --> 16:17.380
functionally.

16:17.380 --> 16:24.460
So I'm going to say if and we're going to take the ability tag we're messing with here and we're going

16:24.460 --> 16:26.530
to call matches tag exact.

16:27.180 --> 16:28.580
What are we going to match it against?

16:28.590 --> 16:34.830
Well, we need to know the ability tag associated with this pesky slot that we're dealing with.

16:34.860 --> 16:37.500
So we need to get ability tag.

16:39.290 --> 16:43.940
From not spec but slot so we don't have git.

16:43.970 --> 16:45.320
Ability tag from slot.

16:45.320 --> 16:47.750
But we do have git ability tag from spec.

16:47.750 --> 16:49.220
And we do have the spec.

16:49.220 --> 16:55.730
So we're going to call git ability tag from spec that takes in a ability spec not by pointer.

16:55.730 --> 16:57.430
So we have to dereference.

16:57.440 --> 16:58.100
That's okay.

16:58.100 --> 16:59.720
We made sure it's not null.

16:59.720 --> 17:03.950
So we're going to say star spec with slot pass that in.

17:03.950 --> 17:10.220
And in this case our ability tag that we're trying to equip into this slot as the same as the ability

17:10.220 --> 17:15.260
tag in the slot, we're trying to equip an ability where it already is so we can return.

17:15.290 --> 17:21.230
Now we don't just want to return though, because down here at the bottom, Client Equip ability is

17:21.230 --> 17:23.750
taking care of some things in the spell menu side.

17:23.750 --> 17:28.610
Remember, our spell menu has a little flashing rectangle down there waiting for us to click on it.

17:28.610 --> 17:34.250
And if we click on it and the server just returns and does nothing, it's going to still be there waiting

17:34.250 --> 17:35.420
for us to click on it.

17:35.450 --> 17:36.590
We're going to keep clicking.

17:36.590 --> 17:37.880
The rectangle won't go away.

17:37.880 --> 17:39.560
It's going to be really frustrating.

17:39.560 --> 17:45.590
So we just need to call client equip ability to make sure that that doesn't happen.

17:45.590 --> 17:49.580
So we'll go ahead and get that there and return early.

17:49.670 --> 17:54.680
So we can go ahead and put a comment here so we know what this means.

17:54.680 --> 18:01.160
We'll say is that ability the same as this ability.

18:01.760 --> 18:05.390
If so we can return early.

18:07.640 --> 18:13.160
However, if we don't return early here, now we have some stuff to do, right?

18:13.190 --> 18:18.860
And really the most important thing is, is this a passive ability?

18:18.860 --> 18:22.970
Because this is handling things for the offensive abilities too.

18:23.000 --> 18:27.680
So I'd like to be able to know if this is a passive ability.

18:27.680 --> 18:32.390
I'd like an is passive ability function that can take in that spec.

18:33.370 --> 18:38.290
So why don't we make an is passive ability that returns a boolean for us.

18:38.500 --> 18:41.800
So back to our handy dandy functions.

18:41.800 --> 18:43.000
We're going to make another bool.

18:43.000 --> 18:52.030
Returning function is passive ability and it's going to take a const f gameplay ability spec reference

18:52.030 --> 18:53.140
called spec.

18:54.220 --> 18:56.220
And this is just going to tell us yes or no.

18:56.230 --> 18:58.300
We can make this a const function.

18:58.300 --> 19:00.850
And I'm going to generate the definition.

19:01.210 --> 19:04.930
And how is this function going to work.

19:05.020 --> 19:07.640
Well this one's a little bit more interesting.

19:07.660 --> 19:10.840
Our ability type passive or offensive.

19:10.870 --> 19:12.730
That's in our ability info.

19:12.760 --> 19:17.100
We need to get the ability info if we want to check an ability type.

19:17.110 --> 19:20.530
So this function needs to get you ability info.

19:22.330 --> 19:23.850
So we'll get that data asset.

19:23.860 --> 19:31.690
We'll call this ability info, make a local variable and use you or ability system library get ability

19:31.690 --> 19:32.410
info.

19:32.410 --> 19:34.600
Now it needs a world context object.

19:34.600 --> 19:37.300
I always like to pass in the avatar actor.

19:37.300 --> 19:45.640
It's just a habit and for the ability info we need to find the ability info for a given ability tag.

19:45.640 --> 19:49.540
Well, we have a spec, so we need to get the ability tag from the spec.

19:49.570 --> 19:51.760
We can say gameplay tag.

19:52.060 --> 19:55.870
This can be const and we'll call this ability tag.

19:56.260 --> 20:02.920
And we'll call Get Ability tag from spec because we have the spec and now we have the ability tag.

20:03.100 --> 20:09.490
Now what we need here is the ability info struct that we can get from ability info.

20:09.520 --> 20:17.860
In other words we can make a const f or a ability info struct reference called info and we can set that

20:17.860 --> 20:19.810
equal to ability info.

20:21.570 --> 20:25.350
Find ability info for tag passing in that ability tag.

20:26.010 --> 20:29.550
And once we have that info we can get the type from it.

20:29.580 --> 20:34.830
We can say const f gameplay tag ability type.

20:36.000 --> 20:39.450
And we can get info dot ability type right.

20:39.480 --> 20:43.260
No need for so many intermediate local variables by the way.

20:43.260 --> 20:44.880
Just making things clear here.

20:44.880 --> 20:45.900
What we're doing.

20:45.900 --> 20:49.230
And this function returns a bool so we can return.

20:49.230 --> 20:50.700
And what are we going to return.

20:50.700 --> 20:56.970
We're going to take our ability type and see if it is the passive ability type.

20:56.970 --> 21:07.380
So we can say if ability type dot matches tag exact f or a gameplay tags get dot abilities.

21:08.640 --> 21:09.390
Type.

21:10.260 --> 21:17.310
Passive and of course ability info could be a const pointer that is not const.

21:18.340 --> 21:22.650
Const and we have an is passive ability function.

21:22.800 --> 21:26.610
So now that we can know we can go back to what we were doing down here.

21:26.640 --> 21:28.770
We have an is passive ability.

21:28.800 --> 21:32.040
We can check that for the spec with slot.

21:32.070 --> 21:37.710
This pesky spec that's sitting right there in the slot that we want to push out.

21:37.710 --> 21:42.510
So we're going to say if is passive ability we're going to pass in that spec.

21:42.510 --> 21:44.310
But spec with slot is a pointer.

21:44.310 --> 21:48.000
So we need to dereference spec with slot pass that right in.

21:48.420 --> 21:51.180
So spec with slot is a passive ability.

21:51.180 --> 21:52.230
We're pushing it out.

21:52.230 --> 21:55.140
That means we need to deactivate it.

21:55.140 --> 21:57.510
And how do we deactivate it.

21:57.510 --> 22:03.180
Well remember we made a delegate f deactivate passive ability here.

22:03.180 --> 22:06.480
And our passive abilities all bind to this.

22:06.480 --> 22:12.780
So we can broadcast the ability tag through this, and all of our passive abilities will respond to

22:12.780 --> 22:14.210
it and check that tag.

22:14.220 --> 22:16.740
So we're going to take deactivate passive ability.

22:16.740 --> 22:21.030
We're going to broadcast it and we're going to broadcast the ability tag.

22:21.210 --> 22:24.090
What's the ability tag for spec with slot.

22:24.120 --> 22:32.430
Well we can get ability tag from spec and pass in the Dereferenced spec with slot like that.

22:32.580 --> 22:39.150
So this is going to result in our passive ability with this tag ending itself.

22:39.820 --> 22:41.560
That's exactly what I want to do.

22:42.160 --> 22:49.600
So once we've done that, now that this ability in this slot has taken care of ending itself, now we

22:49.600 --> 22:54.300
don't care what its ability tag is, we don't care what its input tag is.

22:54.310 --> 23:01.480
In fact, we should clear its input tag of the slot that it was in, and we have a function to clear

23:01.480 --> 23:03.970
a slot if we search for clear slot.

23:04.300 --> 23:12.040
We saw that we were using it down there and it's going to take a spec get its input tag.

23:12.610 --> 23:16.150
Check its dynamic ability tags and remove that tag.

23:16.760 --> 23:19.730
It also marks the spec dirty to force it to replicate.

23:19.730 --> 23:21.910
But we're going to be doing that already.

23:21.920 --> 23:24.590
So I think I'm just going to remove that part from it.

23:24.590 --> 23:29.180
And we'll just have clear slot here, which by the way, can be made static.

23:29.180 --> 23:32.930
Now that we've moved that member function call out of it.

23:32.930 --> 23:35.510
So clear slot here it is.

23:35.510 --> 23:38.150
Down here we can make it a static function.

23:39.280 --> 23:46.000
And going back to where we were right here after we've deactivated the passive ability, whether or

23:46.000 --> 23:51.250
not it's passive, we still want to clear the slot so it doesn't have that input tag anymore.

23:51.250 --> 23:52.780
So we're going to call Clear Slot.

23:53.830 --> 24:00.670
And we're going to pass in that spec and clear slot takes in the spec as a pointer so we can just pass

24:00.670 --> 24:01.990
that pointer on in.

24:02.890 --> 24:08.170
Okay, so this takes care of the case where the slot was not empty.

24:08.560 --> 24:11.620
So what do we do when we've passed that point?

24:11.620 --> 24:15.850
Because that just takes care of pushing that slot out, right?

24:16.180 --> 24:19.990
Now we need to put our new ability in that slot.

24:20.020 --> 24:21.610
Now here's the thing.

24:21.610 --> 24:28.610
Now that this ability could be passive, we need to activate it if it's not already active.

24:28.630 --> 24:30.930
It doesn't have a slot already.

24:30.940 --> 24:35.760
That's why I thought it would be nice to have an ability has slot function.

24:35.770 --> 24:41.910
We made that up here as a useful function that one of our other functions can use.

24:41.920 --> 24:43.120
Here we can check that.

24:43.120 --> 24:48.640
We can say if not ability has slot.

24:49.540 --> 24:51.640
Now this takes the ability spec.

24:51.670 --> 24:54.340
We have a pointer called ability spec.

24:54.460 --> 24:58.390
Now ability has slot is going to return true.

24:58.420 --> 25:01.690
If the ability has a specific slot right.

25:01.720 --> 25:04.510
We'd have to pass in the slot that we're checking.

25:04.510 --> 25:10.300
But I want to know if the ability has any slot, not just a specific slot.

25:10.300 --> 25:13.440
I want to know if it doesn't have a slot at all.

25:13.450 --> 25:18.700
So in other words, I want a function called ability has any slot.

25:19.720 --> 25:21.970
So I'm going to make another function actually.

25:21.970 --> 25:27.520
So next to ability has slot I'm going to call this ability has any slot.

25:29.460 --> 25:37.080
And this will take in just an ability spec, but not a slot because I want it to return true if it has

25:37.080 --> 25:39.330
any slot, no matter what it is.

25:39.330 --> 25:47.790
And when I say slot, of course we're talking about input tags, so we need to return our spec dot dynamic

25:47.790 --> 25:49.080
ability tags.

25:49.110 --> 25:52.890
Dot has tag but not has tag exact.

25:52.920 --> 25:57.000
We want to check has tag and just check for input tag.

25:57.150 --> 26:01.020
We want to return true if it has any tag with input tag in it.

26:01.020 --> 26:09.540
So I'm going to use F gameplay tag request gameplay tag using the F name input tag.

26:09.540 --> 26:16.650
Now yes, we're using an F name and variables are better and we could just go into gameplay tags and

26:16.650 --> 26:17.970
make an input tag.

26:17.970 --> 26:19.290
Gameplay tag.

26:19.290 --> 26:22.470
Yes, you could do all that, of course, but I'm not.

26:22.470 --> 26:23.880
I'm just going to do it this way.

26:23.880 --> 26:25.830
I think it's totally fine in this case.

26:25.830 --> 26:28.050
And this can be a static function.

26:28.080 --> 26:31.770
In fact, ability has slot and ability has any slot.

26:31.770 --> 26:34.290
Both can be static functions.

26:35.490 --> 26:37.620
We'll go ahead and make them both static.

26:38.380 --> 26:41.380
And with that we have ability has any slot.

26:41.950 --> 26:46.510
So let's go back and we're going to use ability has any slot.

26:46.660 --> 26:49.090
And we'll make a little comment here.

26:49.120 --> 26:52.150
If not ability has any slot.

26:52.180 --> 26:54.670
This ability doesn't yet have one.

26:54.670 --> 27:01.270
So we're going to say ability doesn't yet have a slot.

27:01.270 --> 27:04.390
In other words it's not active.

27:06.610 --> 27:13.450
Now that's important because if this is a passive ability we're going to want to activate it.

27:13.480 --> 27:20.410
So I'm going to check if is passive ability passing in ability spec.

27:21.640 --> 27:22.480
Dereferenced.

27:22.480 --> 27:23.290
Of course.

27:23.530 --> 27:25.810
Then I want to try activate a.

27:27.240 --> 27:29.670
And I can pass in ability back.

27:30.300 --> 27:31.860
But it's got to be a handle.

27:31.860 --> 27:34.980
So we need to pass an ability spec handle here.

27:35.340 --> 27:43.230
So with that, now we're activating abilities and deactivating them based on the correct conditions.

27:43.230 --> 27:48.690
If the ability doesn't yet have a slot, we know that it's not active because we're activating it every

27:48.690 --> 27:52.500
time it's being put into a slot for the first time.

27:52.740 --> 27:55.590
Now that takes care of activating it.

27:55.590 --> 27:57.060
But what about its input tag?

27:57.060 --> 27:59.070
It now needs to have a tag.

27:59.070 --> 28:03.090
So we need a function to assign a slot to an ability.

28:03.090 --> 28:07.650
So something like assign slot to ability.

28:08.940 --> 28:16.410
Which can take in a spec and a slot, because this can handle not only removing any input tags that

28:16.410 --> 28:22.800
it may have, because even though if we're in this if statement, it's the first slot it's getting,

28:22.800 --> 28:24.360
it doesn't have one already.

28:24.360 --> 28:26.400
But we're not in that if statement.

28:26.430 --> 28:28.080
This only takes care of that case.

28:28.080 --> 28:33.960
But in the other cases where there might be a slot already on this ability, we need to clear that and

28:33.960 --> 28:35.870
then add the new slot.

28:35.880 --> 28:37.950
So I'm going to make a new function.

28:38.550 --> 28:39.630
It's going to be void.

28:39.630 --> 28:43.650
And I'm going to call it assign slot to ability.

28:44.340 --> 28:46.710
So this needs a couple of things.

28:46.710 --> 28:51.060
It needs an F game play ability spec reference.

28:51.090 --> 28:52.320
Now we're changing it.

28:52.320 --> 28:54.240
So it's not going to be const.

28:54.390 --> 28:56.220
And we're going to call this spec.

28:57.080 --> 29:02.030
And a const gameplay tag reference called slot.

29:03.850 --> 29:11.980
So assigned slot two ability is going to first of all remove its input tag if it has one, and then

29:11.980 --> 29:13.480
assign it a new slot.

29:13.930 --> 29:17.110
So we already have a function to clear a slot.

29:17.140 --> 29:18.670
We can take clear slot.

29:18.700 --> 29:21.340
We can pass in our spec.

29:21.350 --> 29:23.500
Now clear slot needs a pointer.

29:23.500 --> 29:25.930
So we have to pass in the address of spec.

29:25.960 --> 29:26.860
No problem.

29:26.860 --> 29:29.680
We have the address of operator to help us out.

29:29.860 --> 29:34.930
Now we also want to add this new slot to the dynamic ability tag.

29:34.930 --> 29:41.200
So we're going to take spec dot dynamic ability tags call add tag and pass in slot.

29:41.380 --> 29:44.950
So two things out with the old in with the new.

29:44.950 --> 29:48.970
And we have a nice new function that can be static.

29:49.000 --> 29:52.540
So we can make this a static function as well.

29:53.740 --> 30:00.070
And with that we can go back to what we were doing down here where we have assigned slot to ability.

30:00.070 --> 30:01.510
We can call that function now.

30:01.510 --> 30:05.560
So we have assign slot to ability takes in a spec.

30:05.560 --> 30:10.330
We're going to pass in the Dereferenced ability spec and we're going to pass in the slot.

30:11.140 --> 30:15.070
And after all that we can mark the ability spec dirty.

30:15.070 --> 30:18.940
And after all that we can call client equip ability.

30:18.940 --> 30:22.450
In other words we can delete these old comments.

30:22.750 --> 30:26.740
And now we have a new algorithm.

30:26.980 --> 30:35.140
And this algorithm should handle activating and deactivating abilities deactivating via a broadcast

30:35.170 --> 30:36.070
of a delegate.

30:36.070 --> 30:38.710
And those abilities should all be bound to it.

30:38.890 --> 30:44.050
So with that, let's hit the debug button and launch the engine.

30:47.490 --> 30:48.060
Okay.

30:48.060 --> 30:51.660
So first thing I'm going to try with one player first.

30:51.660 --> 30:55.350
And I'm going to go ahead and I need to level up.

30:55.350 --> 30:56.850
So let's get some XP.

30:58.030 --> 31:01.630
Level four now got three spell points.

31:01.630 --> 31:04.720
I'm going to spend one and equip this one.

31:04.840 --> 31:08.110
And look at this halo of protection activated.

31:08.110 --> 31:15.280
So far so good I'm going to go ahead and spend a point on my next spell here and equip that down here.

31:15.310 --> 31:17.380
Look at that life siphon activated.

31:17.380 --> 31:19.960
So activating these abilities is working.

31:19.960 --> 31:22.390
Let's see what happens when we take a new one.

31:22.390 --> 31:25.030
Spend a point on it and push one of these out.

31:25.030 --> 31:26.800
Let's push out Halo of protection.

31:26.800 --> 31:28.780
Now this one is called mana siphon.

31:28.780 --> 31:35.680
So we should see mana siphon activated and Halo of Protection deactivated if all goes well.

31:35.680 --> 31:38.590
So I'm going to click equip and click on Halo of Protection.

31:38.590 --> 31:43.720
Looking up to the top left of my screen and mana siphon activated.

31:43.720 --> 31:47.560
But Halo of Protection was not deactivated.

31:47.560 --> 31:49.630
So we need to find out why.

31:50.700 --> 31:55.020
So activating abilities is working.

31:55.080 --> 31:58.710
It's deactivating that we have an issue with.

31:59.530 --> 32:03.340
So we need to find out if we're actually broadcasting this delegate.

32:03.340 --> 32:05.110
I'm going to place a breakpoint there.

32:06.290 --> 32:07.370
I'm going to level up.

32:10.950 --> 32:14.220
And I'm going to go ahead and equip Halo of Protection.

32:14.220 --> 32:18.060
And I'm just going to try to push it out right away with life siphon.

32:19.250 --> 32:21.560
Okay, so I didn't get my breakpoint.

32:23.480 --> 32:26.470
So that tells me we never made it this far.

32:26.480 --> 32:30.650
And if I scroll up, what could prevent me from making it into here?

32:30.650 --> 32:36.980
Well, now I've got my eye on slot is empty, so I'm going to go ahead and go back to that function

32:36.980 --> 32:40.580
and make sure I didn't make any silly logic mistakes.

32:40.700 --> 32:48.380
So the function is called slot is empty, which means we want to return true if there are no abilities

32:48.380 --> 32:49.910
that have this slot.

32:49.940 --> 32:54.380
Well, we're checking if ability has slot and looks like we're returning.

32:54.410 --> 33:00.680
True if it does, but we want to return true if none of these have the slot.

33:00.770 --> 33:08.690
So my true and false is are reversed, I need to return false if the ability has this slot.

33:08.690 --> 33:15.140
So if any of our abilities that we stumble upon happen to have this slot, we can return false because

33:15.140 --> 33:16.430
the slot is not empty.

33:16.460 --> 33:20.690
Otherwise we'll return true if we get to the end of this.

33:20.690 --> 33:23.300
And then our slot really is empty.

33:23.300 --> 33:28.310
So for that reason I'm going to fix that and I can hit rerun.

33:28.900 --> 33:30.460
And we can try this again.

33:32.420 --> 33:33.080
All right.

33:33.080 --> 33:35.840
So I'm going to go ahead and level up again.

33:36.860 --> 33:38.120
Get out of here, Gabby.

33:38.120 --> 33:42.440
And I'm going to go ahead and equip Halo of Protection.

33:42.440 --> 33:42.890
There we go.

33:42.890 --> 33:43.880
It's activated.

33:43.880 --> 33:48.590
And I'm going to try to push it out first thing with the red ability clicking on here.

33:48.590 --> 33:49.820
And there we go.

33:49.820 --> 33:53.420
Halo of protection ended life siphon activated.

33:53.420 --> 33:55.520
That was what I wanted to see.

33:55.550 --> 33:59.990
Let's go ahead and full screen this because there are some pretty small icons down here.

33:59.990 --> 34:01.160
But let's test the others.

34:01.160 --> 34:05.360
Let's get our mana siphon, spend a point on it, equip it.

34:05.360 --> 34:06.500
I'll put it down here.

34:06.530 --> 34:07.460
Mana siphon.

34:07.460 --> 34:08.060
Activate it.

34:08.060 --> 34:08.750
Cool.

34:08.780 --> 34:10.670
I'm going to select Halo of protection.

34:10.670 --> 34:12.260
Equip and replace.

34:12.260 --> 34:12.800
Life.

34:12.800 --> 34:13.580
Siphon.

34:13.580 --> 34:14.090
Life.

34:14.090 --> 34:14.750
Siphon ended.

34:14.780 --> 34:16.250
Halo of protection activated.

34:16.250 --> 34:17.960
Exactly what I wanted to see.

34:17.990 --> 34:23.360
Let's try equipping Halo of Protection to the slot that it's already in.

34:24.280 --> 34:24.640
Okay.

34:24.670 --> 34:31.330
Nothing happened as far as activation or deactivation of abilities, but because we called client activate

34:31.330 --> 34:37.570
ability and went ahead and pushed along that same data down, at least we could end that animation,

34:37.570 --> 34:41.800
play a little sound, and get back to square one.

34:41.920 --> 34:48.160
Now I'm going to go ahead and just try different combinations and make sure that we're ending abilities

34:48.160 --> 34:51.120
when we should and activating abilities when we should.

34:51.130 --> 34:52.630
So let's just see what happens.

34:52.630 --> 34:54.970
I'm going to take the blue and click on the red.

34:54.970 --> 34:57.910
We should be pushing the red out and pushing the blue up.

34:57.910 --> 34:59.650
So the red should be deactivated.

34:59.650 --> 35:04.630
That's life siphon and the blue should not be deactivated and it should not be reactivated.

35:04.630 --> 35:06.130
Nothing should happen to it.

35:06.130 --> 35:07.330
Let's see what happens.

35:07.540 --> 35:11.680
And we just see life siphon ended, which is exactly what we should see.

35:11.980 --> 35:18.670
So pressing the red ability and clicking on the blue now should deactivate the blue.

35:18.700 --> 35:22.000
We should deactivate Mana Siphon and activate Life siphon.

35:22.000 --> 35:23.470
Let's see if that happens.

35:24.210 --> 35:31.920
Okay life siphon was activated, but man is siphon was not so man is siphon needs to be deactivated.

35:31.920 --> 35:40.770
And in this case we clicked on a slot that was not empty and we didn't get to deactivate it.

35:40.800 --> 35:44.040
Let's see if we can get the blue to push out the red.

35:44.070 --> 35:45.210
So that worked.

35:45.210 --> 35:47.400
But when the red pushed out the blue.

35:48.070 --> 35:50.140
Looked like it didn't do anything.

35:51.810 --> 35:55.170
Let's just make sure that mana siphon does have.

35:55.170 --> 35:57.000
Oh, there there's the issue.

35:57.000 --> 36:01.770
So I suspect it was working, but my print string was not connected.

36:01.770 --> 36:03.240
Let's try that again.

36:03.420 --> 36:06.120
So got to level up first.

36:08.190 --> 36:11.880
And what I'll do is I'll spend a point on all three.

36:13.450 --> 36:17.560
I'm going to full screen here and we'll equip mana siphon.

36:17.590 --> 36:19.180
Mana siphon activated.

36:19.180 --> 36:21.640
And we'll push it out with life siphon.

36:21.850 --> 36:23.840
Now we see mana siphon ended.

36:23.860 --> 36:25.240
Life siphon activated.

36:25.240 --> 36:28.810
So it's looking like everything is working as it should.

36:28.840 --> 36:32.500
We're now activating and deactivating our passive abilities.

36:32.500 --> 36:33.850
And they stay active.

36:33.880 --> 36:39.150
They stay active as long as they're right here in our slots in the HUD.

36:39.160 --> 36:41.990
So as long as we see them there, they're active.

36:42.010 --> 36:48.820
Now, that's not exactly enough for me to just see icons and just know that these abilities are active.

36:48.820 --> 36:50.650
I like to see particle systems.

36:50.650 --> 36:52.360
This is Unreal Engine after all.

36:52.360 --> 36:58.690
We have Niagara, we have some of the best particle systems on the planet, and it'd be a shame not

36:58.690 --> 37:00.070
to take advantage of that.

37:00.070 --> 37:03.580
So my next steps for this are.

37:03.580 --> 37:10.030
I'd like to assign particle systems to play while these passive abilities are active.

37:10.030 --> 37:12.910
And that way we can have something cool to look at.

37:12.910 --> 37:20.740
And also visually, we'll know when halo of protection is active, when mana siphon is active versus

37:20.770 --> 37:22.030
life siphon.

37:22.030 --> 37:27.040
And if we swap them out, I want to see those particle systems swap out as well.

37:27.400 --> 37:29.050
So that's our next step.

37:29.230 --> 37:30.520
I'll see you soon.
