WEBVTT

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

00:08.110 --> 00:14.370
So now we're successfully finding the data table row associated with any given tag.

00:14.380 --> 00:21.880
We now would like to broadcast this up to widgets that can bind to some kind of delegate and receive

00:21.880 --> 00:28.480
that row and then show something in the HUD using assets from that data table row.

00:28.570 --> 00:32.350
So we're going to want some kind of delegate.

00:33.050 --> 00:35.870
So let's go back to overlay widget controllers.

00:36.290 --> 00:41.420
I'm going to move it over to the right here and we're going to make a delegate up here at the top and

00:41.420 --> 00:47.120
we're going to use one delegate for all messages because we can just broadcast a row.

00:47.150 --> 00:48.300
That's all we need.

00:48.320 --> 00:54.570
The row has all the information to identify that specific bundle of data.

00:54.590 --> 00:56.390
It has a gameplay tag.

00:56.390 --> 00:57.790
It has the message.

00:57.800 --> 01:03.160
All of this stuff is in the row itself, so we could just use one row to rule them all.

01:03.170 --> 01:08.930
So I'd like to make a dynamic multicast delegate one param just like these.

01:10.340 --> 01:22.130
Only we're going to call this delegate signature F message widget row signature and it's going to broadcast

01:22.130 --> 01:25.490
a value of type f ui widget row.

01:25.490 --> 01:33.060
So we'll put that there and we'll just call it row now f ui Widget row is undefined right here and we're

01:33.060 --> 01:39.150
not going to use a pointer, we're just going to use an f UI widget row, which means we need to define

01:39.150 --> 01:42.060
this struct before we define the delegate.

01:42.060 --> 01:50.010
So we can just cut the entire struct definition with control x and move it up to above everything.

01:50.010 --> 01:52.860
I'm just going to put it just below the includes there.

01:52.860 --> 01:55.080
And now it's defined.

01:55.410 --> 02:02.100
Now as soon as we move it up here, well now we're using some types in the struct that are not defined

02:02.100 --> 02:06.180
yet and these ones we can forward declare.

02:06.180 --> 02:11.640
So we're using or user widget, that's really the only one we can forward declare this.

02:11.640 --> 02:15.630
I'm going to go ahead and forward declare it just right here and now.

02:15.630 --> 02:19.710
If I compile this, then I get a successful compile.

02:19.710 --> 02:23.610
So now we're all good on our types.

02:23.790 --> 02:30.270
So now that we have this signature, let's make a member variable of this type right here just below

02:30.270 --> 02:31.230
the others.

02:31.230 --> 02:36.750
So I'm going to call this method message widget row delegate.

02:38.130 --> 02:43.980
Or we could just call it message Widget row doesn't matter and I'm going to make it blueprint assignable,

02:43.980 --> 02:46.110
so I'll put that uproperty there.

02:46.110 --> 02:52.350
And for the category, let's give it gas with the pipe symbol and then messages.

02:52.350 --> 02:54.720
And now we can broadcast this delegate.

02:54.870 --> 02:56.550
So we're going to do that.

02:56.580 --> 03:02.790
Now, I know you're probably thinking if we just have one delegate for all messages, why can't we just

03:02.790 --> 03:05.490
have one delegate for all attributes?

03:05.490 --> 03:12.840
And the answer is you actually could we could just have an F on attribute change signature as they're

03:12.840 --> 03:20.280
all floats anyway, so we'll probably have some refactoring to do that in the near future.

03:20.280 --> 03:25.800
But for the task at hand, we just want to broadcast a UI widget row.

03:25.800 --> 03:32.250
So now that we have this delegate, let's go back into our lambda and just after getting that row we

03:32.250 --> 03:40.430
can take our message widget row, delegate, we can call broadcast and we can broadcast the row.

03:40.580 --> 03:45.890
Now we know that this is a pointer, so we're going to have to dereference the pointer.

03:45.890 --> 03:51.350
So we'll just say star row and the reference it just like that.

03:51.350 --> 03:55.940
Now you might be thinking, isn't there a problem with this system?

03:55.940 --> 04:01.990
What if asset tags has a game play tag that is not a message tag, right?

04:02.000 --> 04:06.140
What if it's some other tag we choose to use for something else?

04:06.140 --> 04:07.760
For the game play effect.

