WEBVTT

00:00.230 --> 00:02.270
Welcome to your next quest.

00:02.630 --> 00:07.160
Now we're going to close out the section by creating an enemy health bar.

00:07.160 --> 00:08.960
And this is a quest for you.

00:08.990 --> 00:12.290
Now, this is going to involve creating a widget, of course.

00:12.290 --> 00:14.780
And I'd like this to be above the enemy's head.

00:14.780 --> 00:18.050
So add a widget component to Ora enemy.

00:18.170 --> 00:21.310
Now you're going to need to respond to health changes.

00:21.320 --> 00:23.150
You should know how to do that.

00:23.150 --> 00:29.570
And as a bonus, I'd like you to see if you can use the existing system that we have in place.

00:29.660 --> 00:38.780
Now, by system, I'm talking about using a widget controller to broadcast data to a widget, in our

00:38.780 --> 00:44.420
case, the health bar widget that we're going to set for our enemies widget component.

00:44.450 --> 00:50.420
Now you'll need to think about what should be the widget controller for this and if you really even

00:50.420 --> 00:51.800
need to create one.

00:51.950 --> 00:58.460
And I have an additional hint for you if you're a little bit stumped as far as how to approach this,

00:58.490 --> 01:03.600
if you're ready to jump in, go ahead and pause the video now and conquer the quest.

01:04.740 --> 01:08.550
But if you'd like an extra hint, I'll give you one now.

01:08.880 --> 01:12.480
Our widget controller is a new object.

01:12.510 --> 01:20.460
That means it can be anything that derives from you object that includes actors, pawns and even characters.

01:20.490 --> 01:24.690
A character itself could be the widget controller.

01:24.690 --> 01:31.320
So there's a little bit of a hint and it's a hint about how I'm going to implement this as well.

01:31.320 --> 01:35.010
So pause the video and conquer this quest now.

01:38.230 --> 01:38.680
Okay.

01:38.680 --> 01:43.150
So there are going to be a few parts to this challenge.

01:43.240 --> 01:49.150
I need a widget component on my enemy class, so I'm going to start there.

01:49.180 --> 01:55.630
I'm going to close all tabs and open my public folder, go to character and ora enemy.

01:56.560 --> 02:00.770
And I'd like to add a health bar widget component.

02:00.790 --> 02:05.050
So to add a widget component, we need a variable of that type.

02:05.080 --> 02:07.820
I'm just going to put it down here in the protected section.

02:07.840 --> 02:17.410
It's going to be a T object pointer and it'll be of type U widget component and we'll call this health

02:17.410 --> 02:17.950
bar.

02:18.070 --> 02:22.780
I'll go ahead and forward declare the U widget component type.

02:23.560 --> 02:26.290
Class U widget component.

02:26.950 --> 02:31.210
Now this needs a U property, so we'll give it one.

02:31.210 --> 02:33.610
And I'd like to set this in the blueprint.

02:33.610 --> 02:34.780
It's a component.

02:34.780 --> 02:38.290
So like most components, we need to give it visible anywhere.

02:38.590 --> 02:45.960
I'll make it blueprint read only and we'll have to construct this health bar widget component.

02:45.970 --> 02:53.280
So we'll go into the CPP file all the way up to the constructor and make the health bar here.

02:53.290 --> 02:55.720
I'm going to do it just after the attribute set.

02:55.720 --> 02:57.410
So we're going to say health bar.

02:58.430 --> 03:04.610
I'm going to use create default Subobject with u widget component.

03:07.540 --> 03:09.730
And I'm just going to call it Health Bar.

03:11.260 --> 03:14.770
And we'll need to include the header file for it.

03:14.770 --> 03:16.480
So I'm going to put it right here.

03:16.960 --> 03:23.310
Include and it's going to be in components slash widget component dot H.

03:24.180 --> 03:29.430
So now we've created our health bar and we need to attach this.

03:29.430 --> 03:33.970
I'm going to attach it to the root and then we'll adjust it from the enemy blueprint.

03:33.990 --> 03:39.090
So we're going to say health bar setup attachment and we're going to attach to the root component.

03:39.090 --> 03:41.730
So simply using get root component there.

03:41.730 --> 03:48.720
And now we have a widget component so we can go ahead and launch and we can get started making the widget

03:48.720 --> 03:50.850
that our widget component will use.

