WEBVTT

00:00.590 --> 00:02.630
Welcome to your next quest.

00:03.080 --> 00:08.210
Okay, so you finished your last assignment, and the project manager says, that's great, excellent

00:08.210 --> 00:11.510
thinking when it came to taking the level into account.

00:11.540 --> 00:14.480
Now, I have another task for you.

00:14.510 --> 00:20.840
I'd like you to bind to that on XP change delegate we created in the player state and I'd like you to

00:20.840 --> 00:24.140
bind to it on the widget controller for the overlay.

00:24.170 --> 00:24.770
Why?

00:24.800 --> 00:31.100
Because our overlay is going to have an XP bar, so it needs to know when our XP changes.

00:31.490 --> 00:37.310
Now as a bonus, see if you can figure out what that percent will be for the XP bar.

00:37.340 --> 00:44.120
Now this is deceptively a little bit more difficult than you might think as the way that we calculate

00:44.120 --> 00:46.700
the percent depends on what level we are.

00:46.730 --> 00:49.010
So see if you can figure that out.

00:49.010 --> 00:55.640
And as a hint, does the overlay widget controller need level up info because level up info contains

00:55.640 --> 00:59.200
those level up requirements for XP for each level.

00:59.210 --> 01:02.400
So see if that's something you're going to need.

01:02.400 --> 01:05.880
And if you do, where should level up info go?

01:05.910 --> 01:11.720
We created the data asset blueprint, but we never set that on any of our classes, right?

01:11.730 --> 01:19.200
So try to think about where a good spot for that level up info should go and try to keep in mind that

01:19.200 --> 01:24.930
we may need that level up info in our widget controller, both on clients and server.

01:24.930 --> 01:30.960
And just remember that the game mode doesn't exist on the clients, it only exists on the server.

01:30.960 --> 01:34.910
So right away I'm telling you it probably shouldn't go in the game mode.

01:34.920 --> 01:38.700
So give it a little bit of thought, see if you can figure that out.

01:38.700 --> 01:41.520
And if you're up for a bonus challenge, give that a try.

01:41.550 --> 01:47.520
But either way, I'd like you to bind to on XP changed in the overlay widget controller.

01:47.520 --> 01:50.880
So pause the video and conquer this quest now.

01:53.800 --> 02:00.550
Now we're going to need to bind to our on XP change delegate in our widget controller.

02:00.580 --> 02:05.050
Now it's possible that we may decide to bind to on level changed as well.

02:05.050 --> 02:07.480
So that's something to keep in mind.

02:07.570 --> 02:14.380
But when we bind to on XP change, we're going to want to figure out what that XP bar percent is going

02:14.380 --> 02:14.680
to be.

02:14.680 --> 02:16.400
So we'll keep that in mind as well.

02:16.420 --> 02:22.090
Well, the first thing we should do is go to our widget controller class that's going to be in UI widget

02:22.090 --> 02:25.480
controller and it's our overlay widget controller.

02:25.690 --> 02:28.510
Here is where we're going to want to bind to the delegate.

02:28.510 --> 02:28.900
Right?

02:28.900 --> 02:35.860
So I would like to make a callback function to bind because it's going to be a little bit more complicated

02:35.860 --> 02:39.100
than just passing through that value up to widgets.

02:39.130 --> 02:42.000
We're going to be performing some calculations, right?

02:42.010 --> 02:48.250
So I'm going to make a function in the protected section, and this is going to be for when our XP changes,

02:48.250 --> 02:55.250
we're going to bind it to the delegate on the player state called on XP change delegate, which can

02:55.250 --> 02:58.970
only have functions bound to it that can receive an INT 32.

02:59.000 --> 03:03.050
So here in overlay widget controller, we're going to make a function.

03:03.050 --> 03:12.770
It's going to be void and I'm going to call this on XP changed, which will take an INT 32 called New

03:12.770 --> 03:16.520
XP and we'll go ahead and generate the definition for it.

03:16.520 --> 03:20.890
And before we figure out what to do in this function, we're going to bind it.