04:07.790 --> 04:12.380
We don't want to restrict our asset tags container to just message tags.

04:12.380 --> 04:12.980
Right.

04:13.530 --> 04:20.610
So how do we enforce or rather restrict this functionality to only when we have a message tag?

04:21.210 --> 04:24.960
Well, tags are super useful and we can do things like that.

04:25.200 --> 04:28.680
The gameplay tag has some functions.

04:28.680 --> 04:36.060
Let's type F gameplay tag double colon and search for match and notice.

04:36.060 --> 04:40.740
We have a bunch of functions that start with match such as matches tag.

04:40.860 --> 04:47.340
Now this is not a static function, but I just wrote this so that I can right click on matches tag and

04:47.340 --> 04:48.690
go to its definition.

04:48.690 --> 04:51.210
So go to declaration or usages.

04:51.300 --> 04:52.170
Here it is.

04:52.170 --> 04:58.440
We can see what it does, but let's control O and find it here in the header file.

04:58.440 --> 05:00.510
It's in gameplay tag container.

05:00.690 --> 05:07.040
And what we do is we call this function on a gameplay tag passing in another gameplay tag.

05:07.050 --> 05:10.890
So it says determine if this tag matches tag to check.

05:10.920 --> 05:21.070
That's what we pass in expanding our parent tags and it says a .1. matches tag A will return.

05:21.070 --> 05:30.760
True if a dot matches tag a dot one will return false and it says if tag to check is not valid, it

05:30.760 --> 05:32.050
will always return false.

05:32.050 --> 05:39.010
So if this explanation seems a little confusing, let's copy this line and come back to the widget controller

05:39.130 --> 05:43.750
and we'll make a little comment here and paste that in.

05:43.750 --> 05:46.990
So a dot one matches tag A will return.

05:46.990 --> 05:47.800
True.

05:48.010 --> 05:48.970
What does that mean?

05:48.970 --> 05:50.830
Well, let's take our tag.

05:52.640 --> 05:55.400
Use Dot and we'll call matches tag.

05:55.400 --> 05:56.090
Okay.

05:57.020 --> 06:01.610
Now we want to match against the message tag.

06:01.610 --> 06:08.210
And if a tag exists in our project, it exists in one of our config files.

06:08.240 --> 06:19.160
Then we can get the tag with the static function f gameplay tag colon colon request gameplay tag which

06:19.160 --> 06:20.830
requires an F name.

06:20.840 --> 06:25.130
So we're going to say f name and then we say the tag we want.

06:25.160 --> 06:27.320
We want a message.

06:27.770 --> 06:30.650
So this returns a gameplay tag.

06:30.650 --> 06:31.520
We're going to store it.

06:31.520 --> 06:42.200
We're going to say F gameplay tag message tag and request gameplay tag has a bool called error if not

06:42.200 --> 06:44.210
found automatically set to true.

06:44.210 --> 06:50.810
So if we call this with a tag that does not exist already in our project, we can't see it in project

06:50.810 --> 06:51.470
settings.

06:51.470 --> 06:56.220
We'll get an error, but we can use message even though we have message.

06:56.220 --> 06:59.070
Dot health potion message dot mana potion.

06:59.070 --> 07:02.460
Well message is considered a tag as well.

07:02.730 --> 07:09.270
It's the top of that little hierarchy so we can call tag matches, tag and pass in a tag.

07:09.270 --> 07:11.040
We're going to pass in message tag.

07:11.550 --> 07:16.020
And now we have something more concrete for this explanation.

07:16.290 --> 07:19.650
So let's make this a little bit less confusing, shall we?

07:19.650 --> 07:22.560
Let's take a hypothetical example.

07:22.830 --> 07:29.910
Now we know that tag in asset tags could be one of those message tags in our project.

07:29.910 --> 07:33.990
So let's take the example where tag is equal to one of them.

07:33.990 --> 07:42.270
We'll say, for example, say that tag is message dot health potion.

07:42.750 --> 07:48.600
So here in this comment, we're going to replace a with message.

07:49.460 --> 07:51.860
And one with health potion.

07:53.020 --> 07:55.780
So here A is message.

07:57.140 --> 08:00.170
And over here A is message.

08:00.290 --> 08:03.530
A one is message dot health potion.