03:52.760 --> 03:56.240
So we'll go ahead and create a new widget blueprint.

03:56.240 --> 04:03.680
I'm going to go into Blueprints and UI and we have a progress bar folder where we have our globes.

04:03.770 --> 04:10.070
I'd like to make my enemy health progress bar here, so I'm going to go to user interface, Choose Widget

04:10.070 --> 04:10.670
Blueprint.

04:10.670 --> 04:17.540
We're going to use Ora user widget and this is going to be WB underscore enemy health bar.

04:17.930 --> 04:22.190
Actually, this could really just be a basic progress bar.

04:22.190 --> 04:31.790
So I'm going to call this WB progress bar so we have a globe progress bar and we have a WB progress

04:31.790 --> 04:35.510
bar that way this could be just generalized.

04:35.510 --> 04:39.230
So I'm going to have first of all a size box.

04:41.000 --> 04:45.080
We'll call this, as we normally do, size box routes.

04:46.950 --> 04:51.170
And I'm going to set this from fill screen to desired.

04:51.180 --> 04:55.160
And this is going to be a relatively small size box.

04:55.170 --> 05:01.620
We're going to use width and height override, but I'd like these to be parameters and just to get a

05:01.620 --> 05:11.250
sort of idea for what kind of size I want, we'll do something like perhaps 60 by maybe five.

05:11.280 --> 05:12.480
That might be too small.

05:12.480 --> 05:19.530
We'll have to see what it looks like on screen, but we'll go ahead and make the size box route a variable

05:19.680 --> 05:22.290
and we'll set these from pre construct.

05:22.740 --> 05:25.020
So I'm going to drag it out twice.

05:25.740 --> 05:28.800
Call set width override.

05:29.870 --> 05:30.590
And call.

05:30.590 --> 05:32.000
Set height override.

05:34.670 --> 05:37.680
And we'll promote these two variables.

05:37.700 --> 05:42.320
We'll call this box width, as we normally do.

05:42.350 --> 05:50.960
That's a float, and I'm going to give it a category of progress bar properties.

05:50.960 --> 05:52.490
So we'll have a box width.

05:52.490 --> 05:55.640
We'll promote this to a variable, have a box height.

05:56.610 --> 06:03.120
And set that to progress bar properties as well, and we can hook these up.

06:03.960 --> 06:05.040
Compile.

06:05.700 --> 06:07.410
And give them defaults.

06:07.410 --> 06:11.850
And I think for width we'll do 60 and for height we'll do five.

06:11.880 --> 06:14.250
But we'll tweak these if we need to.

06:14.250 --> 06:19.770
And I'm going to go ahead and collapse this to a function called update box.

06:20.460 --> 06:27.090
Size and we just really need a progress bar.

06:27.210 --> 06:32.790
But I'm anticipating possibly the desire for a ghost progress bar.

06:32.790 --> 06:36.060
And because of that, I'd like an overlay.

06:36.090 --> 06:43.200
So I'm going to stick an overlay onto my size box, rename this to overlay root, and then I'll put

06:43.200 --> 06:45.090
a progress bar on top.

06:45.560 --> 06:47.930
So we'll stick a progress bar in here.

06:48.290 --> 06:52.290
And this progress bar, this is going to be simple.

06:52.310 --> 06:58.760
I'm going to take my fill color and opacity and drag that saturation down so it's white.

06:59.180 --> 07:05.000
I'm going to take the style and we're going to take our background image.

07:05.000 --> 07:10.760
And I think I'd like my background image to have a tint with Zero Alpha.

07:11.060 --> 07:16.250
This is just personal preference here, and I'm going to go ahead and up the percent a little bit so

07:16.250 --> 07:20.300
I can set the fill image here and the image.

07:20.300 --> 07:26.600
I think this actually can be a parameter so we can change it if we want it to be red, blue, whatever.

07:26.720 --> 07:31.480
So I'm going to go ahead and call set style in the graph.

07:31.490 --> 07:33.610
I'm going to change the progress bar, though.

07:33.620 --> 07:41.110
I'm going to have progress bar underscore front and then we'll have one that's a ghost, possibly.

07:41.120 --> 07:47.880
So for progress bar front I'm going to check is variable drag it on out and call set style.

07:48.760 --> 07:50.080
And for the style.

07:50.080 --> 07:54.270
We'll make a style, make progress, bar style.