03:20.900 --> 03:27.680
So we need to go up to our bind callbacks to dependencies where we're binding to all of our callbacks

03:27.680 --> 03:31.400
and we have a few bound to the ability system component.

03:31.430 --> 03:36.650
We have some bound to the attributes set, but we don't have anything bound to the player state.

03:36.650 --> 03:39.410
So we're going to have to get our player state, aren't we?

03:39.410 --> 03:46.220
So up here as we're getting our aura attributes set, I'd like to cast to the Aura player state as well.

03:46.220 --> 03:53.390
So I'm going to go ahead and create a const pointer to it and it's going to be of type A or a player

03:53.390 --> 03:54.020
state.

03:56.710 --> 03:59.830
And I'm going to go ahead and include the header file.

03:59.830 --> 04:03.040
So alt enter and writer will do that for me.

04:03.460 --> 04:09.610
Adding the include for it to send player slash player state and I'm going to call this or player state.

04:12.030 --> 04:15.000
Now I'm going to use cast checked for this.

04:18.630 --> 04:21.960
By the way, in a package build, this compiles as a static cast.

04:21.960 --> 04:24.690
So you have that bit of optimization there too.

04:24.720 --> 04:31.410
Now, this will be an A or a player state and we're going to cast our player state variable that all

04:31.410 --> 04:32.850
widget controllers have.

04:34.740 --> 04:40.320
Now we know that we have the aura player state and we can bind callbacks to the aura player state.

04:40.350 --> 04:46.950
I'm going to actually move this aura player state local variable up to the first line and the first

04:46.950 --> 04:53.710
thing we'll do is bind to the player state callbacks and then the attribute set will be after that.

04:53.730 --> 05:00.720
So after getting the aura player state, we can take Aura player state and we can access that public

05:00.750 --> 05:04.950
on XRP changed delegate and we can bind to it.

05:04.980 --> 05:07.050
We're going to use Add new object.

05:08.390 --> 05:15.920
And with the user object being this and the function being the address of you overlay widget controller

05:15.950 --> 05:17.510
on XP changed.

05:17.750 --> 05:23.120
And of course we're going to get red squiggles here because now we're actually changing something on

05:23.120 --> 05:26.750
the player state so it can't be a const pointer anymore.

05:26.780 --> 05:30.200
If we're going to want to bind callbacks to delegates.

05:30.410 --> 05:30.800
Okay.

05:30.800 --> 05:37.190
So now we have a callback bound to on Change delegate so we'll know in the widget controller when our

05:37.190 --> 05:38.720
XP has changed.

05:38.750 --> 05:43.940
Now we need to broadcast something up to our progress bar in Blueprint.

05:43.940 --> 05:48.380
But the thing is, we can't just broadcast the total amount of XP.

05:48.680 --> 05:55.190
We need to find out what the percentage of that bar should be and that's going to involve the use of

05:55.190 --> 05:56.660
our level up info.

05:56.690 --> 05:59.480
So what class should have the level up info?

05:59.510 --> 06:05.630
Well, I think the player state is probably a good class to keep that level up info as it is the class

06:05.630 --> 06:10.650
that has the level stored on it and also the player state is replicated.

06:10.650 --> 06:16.950
So if we access the player state in our widget controller on the client, we can get level up info from

06:16.950 --> 06:17.610
there.

06:17.760 --> 06:24.060
So I think a great place for it is here on Aura Player State right here in the public section.

06:24.150 --> 06:27.870
So I'm going to go ahead and declare a public variable.

06:27.870 --> 06:29.940
It's going to be a T object pointer.

06:30.920 --> 06:40.280
Now its type will be you level up info and we can forward declare that we don't have to include level

06:40.280 --> 06:41.480
up info up here.

06:41.480 --> 06:43.340
We can just say class.

06:43.370 --> 06:52.490
You level up info here and we can create this variable called level up info and we can make it a new

06:52.520 --> 06:57.650
property with edit defaults only so we can set it in our player state blueprint.

06:57.650 --> 06:59.450
So we'll remember to do that.

