WEBVTT

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

00:07.980 --> 00:12.810
In this video, we're going to take care of an edge case, but it's actually an important edge case.

00:12.810 --> 00:19.590
And that's when we have our spell menu open with one of our icons selected and we happen to level up.

00:19.860 --> 00:26.330
So if we level up with an icon selected, we expect those buttons to update, but they don't.

00:26.340 --> 00:29.640
And there are two things that should trigger the update.

00:29.670 --> 00:37.970
One is when spell points change, we just changed from 0 to 1 spell points with an equipped ability

00:37.980 --> 00:42.840
globe selected and we expect the spend point button to be enabled.

00:42.960 --> 00:44.130
That's one case.

00:44.130 --> 00:52.230
And another is if we have a locked spell globe selected and we level up and we expect.

00:53.050 --> 00:57.430
Once it becomes eligible for the spend point button to be enabled.

00:57.430 --> 01:05.260
And for that reason, we're going to need to broadcast those two booleans for the enabled status of

01:05.260 --> 01:10.570
these buttons when spell points changes and when an ability status changes.

01:12.070 --> 01:13.780
So we need to handle that.

01:14.200 --> 01:18.910
So I'm going to close out of the editor and back in our spell menu widget controller.

01:18.910 --> 01:24.490
I'm looking at buying callbacks to dependencies because we have two lambdas here.

01:24.520 --> 01:31.270
One is bound to ability status changed and one is bound to on spell points change delegate.

01:31.660 --> 01:38.590
Now, every time the status of an ability changes, we need to know what the currently selected ability

01:38.590 --> 01:42.940
is, which we're not really setting when we click on a spell globe.

01:43.180 --> 01:45.730
Same goes for when a spell point changes.

01:45.730 --> 01:48.670
We need to know what the currently selected ability is.

01:48.910 --> 01:50.440
So we need to store that.

01:50.440 --> 01:56.830
We could store it as a gameplay tag, for example, but we also need to store that as current status

01:56.830 --> 01:57.710
as well.

01:57.790 --> 01:59.500
And here's the reason why.

01:59.530 --> 02:07.930
When we level up, both, the status of some abilities might change and our spell points is going to

02:07.930 --> 02:08.680
change.

02:08.980 --> 02:15.710
Now let's just say that we've selected a spell globe that is currently locked and that we've just leveled

02:15.710 --> 02:21.830
up and that we now meet the level requirement for that spell, which means it should now be eligible.

02:22.350 --> 02:26.430
In that case, both of these delegates will be broadcast.

02:26.980 --> 02:29.860
And it won't be clear which one will happen first.

02:30.070 --> 02:36.730
Our on spell points change delegate is broadcast from the player state and when that happens, depends

02:36.730 --> 02:42.820
on if we're on the server or if the spell points is replicated down to clients and so on.

02:43.030 --> 02:47.710
And our ability status is broadcast from the ability system component.

02:47.710 --> 02:52.510
And again, that depends on whether we're on the server, on clients and so on.

02:52.510 --> 02:55.450
So it isn't clear which will happen first.

02:55.660 --> 03:03.430
Now we could code this in a way that takes care of either situation, either one being broadcast first.

03:03.430 --> 03:10.630
But we have to be careful because if we don't keep those situations in mind, then we may not code something

03:10.630 --> 03:12.700
that works in all scenarios.

03:13.260 --> 03:19.740
Now let's imagine for a moment that the ability status changed delegate is broadcast first, which means

03:19.740 --> 03:23.610
that spell points change delegate has not yet broadcast.

03:23.790 --> 03:30.260
Now, at this point, we could check what those booleans should be.

03:30.270 --> 03:37.830
And if we check what those booleans should be, say using should enable buttons, we need to know the

03:37.830 --> 03:44.640
status and we need to know the number of spell points before we can determine those two booleans.

03:44.640 --> 03:48.630
And those are for enabling the spell points button and the equip button.

03:49.190 --> 03:54.410
Now let's say that our spell points haven't yet updated, so we've just leveled up.

03:54.900 --> 03:58.200
But let's say our spell points is still zero.

03:58.290 --> 04:04.350
Well, in that case, we would determine the wrong boolean for whether or not our spell points button

04:04.350 --> 04:05.450
should be enabled.

04:05.460 --> 04:06.720
It should be enabled.

04:06.720 --> 04:13.560
But since our spell points hasn't updated yet, it'll still be zero and that button will not enable.