07:54.280 --> 08:00.480
And actually here is where we're going to set the properties like background image and things like that.

08:00.490 --> 08:08.350
So here's what I'll do is first I'll drag off, we'll make a slate brush for the background image and

08:08.350 --> 08:14.530
we'll expand it and drag out of the tent, make a slate color.

08:14.530 --> 08:20.140
And I'm just going to go ahead and bring that alpha to zero for the slate color.

08:20.140 --> 08:24.070
And there that takes care of our background image.

08:24.160 --> 08:27.670
I'm also going to delete these two nodes for now.

08:28.030 --> 08:35.830
So there's our background image and then we can promote fill image to a variable and we'll call this

08:35.830 --> 08:38.470
front bar fill brush.

08:38.830 --> 08:42.940
We'll stick this in the category of progress.

08:42.940 --> 08:47.410
Bar properties will compile and give this a default.

08:47.410 --> 08:49.940
And I'm going to just take the tint.

08:49.940 --> 08:56.390
And I think what I'll do is make this just red click okay, maybe make it a little darker of a red and

08:56.390 --> 09:02.510
click okay, draw his image is fine and compile that and we can hook this up.

09:02.920 --> 09:07.870
See what it looks like if we compile and it looks like a red progress bar.

09:08.050 --> 09:12.520
Since that looks great, we'll collapse this to a function.

09:13.120 --> 09:19.690
Right click collapse the function update front fill brush.

09:20.230 --> 09:24.640
So you could make the background image also a parameter.

09:24.640 --> 09:26.890
I tend to like them transparent.

09:26.890 --> 09:27.910
That's just me.

09:28.150 --> 09:36.340
I'm going to set horizontal and vertical alignment to fill and we could just go ahead and make a background

09:36.340 --> 09:38.670
bar, but I'm going to save that for later.

09:38.680 --> 09:44.200
First, I want to make this work, so I'm going to get basic functionality working before I go and make

09:44.200 --> 09:47.980
things like a ghost progress bar and so on.

09:48.250 --> 09:49.930
So that's looking good.

09:49.930 --> 09:53.560
We're going to add this to our enemy and I'll go to my base enemy.

09:53.560 --> 10:02.380
So Blueprint, we'll go to character and enemy base, open the Viewports and I'm going to select my

10:02.380 --> 10:07.450
health bar widget and we're going to want to decide how to draw this.

10:07.450 --> 10:12.830
I'd like to draw this in screen space, so I'm going to set space to screen.

10:12.830 --> 10:18.680
We're going to set our widget class and this is going to be a progress bar.

10:22.380 --> 10:23.460
So we'll get that.

10:23.490 --> 10:25.080
We can't see it here.

10:25.110 --> 10:28.410
We'll have to look in the game when we play test it.

10:28.410 --> 10:31.020
But we have a draw size here.

10:31.140 --> 10:33.810
But we can also click draw at desired size.

10:33.810 --> 10:39.750
So if we click draw at desired size, we should see what it looks like if we go ahead and save all.

10:40.390 --> 10:42.130
And press play.

10:42.700 --> 10:45.100
Then we can see what it looks like in the world.

10:45.100 --> 10:47.770
And I think that looks pretty good.

10:47.890 --> 10:51.550
Just a tiny little progress bar for our little enemies.

10:51.560 --> 10:52.960
I think that looks great.

10:53.230 --> 10:55.490
So that's going to work.

10:55.510 --> 11:01.900
I would like the progress bar raised a little bit, so I'm going to raise it up to about there, about

11:01.900 --> 11:04.210
80 units higher.

11:04.210 --> 11:06.940
And now we can see them above the enemy.

11:07.120 --> 11:09.010
And that looks great.

11:09.280 --> 11:14.740
But if we launch a fireball at it, that's not going to do anything to the health bar.

11:14.740 --> 11:16.420
We're not seeing any change.

11:16.420 --> 11:18.400
So that's an issue.

11:18.670 --> 11:21.370
So we're going to want to make this functional.

11:21.400 --> 11:27.280
Before we do, though, I think my default size is a little small, so I'm going to take my box width

11:27.280 --> 11:33.970
and change it from 60 to 80 and box height from five to maybe ten.

11:36.090 --> 11:37.890
Compile that press play.

11:39.160 --> 11:41.560
I liked five for the height.

11:41.560 --> 11:42.760
I think so.