06:59.450 --> 07:06.380
And in our widget controller we can access that when determining how much our percent bar should show.

07:06.380 --> 07:09.440
And that's going to be all in on XRP changed.

07:09.440 --> 07:15.290
And once we figure out that percent, we can broadcast something up to our widgets.

07:15.290 --> 07:17.420
Now what are we going to broadcast?

07:17.450 --> 07:21.230
Well, we're going to broadcast a float for the percent of our XRP bar.

07:21.230 --> 07:26.720
And if we want to broadcast a float, we have an on attribute change signature we can use.

07:26.750 --> 07:28.280
It's not an attribute.

07:28.310 --> 07:36.030
Our percentage for the XRP bar technically isn't a gameplay attribute, but we can still use this same

07:36.030 --> 07:36.480
delegate.

07:36.510 --> 07:42.690
If the name bothered us, we could create a new delegate with a different name capable of broadcasting

07:42.690 --> 07:43.050
a float.

07:43.050 --> 07:45.390
But that's a little bit silly.

07:45.390 --> 07:49.950
I think we could just use this delegate signature and create a new delegate.

07:49.950 --> 07:56.160
In fact, I'm going to give it a new property so I can take one of our other attribute changed signatures

07:56.160 --> 07:57.360
and copy it.

07:57.360 --> 08:02.880
And down here at the bottom of it in the public section, I'm going to paste, but change the name and

08:02.880 --> 08:05.370
this will be on XRP.

08:05.580 --> 08:15.660
Percent changed and we'll tack on delegate at the end there and this will be gas slash XRP for the category.

08:15.690 --> 08:18.090
So now we have a delegate to broadcast.

08:18.120 --> 08:24.900
Now we just need to figure out what that percent should be and broadcast that in on XRP changed.

08:24.930 --> 08:26.820
Now here in on XRP changed.

08:26.820 --> 08:33.780
We're going to want the level up info and we know that that exists on the player state so we can access

08:33.780 --> 08:35.700
the player state with a cast checked.

08:36.150 --> 08:39.240
We'll go ahead and copy that line and paste it there.

08:39.270 --> 08:43.530
Don't worry about using cast checked each time our XRP changes.

08:43.560 --> 08:49.740
As I mentioned, this turns into a static cast in builds, so this is not something to worry about performance

08:49.740 --> 08:50.370
wise.

08:50.640 --> 08:54.660
So in on XRP changed, What exactly are we going to do here?

08:54.660 --> 09:03.600
Well, we need to get our level up info, so I'm just going to say you level up info, we'll get a pointer

09:03.600 --> 09:04.470
to that.

09:04.500 --> 09:10.230
We'll call this level up info and we'll use our aura player state.

09:11.500 --> 09:13.580
And get that level up info.

09:13.600 --> 09:14.830
Public variable.

09:15.010 --> 09:21.240
And what we'll do with our level up info is we're going to perform lookups for data from it.

09:21.250 --> 09:26.350
So this can be a const pointer and if we like, we can perform a check on that.

09:26.350 --> 09:38.560
We can say check level up info and we can even use a check f if we want a descriptive message.

09:38.740 --> 09:46.210
When level up info is a null pointer, we can say unable to find level up info.

09:47.710 --> 09:49.930
Please fill out.

09:51.460 --> 09:54.310
Or a player state blueprint.

09:55.520 --> 10:02.810
So we'll definitely know if we forgot that we'll get a crash or an assertion in debug mode with that

10:02.810 --> 10:03.620
message.

10:03.800 --> 10:09.620
So how are we going to know what our percent bar should be when we know what our XP is?

10:09.650 --> 10:16.460
Well, level up info has a handy function that can tell us what level we should be for a given experience

10:16.460 --> 10:17.420
value.

10:17.720 --> 10:21.110
We can take our level up info and call that function.

10:21.110 --> 10:24.590
It's called find level for XP.

10:25.070 --> 10:28.820
It takes an int 32 we can pass in new XP.