04:14.290 --> 04:19.360
Now, you might think, well, that's okay, because by the time spell points does update, we'll broadcast

04:19.360 --> 04:20.340
it here too.

04:20.350 --> 04:27.760
But in that case, what if we try to get the status from, say, the ability corresponding to whatever

04:27.760 --> 04:34.840
we've selected and that that status has not yet replicated down from the ability system component to

04:34.840 --> 04:35.890
a client?

04:36.190 --> 04:41.680
Well, it's possible that our spell points will be correct, but then our status will not.

04:42.480 --> 04:48.750
Now, the way to get around this is to keep in mind that when we level up, both of these delegates

04:48.750 --> 04:50.640
will be broadcast eventually.

04:50.820 --> 04:57.330
So what we can do is when the status for a given ability changes, if it's our currently selected ability,

04:57.360 --> 04:59.870
we'll store that ability status.

04:59.880 --> 05:06.450
And then shortly after when the spell points change delegate is broadcast, we'll check what that status

05:06.480 --> 05:08.430
is that recently changed?

05:09.070 --> 05:16.900
So we'll keep a local record of the status of our currently selected ability and update it every time

05:16.930 --> 05:20.040
our spell menu widget controller catches wind of the change.

05:20.050 --> 05:24.430
And we'll also keep a local count for the spell points as well.

05:24.580 --> 05:30.880
So when we click on a spell globe, we need to keep track of what that ability is and the status for

05:30.910 --> 05:33.760
that ability which will update as soon as we know.

05:33.910 --> 05:42.880
Now, in order to keep track of both of those, I'd like a custom struct that simply has two gameplay

05:42.880 --> 05:46.750
tags, one for the ability tag and one for the status.

05:46.750 --> 05:54.310
So I'm going to make this struct and call it F selected ability and I'm not even going to expose it

05:54.310 --> 05:54.910
to blueprint.

05:54.910 --> 06:00.130
It's just an internal data structure that I'll use as a tool to keep track of our currently selected

06:00.130 --> 06:00.970
ability.

06:00.970 --> 06:04.990
And we'll have an gameplay tag called ability inside of it.

06:05.020 --> 06:11.990
We'll set it equal to an empty gameplay tag by default and we'll have an F gameplay tag called status

06:12.110 --> 06:15.740
and we'll set it equal to an empty gameplay tag as well.

06:16.640 --> 06:22.130
So we'll just have an F selected ability and we'll keep track of our currently selected ability and

06:22.130 --> 06:23.180
its status.

06:23.330 --> 06:26.260
So we'll make one right here in the private section.

06:26.270 --> 06:32.480
So it's going to be an F selected ability, we'll call it selected ability and we can initialize it

06:32.480 --> 06:34.100
with two gameplay tags.

06:34.100 --> 06:37.100
We'll use F or a gameplay tags get.

06:38.770 --> 06:42.640
And for the ability, we'll just initialize it with abilities.

06:42.670 --> 06:43.330
None.

06:43.930 --> 06:48.670
And for the status, we'll just initialize it with the locked status.

06:48.670 --> 06:57.520
So we're going to get that static get function and we'll say abilities status locked just to give it

06:57.520 --> 06:59.380
a default value.

06:59.500 --> 07:05.500
But as soon as the spell menu widget controller knows that it's changed, we'll store that new value

07:05.530 --> 07:13.210
and we'll also have an INT 32 called current spell points and we'll set that to zero by default.

07:13.810 --> 07:14.170
Okay.

07:14.170 --> 07:20.590
So what we'll do is we'll set our selected ability every time we select a spell globe.

07:20.890 --> 07:24.940
So we'll go into spell globe selected right here.

07:25.060 --> 07:32.440
And as soon as our spell globe has been selected, we know its ability tag and we've also taken a look

07:32.440 --> 07:34.120
at what its ability status is.

07:34.120 --> 07:37.360
So by this point, we know the status of it.

07:37.890 --> 07:45.600
So we can set our selected ability, we can say selected ability, dot ability equals ability tag.

07:46.890 --> 07:48.210
And we know its status too.

07:48.240 --> 07:49.860
So we can say selected ability.

07:49.890 --> 07:54.630
Dot status equals ability status.

07:56.410 --> 08:02.020
So at this point, we know our selected ability and its status and we're storing both of these.