11:42.760 --> 11:44.800
We'll go back to five.

11:44.830 --> 11:46.300
Actually, let's do six.

11:48.080 --> 11:51.080
Just tweaking six looks pretty good.

11:51.980 --> 11:52.670
All right.

11:52.670 --> 11:54.650
So we need this to be functional.

11:54.650 --> 11:57.080
So we need to think about how to do that.

11:57.200 --> 12:04.670
Well, our progress bar is going to need some way that we can set its progress.

12:04.670 --> 12:13.760
And if this is going to be an enemy health bar, then it should specifically respond to some kind of

12:13.760 --> 12:15.260
delegate broadcast.

12:15.260 --> 12:15.830
Right.

12:15.830 --> 12:17.630
To update the progress.

12:17.660 --> 12:25.850
Now, we could keep this generic keep it a generic progress bar set to respond to a generic delegate

12:25.850 --> 12:29.990
broadcast with an event that will set its progress.

12:29.990 --> 12:36.140
And that way, if we subclass it, then we can change the color and respond to really any sort of delegate

12:36.140 --> 12:37.250
broadcast.

12:37.250 --> 12:38.840
So that's an option.

12:38.930 --> 12:44.480
But what I'd like to do is perhaps make a child of this simply for health and then it can listen to

12:44.480 --> 12:45.770
a health broadcast.

12:46.010 --> 12:52.980
So the question is what class is going to have the delegate to broadcast that we can bind to on our

12:52.980 --> 12:54.000
progress bar?

12:54.090 --> 13:00.390
Well, if our progress bar class is going to be generic, then we'll subclass it into a health bar and

13:00.390 --> 13:01.590
the health bar will decide.

13:01.590 --> 13:04.110
But again, the question is still there.

13:04.110 --> 13:06.540
What class do we bind to?

13:06.570 --> 13:08.520
What class is going to broadcast?

13:08.550 --> 13:14.970
Well, recall that I gave you a hint, and that hint was that the widget controller on the aura user

13:14.970 --> 13:18.900
widget class is a U object, meaning it could be set to anything.

13:18.900 --> 13:25.410
It could be set to a character, an actor, or whatever class we want that's derived from U object.

13:25.440 --> 13:31.890
That means our enemy's progress bar could have its widget controller set to the enemy itself.

13:31.890 --> 13:33.180
And that's what I'd like to do.

13:33.180 --> 13:39.330
I'd like to broadcast values from the enemy, so I'm going to go ahead and save all and close and we're

13:39.330 --> 13:41.280
going to go into Aura Enemy.

13:41.280 --> 13:48.300
And I'd like to create a delegate we can broadcast to our widget from the enemy itself.

13:48.420 --> 13:56.880
So for that reason, I'm going to create a variable that can broadcast an attribute value.

13:56.910 --> 14:00.540
Now, recall that we already made a delegate like that.

14:00.540 --> 14:10.020
If we go into our public folder, into UI widget controller and we go into overlay widget controller,

14:10.020 --> 14:16.410
here's a multicast delegate one param called on attribute changed signature.

14:16.440 --> 14:23.730
This is a delegate that can broadcast a float value f on attribute changed signature.

14:24.060 --> 14:26.790
What if we want to use that here in aura enemy?

14:26.820 --> 14:34.530
Could we go into the public section and simply add one of these and call this on health changed?

14:36.270 --> 14:38.640
Well, it's not a defined type.

14:38.640 --> 14:40.080
It's incomplete.

14:40.080 --> 14:46.830
So we are going to need to include something here so we can include that overlay widget controller class.

14:46.830 --> 14:52.560
So I'm going to include it and it's going to be in UI slash.

14:53.300 --> 14:56.540
Widget Controller Slash overlay.

14:56.570 --> 14:57.740
Widget controller.

14:57.860 --> 14:59.140
And now check it out.

14:59.150 --> 15:00.770
We can use that delegate.

15:00.770 --> 15:03.260
So no need to create a new delegate.

15:03.290 --> 15:08.160
We can actually reuse one that already exists for this very purpose.

15:08.180 --> 15:14.030
Yes, we did have to include overlay widget controllers, which is not a huge class.

15:14.030 --> 15:16.640
It's not a big deal that we're including that here.

15:16.670 --> 15:20.880
This is more an exception rather than the rule for habits that we have.