10:29.090 --> 10:36.200
Now we made level up info, const and find level for XP could be const, so one has to change.

10:36.200 --> 10:43.220
Either this function can be const and then our pointer can be const or the function can not be const.

10:43.220 --> 10:47.030
But if it's not const then our pointer can't be const.

10:47.270 --> 10:52.100
Well, if it's just a lookup to find level for XP, it could easily be const.

10:52.130 --> 10:59.580
We can go into our public ability system data folder and to level up info and we can make find level

10:59.580 --> 11:01.650
for XP a const function.

11:01.650 --> 11:04.590
We'll have to do it in the header and the CPP file.

11:05.520 --> 11:11.550
And once we do that, then here in the widget controller we can call this function no problem.

11:11.550 --> 11:13.410
So this gives us the level.

11:13.410 --> 11:21.300
It's an int 32 returning function so we can create an int 32 called level and now we know what our level

11:21.300 --> 11:21.750
is.

11:21.780 --> 11:29.490
Now that's important because we need to know how much XP to get from the beginning of one level to the

11:29.490 --> 11:30.780
end of that level.

11:30.780 --> 11:33.780
In other words, that Delta XP requirement.

11:34.050 --> 11:39.840
And if we're going to be finding Delta XP from one level to another, we should know what that max level

11:39.840 --> 11:40.170
is.

11:40.170 --> 11:44.670
So we should have a const int 32 called max level.

11:44.700 --> 11:51.420
I said const, we'll make it constant, a second max level equals and we'll get our level up info and

11:51.420 --> 11:56.880
access that level up information and get the number of elements in it.

11:56.880 --> 12:01.770
So the number of elements in it should be the max level possible.

12:01.770 --> 12:04.410
So these both can be constants.

12:06.130 --> 12:07.750
So we know our current level.

12:07.750 --> 12:10.000
We know the max level possible.

12:10.120 --> 12:17.950
We need to figure out that delta between the amount of XP when we first reached our current level to

12:17.950 --> 12:20.170
the amount of XP at the end of that level.

12:20.170 --> 12:22.300
In other words, it's level requirement.

12:22.630 --> 12:31.300
So first I'm going to place a check here that says if level is less than or equal to max level, that

12:31.300 --> 12:33.010
way, we're in range here.

12:33.430 --> 12:37.630
But I'm also going to have an and and make sure level is greater than zero.

12:39.370 --> 12:42.130
Because it's a zero level doesn't make sense either.

12:42.430 --> 12:48.130
Now, the level requirement for our current level that can be accessed from our level up information.

12:48.130 --> 12:54.280
So I'm going to make a const int 32 called level requirement or level up requirement.

12:55.160 --> 12:58.040
And that's going to be our level up info.

12:59.590 --> 13:04.360
Accessing level up information from it and indexing it at our current level.

13:04.510 --> 13:09.730
But that's a struct which contains the level up requirements, so we have to access that.

13:09.760 --> 13:12.850
Now I want to know the previous level requirement.

13:12.850 --> 13:18.400
In other words, the XP that we were at at the very beginning of our current level, that's the level

13:18.400 --> 13:20.530
up requirement for the previous level.

13:20.650 --> 13:28.840
So I'm going to make a const int 32 called previous level up requirement and that's going to be level

13:28.840 --> 13:29.890
up info.

13:31.460 --> 13:39.020
Accessing level up information, indexing it at level minus one, the previous level, and then getting

13:39.020 --> 13:40.760
that level up requirement.

13:40.790 --> 13:42.710
So now we have both of those.

13:42.740 --> 13:45.440
Now we can see the difference between them.

13:45.440 --> 13:54.500
A delta, we can say const int 32, Delta level requirement, we'll call it, and that's simply going

13:54.500 --> 13:58.490
to be the current level requirement minus the previous one.

14:00.530 --> 14:07.310
And it's actually level up requirement minus previous level up requirement.

14:09.020 --> 14:15.020
The reason we need this delta is so that we know what to divide our current exp value by.

14:15.110 --> 14:18.610
Now current exp remember is a cumulative total.