08:02.200 --> 08:08.230
Now we need to go up to bind callbacks to dependencies, because in these lambdas we're going to know

08:08.230 --> 08:10.050
when the status has changed.

08:10.060 --> 08:11.920
So we need to update that.

08:11.920 --> 08:17.680
If the ability tag, whose status changed is equal to our currently selected ability.

08:17.830 --> 08:19.520
Otherwise, we don't care.

08:19.540 --> 08:28.780
So we're going to check we're going to say if our selected ability, dot, ability, dot matches, tag

08:28.780 --> 08:35.590
exact, and we're going to see if it matches the ability tag for the ability, that's status just changed.

08:35.860 --> 08:43.150
If that's the case, then we can take our selected ability and set its status to the newly updated status

08:43.150 --> 08:43.810
tag.

08:45.520 --> 08:52.090
And at this point, because we now know the status, we can broadcast those booleans up to our widgets

08:52.090 --> 08:54.100
so they can update the buttons.

08:54.340 --> 09:01.730
In other words, we want to create a local BOOL for each of those booleans, set those based on our

09:01.730 --> 09:08.120
currently selected ability status and our spell points that we've been setting every time they change

09:08.120 --> 09:10.160
and broadcast this delegate.

09:10.160 --> 09:14.810
So we're going to take these four lines and we're going to paste them up here.

09:18.680 --> 09:23.780
Now, the difference here is that the status is going to be status tag.

09:25.180 --> 09:29.320
And the spell points will be the spell points that we've been keeping track of.

09:29.350 --> 09:31.540
Our current spell points here.

09:32.590 --> 09:36.040
So every time they change, we'll keep track of them here.

09:36.160 --> 09:42.820
And to keep track of them, we do so right here in spell points change Delegate What we do is we set

09:42.820 --> 09:47.680
our current spell points and we set them equal to the spell points value.

09:48.040 --> 09:54.390
And as soon as spell points have changed, we also need to do these for lines right here.

09:54.400 --> 09:56.500
So we're going to paste these down here.

09:59.580 --> 10:05.380
Only the status is going to be the status that we've stored in our selected ability.

10:05.400 --> 10:07.320
So we're going to say selected ability.

10:10.710 --> 10:16.470
Dot status and we're passing in our current spell points, which is equal to spell points.

10:17.540 --> 10:19.760
And then we broadcast here.

10:20.510 --> 10:29.360
So every time the status changes or the spell points change, we update our local variables, keeping

10:29.390 --> 10:30.600
track of these.

10:30.620 --> 10:37.760
And when we level up, one will happen, then the other and both will have access to the current information

10:37.760 --> 10:40.220
that we have in the spell menu widget controller.

10:40.220 --> 10:46.760
So with that we can compile and see how this works by testing these edge cases.

10:48.900 --> 10:55.770
So back in the editor, all we need to do is press play, open our menu and select one of our spell

10:55.770 --> 10:57.630
globes and level up.

10:57.720 --> 10:59.760
So let's see what happens.

11:02.560 --> 11:03.610
One more should do it.

11:03.610 --> 11:09.310
And I'm expecting the pinpoint button to become enabled because our spell points will become one.

11:11.200 --> 11:13.210
And it does, Sure enough.

11:13.210 --> 11:19.930
Now the next edge case is going to be when we have this spell globe selected, because when we level

11:19.930 --> 11:27.010
up, it's going to become an eligible spell, which means the spin point button should also become enabled

11:27.010 --> 11:28.240
in that case.

11:28.240 --> 11:29.650
So let's level up.

11:32.580 --> 11:33.840
And there we have it.

11:33.870 --> 11:36.240
It's updating as well.

11:36.630 --> 11:38.610
So that handles the edge cases.

11:38.610 --> 11:44.040
And we can't test them all because we don't have the ability to change the statuses yet.

11:44.070 --> 11:51.690
We can't spend a point and change this spell globe from eligible to unlocked, for example.

11:51.720 --> 11:56.970
So our next steps is to start actually making these buttons functional.

11:57.000 --> 12:02.550
All we're doing right now is setting their enabled status based on what's selected.

12:02.550 --> 12:08.430
But now we need to actually make these buttons do something when we click on them.

12:09.020 --> 12:10.460
And we'll do that next.

12:11.270 --> 12:12.230
Excellent job.

12:12.230 --> 12:14.060
I'll see you in the next video.