15:20.900 --> 15:28.040
However, if this was really a concern, then we could move that delegate into a different class and

15:28.040 --> 15:30.430
just include that wherever we want to use it.

15:30.440 --> 15:32.200
I'm not going to bother with that.

15:32.210 --> 15:36.370
I'm okay with including the widget controller class here in enemy.

15:36.380 --> 15:39.830
So we have an on health changed delegate.

15:39.860 --> 15:45.350
Now this needs a new property and we're going to make it blueprint assignable so we can assign it from

15:45.350 --> 15:46.190
blueprints.

15:46.190 --> 15:53.790
And I'm going to copy and paste a new one of these called on Max Health Changed and now we have two

15:53.790 --> 15:54.570
delegates.

15:54.570 --> 15:59.100
So the question is, when do we broadcast these to our health bar?

15:59.100 --> 16:04.860
Well, we know that there are delegates on the ability system component that we can bind to, and those

16:04.860 --> 16:08.520
will be broadcast when attributes change.

16:08.520 --> 16:13.170
So what we can do is we can bind to those delegates.

16:13.200 --> 16:14.820
Now, when do we do that?

16:14.820 --> 16:20.220
Well, we need our ability system component to be initialized before we do that.

16:20.220 --> 16:25.620
And we know that on the enemy class this happens in init ability actor info.

16:25.650 --> 16:30.420
That's when we're calling an ability actor info on the ability system component.

16:30.420 --> 16:35.370
So we know that our ability system component is initialized by this point.

16:35.370 --> 16:42.090
So right here in Beginplay, I'd like to bind to some of those delegates broadcast by the ability system

16:42.090 --> 16:42.990
component.

16:43.200 --> 16:45.120
Now what are those delegates?

16:45.120 --> 16:53.850
Well, first let's get our ability system component pointer and we're going to call get gameplay attribute

16:54.140 --> 16:56.450
value change delegate.

16:56.600 --> 17:03.710
Now remember, this requires an gameplay attribute, so we need to get that from our attribute set,

17:03.740 --> 17:10.730
which means we are going to need to cast to aura attribute set so we can say you aura attribute set.

17:10.760 --> 17:12.980
We'll call this aura as.

17:13.840 --> 17:15.940
We'll set that equal to a cast.

17:16.570 --> 17:24.550
You aura attribute set and we're casting attribute set and if you want this could be a cast checked.

17:25.600 --> 17:30.820
As we know our aura enemy will use our aura attribute set for sure.

17:30.820 --> 17:36.700
But in your game, if it's possible that you might be using a different attribute set, you may just

17:36.700 --> 17:39.700
try cast and check the pointer.

17:40.180 --> 17:49.330
So you could do it this way and say if aura as then we can bind to those delegates like so.

17:50.060 --> 17:52.230
Now to get that attribute.

17:52.250 --> 17:55.070
First of all, we're going to want the health attribute, right?

17:55.070 --> 18:00.110
So we're going to use aura as get health attribute.

18:01.070 --> 18:07.820
And this returns that delegate and we're going to bind to it so we can use dot and we can use Add you

18:07.820 --> 18:14.360
object and bind a function callback or we can add lambda and bind a lambda to it.

18:14.360 --> 18:20.660
And I think that's cleaner as it doesn't require us to create a function callback.

18:20.660 --> 18:21.890
So I'd like to do that.

18:22.160 --> 18:30.110
So I'm going to make a lambda, which means I need square brackets, parentheses and a function body.

18:30.230 --> 18:37.340
And this lambda needs to have the function signature of a function that takes a very specific const

18:37.370 --> 18:44.240
reference input parameter and its type is F on attribute change data.

18:44.240 --> 18:47.750
So that's a const reference and we can call that data.

18:47.900 --> 18:51.920
And all we want to do in this lambda is broadcast the delegate.

18:51.920 --> 18:56.780
So that's going to be on health changed as this is for the health attribute.

18:56.780 --> 19:01.950
So we're going to broadcast and we're going to broadcast data dot new value.

19:03.460 --> 19:07.720
Now we can't use on health changed because this is not captured.

19:07.720 --> 19:10.870
So we have to pass that in to the capture list.

19:10.900 --> 19:14.590
We got to put this in there and now we can do this.

19:14.620 --> 19:17.410
Now that's for on health changed.

19:17.440 --> 19:19.690
We need on max health changed.