14:18.620 --> 14:23.990
What we need is how much more from the beginning of our current level we have.

14:24.020 --> 14:31.610
In other words, if we're level two and we had to reach 300 to reach level two and now we have 400 then

14:31.610 --> 14:36.140
to calculate the percent and the level up requirement for level two is, say, 900.

14:36.170 --> 14:42.410
In other words, 600 more, then our percent would be 100 divided by 600.

14:42.440 --> 14:47.510
It would be our current Exp minus last level's requirement.

14:47.510 --> 14:59.450
So we're going to say const int 32 exp for this level equals and it's going to be new exp.

14:59.480 --> 15:06.590
That's our current value minus previous level up requirement.

15:07.070 --> 15:13.560
And finally we can calculate the exp bar percent and this is going to be a float because we're going

15:13.560 --> 15:15.900
to do a division, a const float.

15:15.930 --> 15:18.840
We're going to call this exp bar percent.

15:20.970 --> 15:24.180
And this will be our XP for this level.

15:26.160 --> 15:30.360
Divided by the Delta level requirement.

15:30.630 --> 15:33.610
Now, we don't want to perform integer division.

15:33.630 --> 15:39.090
We want to perform float division so we can static cast these to floats.

15:39.120 --> 15:44.400
Or we could have done an implicit cast and created floats for these variables.

15:44.430 --> 15:46.520
Either one, it doesn't really matter.

15:46.530 --> 15:52.320
We were working with integers up to this point, so this is the point at which we need them to be floats

15:52.320 --> 15:54.690
so we can say static cast.

15:54.690 --> 15:58.740
And this is just a regular old C plus plus static cast to float.

15:58.770 --> 16:02.310
We're going to static cast both of these to floats.

16:02.310 --> 16:08.790
So we'll static cast this one and we'll static cast this one and now we have exp bar percent we can

16:08.790 --> 16:18.000
broadcast we can take our on exp changed and actually our delegate is called on exp percent changed

16:18.000 --> 16:21.090
delegate will broadcast this.

16:21.090 --> 16:22.890
This can broadcast a float.

16:22.920 --> 16:26.290
We're going to broadcast exp bar percent.

16:29.220 --> 16:30.180
All right.

16:30.180 --> 16:32.850
Well, that was quite an experience.

16:32.850 --> 16:38.460
And if you did this all on your own, I'm pretty impressed because that was quite a problem to find

16:38.460 --> 16:39.630
a solution to.

16:39.810 --> 16:40.740
Pretty nice.

16:40.740 --> 16:47.060
And by the way, this could be a const function or a player state could be a const variable.

16:47.070 --> 16:54.660
We can just make these const correct on exp changed in the header file can be made const here.

16:55.460 --> 17:02.090
And with that, we now have our widget controller responding to XRP changes.

17:02.120 --> 17:11.360
Now it'd be great to just go into our XRP bar in Blueprint and bind to this on XRP Percent Change Delegate.

17:11.390 --> 17:14.330
You can see that I just compiled while I was talking there.

17:14.450 --> 17:17.300
But we're never actually changing our XRP.

17:17.600 --> 17:23.510
That's going to be something we have to do when we accomplish something like Slay an Enemy or whatever.

17:23.540 --> 17:30.410
So there's really nothing we can do at this point to test it unless we just change our XRP on the player

17:30.410 --> 17:32.270
state willy nilly.

17:32.270 --> 17:33.470
But that's okay.

17:33.470 --> 17:35.000
We'll test it soon enough.

17:35.000 --> 17:37.340
We're going to implement this in stages.

17:37.370 --> 17:39.800
For now, we have our callback.

17:39.800 --> 17:44.420
We even have this code to find out the XRP bar percent.

17:44.450 --> 17:47.240
We'll see very soon if that's correct.

17:47.240 --> 17:49.820
And things are looking good.

17:49.820 --> 17:54.140
So excellent job with this quest and we'll continue in the next video.

17:54.170 --> 17:55.250
I'll see you soon.