08:05.000 --> 08:09.500
Now we have a more concrete example that kind of makes more sense.

08:09.530 --> 08:17.780
So in the case where tag is message dot health potion then for this function matches tag where tag is

08:17.780 --> 08:22.760
message dot health potion and message tag is just message.

08:22.940 --> 08:26.780
Then the comment says message dot health potion.

08:26.780 --> 08:27.260
Right.

08:27.260 --> 08:32.060
That's our tag calling matches tag with message passed in.

08:32.090 --> 08:33.410
That's what we're doing.

08:33.410 --> 08:35.540
It says that this will return true.

08:35.870 --> 08:45.500
However, if instead we had taken our message tag, which is just message and called matches tag passing

08:45.500 --> 08:50.380
in this tag message dot health potion that would return false.

08:50.390 --> 08:53.900
So that's how the matches tag function works.

08:54.080 --> 09:03.030
If we're taking a tag that has more chains of the hierarchy in the tag and we're seeing if it matches

09:03.060 --> 09:09.330
a tag that's less of those branches say message, then this would return.

09:09.330 --> 09:10.040
True.

09:10.050 --> 09:16.320
And that's exactly the behavior we want because we want to see if the tag is a message tag.

09:16.320 --> 09:20.220
We don't care what message as long as it is a message tag.

09:20.220 --> 09:26.160
If it's any other tag, say an ability tag, an input tag, any other kind of tag we define.

09:26.160 --> 09:31.200
We don't want to look for a widget row in our message widget data table.

09:31.200 --> 09:37.170
We only want to look for a row in the table if the tag is a message tag specifically.

09:37.320 --> 09:44.310
So we'll go ahead and keep that comment there just so we know what's going on and we can remove this

09:44.340 --> 09:48.660
onscreen debug message, I'm going to go ahead and remove those lines.

09:48.960 --> 09:51.120
And we have this expression here.

09:51.120 --> 09:52.440
We're calling matches tag.

09:52.440 --> 09:57.480
Now this returns a bool and it will be true if tag is a message tag.

09:57.480 --> 10:04.980
So what we'll do is we'll say if and then we'll place this expression in the if statement.

10:04.980 --> 10:11.520
I'm just going to drag it on in there and we'll only look for the row and make the broadcast if tag

10:11.520 --> 10:14.430
matches the message tag, which is just message.

10:14.430 --> 10:16.710
So I'm going to go ahead and put those lines in there.

10:18.580 --> 10:26.500
So now we won't even bother trying to find a row in our data table unless our tag that we're checking

10:26.500 --> 10:32.430
in asset tags has message as its root of the hierarchy.

10:32.440 --> 10:36.760
And one last thing this row pointer can be const.

10:37.570 --> 10:45.700
Okay, so now we have a broadcast and all we need to do is bind to this delegate.

10:45.730 --> 10:51.520
We're broadcasting in our widget so we can do that and test it out.

10:52.140 --> 10:54.480
So that's going to be your quest.

10:54.750 --> 10:57.330
I'd like you to receive the data table row.

10:57.360 --> 11:00.690
Do this in the widget Blueprint for the overlay.

11:00.720 --> 11:08.460
BP Overlay and bind an event to message widget row, delegate and print a debug string.

11:08.460 --> 11:12.540
Just make sure that that widget is receiving the delegate.

11:12.570 --> 11:15.860
Now choose the best place to do this.

11:15.870 --> 11:21.180
Make sure that that widget controller is set by the time you try to do this.

11:21.180 --> 11:22.970
So let's get this working.

11:22.980 --> 11:28.020
Make sure the print string says something related to the widget so we know that we're getting the actual

11:28.020 --> 11:30.930
string in the widget blueprint, so we know it's working.

11:30.930 --> 11:34.410
So pause the video and conquer this quest now.

11:37.610 --> 11:40.530
Okay, let's compile and launch.

11:40.550 --> 11:42.290
I'm going to run this in debug mode.

11:42.560 --> 11:47.140
And here in the editor, I'm just going to open my overlay widget.

11:47.150 --> 11:52.610
So let's go to Blueprints UI overlay and open up overlay.

11:52.610 --> 11:58.970
And here in the graph tab, I know that I can bind to the widget as soon as my widget controller has

11:58.970 --> 12:00.020
been set.