19:19.690 --> 19:27.130
So let's copy the whole thing, paste it here and we're going to change this to get max health and we're

19:27.130 --> 19:29.570
going to change the delegate to on.

19:29.590 --> 19:30.970
Max health changed.

19:30.970 --> 19:36.440
So now our begin play is taking care of binding to these delegates.

19:36.460 --> 19:40.780
We can move auras into the if statement if we want to do that.

19:41.110 --> 19:44.740
I'm going to go ahead and do that, make it a little bit more concise.

19:44.740 --> 19:51.970
We could also make it a const pointer and now we're taking care of binding to these delegates.

19:52.030 --> 19:58.930
So now that we're broadcasting delegates for when health and max health change, the only thing left

19:58.930 --> 20:02.150
is to bind to these in our progress bar.

20:02.210 --> 20:06.440
So let's go ahead and compile and launch the editor.

20:07.850 --> 20:08.330
All right.

20:08.330 --> 20:09.710
I'm going to click open.

20:09.800 --> 20:11.840
Get that progress bar back.

20:11.840 --> 20:14.330
But this is our base progress bar class.

20:14.330 --> 20:21.080
I'd like to now create one specific to health so we can bind to that on health changed and Max health

20:21.080 --> 20:22.130
change delegate.

20:22.130 --> 20:28.700
So let's go to let's browse to the asset and we'll make a new widget blueprint, user interface, widget

20:28.700 --> 20:35.450
blueprint and under aura user widget we should see the progress Bar WP Progress Bar.

20:35.450 --> 20:42.020
Let's select that and I'll call this WP underscore enemy health bar.

20:42.200 --> 20:44.420
So this one will be specific to the enemy.

20:44.420 --> 20:49.250
And now that we've created this, we need to make sure we're using that in enemy base.

20:49.250 --> 20:55.310
So back in enemy base, let's get our health bar here and we'll change the widget class from Progress

20:55.310 --> 20:59.330
Bar to WP Enemy Health Bar.

20:59.420 --> 21:01.670
Now we're using the correct class.

21:02.280 --> 21:04.180
And an enemy health bar.

21:04.200 --> 21:06.630
We need to bind to some delegates.

21:06.630 --> 21:12.730
But also how do we know the object to bind an event to its delegates?

21:12.750 --> 21:17.670
How do we do that if we don't have a variable referencing our enemy?

21:17.700 --> 21:22.230
We have a widget controller, but that widget controller variable is never being set.

21:22.260 --> 21:24.300
We need to make sure to set that.

21:24.330 --> 21:31.890
So if we go back into writer, how are we going to set the widget controller for our newly created health

21:31.890 --> 21:33.390
bar widget blueprint?

21:33.600 --> 21:35.130
Well, here's what I'd like to do.

21:35.130 --> 21:41.220
I'd like to set the widget controller from the enemy itself as the enemy has access to it.

21:41.400 --> 21:47.040
And I'll go ahead and do that before binding our callbacks here.

21:47.370 --> 21:53.610
So right before we bind our callbacks here and begin play, I'm going to set the widget controller on

21:53.610 --> 21:54.900
our health bar.

21:55.020 --> 22:00.270
But the thing is, our health bar has the type you widget component.

22:00.270 --> 22:04.480
So we're going to need to first of all get its user widget object.

22:04.510 --> 22:08.440
We can do that with get user widget object.

22:08.500 --> 22:12.200
So that gets the user widget used by the component itself.

22:12.220 --> 22:13.780
We can cast that.

22:13.780 --> 22:15.170
So we're going to cast.

22:15.190 --> 22:19.660
And we can cast this to a user or a user widget.

22:19.660 --> 22:22.990
So you or a user widget.

22:23.080 --> 22:30.520
Once we do, that, writer is going to include or a user widget up here in my includes takes care of

22:30.550 --> 22:40.540
that and I'm going to store this in a local variable of type U or a user widget called or a user widget.

22:41.170 --> 22:43.400
And we can set the widget controller here.

22:43.420 --> 22:48.310
Now, I can actually wrap this in an if statement like so.

22:48.610 --> 22:55.540
And we can set the widget controller with or user widgets set widget controller and what are we going

22:55.540 --> 22:56.100
to set it to?

22:56.110 --> 22:58.660
We're going to set it to this.

22:58.960 --> 23:03.560
So now it's widget controller is the enemy itself that owns it.

23:03.580 --> 23:05.050
So that's perfect.

23:05.050 --> 23:12.400
So after we set the widget controller, we then bind our lambdas to the callbacks, but then we should

23:12.400 --> 23:17.350
probably broadcast the initial values because we're calling set widget controller.

23:17.380 --> 23:22.320
Our widget can then bind to these delegates on health change and Non-max health changed.

23:22.330 --> 23:25.990
So after calling set widget controller, we know that's the case.

23:26.380 --> 23:34.570
And then we can simply broadcast the initial values for health and max health right here after we've

23:34.600 --> 23:40.000
bound those delegates, we can say on health changed dot broadcast.

23:40.030 --> 23:41.280
What are we going to broadcast?

23:41.290 --> 23:46.480
Well, we're going to get our auras and we're going to broadcast the value of health so we can call,

23:46.480 --> 23:50.290
get health, and then we can broadcast on max health changed.

23:50.380 --> 23:54.640
So call broadcast here using auras.

23:54.670 --> 23:56.590
Get max health.

23:57.460 --> 24:00.220
So that's broadcasting the initial values.

24:00.220 --> 24:01.660
So we have three things we're doing.

24:01.690 --> 24:06.850
First, we're setting the Progress Bars widget controller, and that's the progress bar used by this

24:06.850 --> 24:08.860
widget component.

24:09.010 --> 24:11.890
Then we're binding callbacks actually.

24:11.890 --> 24:17.790
Lambdas to get gameplay attribute value change delegates on the ability system component.

24:17.800 --> 24:21.190
So those will be broadcast in response to attribute changes.

24:21.190 --> 24:24.580
But then we're broadcasting the initial values here.

24:24.820 --> 24:28.180
Okay, so we'll need to compile again for that to take place.

24:28.180 --> 24:34.960
But in the meantime, now that we know we're going to have a valid widget controller here in enemy health

24:34.960 --> 24:38.920
bar, we can use widget controller set.

24:39.190 --> 24:46.000
And in response to having the widget controller set, we can get the widget controller variable as that

24:46.000 --> 24:51.070
is exposed to blueprint and we can cast it to the enemy class.

24:51.070 --> 24:58.940
So we're going to cast and we can cast to the blueprint BP enemy base or we can cast to Ora enemy.

24:58.940 --> 25:00.050
It doesn't matter.

25:00.080 --> 25:06.440
The delegate is on the C plus plus class so we don't have to choose the BP enemy base, but I'm going

25:06.440 --> 25:07.820
to go ahead and do it.

25:09.300 --> 25:12.130
Just in case in the future we add something to that blueprint.

25:12.150 --> 25:13.990
We might need to access here.

25:14.010 --> 25:18.420
I don't foresee that, but I'm casting to enemy base.

25:18.450 --> 25:20.790
Now we can bind to delegates on it.

25:20.820 --> 25:23.380
We're going to bind to two different delegates.

25:23.400 --> 25:28.800
So first, I'm going to promote this to a variable and call this BP enemy base.

25:29.220 --> 25:32.220
And I'd like to make a sequence node.

25:32.860 --> 25:35.230
To organize the different things we're going to do.

25:35.230 --> 25:37.180
So let's do a sequence.

25:37.900 --> 25:42.970
The first thing we're doing is getting our widget controller casting to enemy base.

25:43.060 --> 25:44.260
And then next.

25:44.290 --> 25:52.300
Now that we've promoted this to a variable, we can get enemy base and we can get on health changed

25:52.300 --> 25:56.440
and we can assign an event to on health changed.

25:57.250 --> 26:01.810
And we can hook that up and we can do the same thing for on max health change.

26:01.810 --> 26:07.780
So I'm going to duplicate BP enemy base and search for on max health changed.

26:08.020 --> 26:11.860
Assign that and hook that up to the sequence as well.

26:12.860 --> 26:20.420
So now we're going to have our two delegates for when max health and health change and what are we going

26:20.420 --> 26:21.230
to do?

26:21.260 --> 26:25.120
Well, we're going to update the progress bar.

26:25.130 --> 26:27.140
So how are we going to set the progress bar?

26:27.140 --> 26:33.020
Well, if we look at Progress Bar, the progress bar is called Progress Bar Front.

26:33.140 --> 26:37.430
So from within our enemy health bar if we search for progress.