12:00.380 --> 12:08.450
Now things are starting to get a little more complicated here because I'm going to bind an event to

12:08.450 --> 12:14.540
the delegate, so I'm going to make a sequence here to organize things.

12:15.240 --> 12:19.010
So I'm going to move these nodes up and out of the way.

12:19.140 --> 12:20.940
Give them a reroute node there.

12:23.780 --> 12:29.510
And the next thing we're going to do is we're going to bind to the delegates on the widget controller.

12:29.510 --> 12:35.440
But remember, our widget controller is just a U object, so we need to cast it.

12:35.450 --> 12:38.270
So in fact, I'd like to do that first.

12:38.270 --> 12:41.690
So then one can be these nodes.

12:41.690 --> 12:45.200
But before I do that, I'm just going to cast my widget controller.

12:45.200 --> 12:45.770
Here it is.

12:45.770 --> 12:53.270
I'm going to duplicate this and cast to BP overlay widget controller, and I'm going to promote this

12:53.270 --> 12:54.020
to a variable.

12:54.020 --> 12:55.580
So hooking that up here.

12:56.830 --> 12:58.770
And promoting it to a variable.

12:58.780 --> 13:04.090
I'm going to call it BP overlay widget controller.

13:06.010 --> 13:08.020
So now we have that there.

13:08.930 --> 13:17.270
And after setting the widget controllers for the health globe and the Mana Globe, now we can take our

13:17.270 --> 13:19.430
BP overlay widget controller.

13:19.460 --> 13:27.080
I can drag off of it and I can type message widget and see I have my message widget row delegate.

13:27.080 --> 13:28.370
I can assign to that.

13:28.370 --> 13:30.140
I'm going to choose that.

13:30.140 --> 13:37.970
Add a pin to the sequence and bring it out and check this out as soon as this delegate gets broadcast.

13:38.000 --> 13:48.380
Here in WB Overlay, we have our event called in response but it receives this a UI widget row structure

13:48.380 --> 13:55.720
and we can drag off and we can even break this and we have access to all sorts of cool stuff here.

13:55.730 --> 14:01.700
Now I'd like to just make sure this is working by using a print string node and I'm going to take my

14:01.700 --> 14:10.260
message and just stick it in there so we can see the message that corresponds to the gameplay tag in

14:10.260 --> 14:11.850
the effect that was applied.

14:11.850 --> 14:13.890
So saving all.

14:13.890 --> 14:18.330
I'm going to pick up some things and see what we get printed to the screen.

14:18.840 --> 14:20.580
Picked up a health crystal.

14:20.580 --> 14:21.450
That looks great.

14:21.450 --> 14:23.160
Let's get a mana potion.

14:23.190 --> 14:23.850
Look at that.

14:23.850 --> 14:25.380
Picked up a mana potion.

14:26.040 --> 14:27.720
Picked up a health potion.

14:28.140 --> 14:29.820
Picked up a mana crystal.

14:29.820 --> 14:35.310
So we're getting the message from the data table.

14:35.730 --> 14:44.460
In fact, we're getting the entire data table row corresponding to whatever gameplay tag was there inside

14:44.460 --> 14:45.870
that gameplay effect.

14:45.870 --> 14:52.230
And the cool thing is we're looping through the gameplay tag container, so there could be multiple

14:52.230 --> 14:58.490
message tags if we really wanted to have multiple and I'm not going to show you that example.

14:58.500 --> 15:04.350
I'm sure you understand that you could just add to the asset tags for a gameplay effect.

15:04.350 --> 15:10.230
And because we're looping through, we would be broadcasting the delegate multiple times.

15:10.350 --> 15:18.600
So now that we know that our system is working, we know that we have access to the gameplay tag, the

15:18.600 --> 15:22.860
message, the widget, which we're not really setting the widget yet.

15:22.860 --> 15:26.710
It's just a widget class actually, because that's a T a subclass of.

15:26.740 --> 15:31.570
But we haven't set that in the data table for any of our tags, but we will.

15:31.570 --> 15:33.900
And then we also have the image as well.

15:33.910 --> 15:42.580
So we have a lot of information now that we can use to display any kind of message we want to the screen.

15:42.580 --> 15:45.460
So we're going to do that in the videos to come.

15:45.730 --> 15:48.730
So great job and I'll see you soon.