26:38.080 --> 26:40.540
Bar underscore front.

26:40.570 --> 26:45.850
We can get that as long as it's a variable, which it is.

26:45.880 --> 26:53.050
And with progress bar front selected we can call set percent the function.

26:54.160 --> 26:56.980
So what percent are we going to set it to?

26:57.010 --> 27:05.320
Well, what we can do is we can take the value that we've gotten from on health changed and we can promote

27:05.320 --> 27:08.800
that to a variable called health.

27:08.890 --> 27:11.320
And I'm going to fix that typo.

27:11.530 --> 27:19.060
And then we can promote this one to a variable for on max health changed and we'll call this max health.

27:19.630 --> 27:24.710
And each time one of these is set, we'll divide health by max health.

27:24.730 --> 27:26.160
So we'll take health.

27:26.170 --> 27:27.610
We'll take max health.

27:27.610 --> 27:30.250
And I'm going to use Safe Divide.

27:30.280 --> 27:36.640
That way, if we're dividing by zero, we'll get zero rather than something that's not a number.

27:36.850 --> 27:43.930
So after setting health, we do the safe divide and we set percent like so.

27:44.560 --> 27:48.190
And this is going to be the same exact thing we do down here.

27:48.960 --> 27:57.120
We can make a function for it or I can just duplicate like so and it's actually not going to be hooked

27:57.120 --> 27:58.470
up to the blue node.

27:58.470 --> 28:01.920
It has to be hooked up to just after we set max health.

28:01.920 --> 28:03.780
That's kind of important.

28:03.780 --> 28:06.600
And by kind of, I mean really important.

28:07.140 --> 28:12.120
Okay, so this is all set up and we have our widget controller set.

28:12.120 --> 28:15.570
At least we made that change in C plus plus, but we didn't compile it.

28:15.570 --> 28:20.940
So we're going to have to close the editor, save all and compile and launch from our IDE.

28:21.570 --> 28:27.270
That way we're actually setting the widget controller, binding the delegates, broadcasting initial

28:27.270 --> 28:27.750
values.

28:27.750 --> 28:30.480
So now we can play test.

28:32.590 --> 28:33.580
All right.

28:33.580 --> 28:40.510
I'll go ahead and get those asset editors open and then we can do some damage to the enemies.

28:41.670 --> 28:42.750
And look at that.

28:42.750 --> 28:43.980
Look at that health bar.

28:43.980 --> 28:45.540
It's going down.

28:48.250 --> 28:49.660
Beautiful.

28:50.110 --> 28:52.440
That is looking really nice.

28:52.450 --> 28:54.820
It's reacting as it should.

28:55.060 --> 28:56.830
And we can see.

28:57.990 --> 28:59.580
That we're doing damage.

29:04.650 --> 29:05.610
Perfect.

29:06.460 --> 29:09.370
Okay, so we have a working enemy health bar.

29:09.960 --> 29:17.790
Now, this is great and we could easily stop here, but it's always fun to do things like trailing ghost

29:17.790 --> 29:18.360
bars.

29:18.360 --> 29:26.040
And I think it's one of those details that's really small and not necessarily noticed as much, but

29:26.040 --> 29:29.700
it is noticed and it is kind of a nice detail.

29:29.820 --> 29:38.460
So I'd really quickly like to have a trailing ghost bar and I'd also kind of like to hide our health

29:38.460 --> 29:40.130
bar when it's inactive.

29:40.140 --> 29:47.340
So if it hasn't been updated in a while, I'd like to sort of hide it and show it again once it's being

29:47.340 --> 29:48.380
displayed.

29:48.390 --> 29:55.050
So that's a couple of things we can do, and I think those would be great for the next video as getting

29:55.050 --> 29:57.540
this working was a good milestone for now.

29:57.540 --> 30:01.110
So in the next video, we're going to make a ghost health bar.

30:01.720 --> 30:04.120
And make our health bar timer based.

30:04.150 --> 30:06.610
Great job and congratulations.

30:06.610 --> 30:10.150
If you made it through this challenge by yourself.

30:10.270 --> 30:15.070
It was nice and challenging and ambitious, so congratulations.

30:15.070 --> 30:18.580
And if you only made it part of the way through, that's totally fine.

30:18.610 --> 30:21.160
Congratulations on doing the challenge.

30:21.160 --> 30:22.870
I'll see you in the next video.
