Welcome back.
So now we're successfully finding the data table row associated with any given tag.
We now would like to broadcast this up to widgets that can bind to some kind of delegate and receive
that row and then show something in the HUD using assets from that data table row.
So we're going to want some kind of delegate.
So let's go back to overlay widget controllers.
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
we're going to use one delegate for all messages because we can just broadcast a row.
That's all we need.
The row has all the information to identify that specific bundle of data.
It has a gameplay tag.
It has the message.
All of this stuff is in the row itself, so we could just use one row to rule them all.
So I'd like to make a dynamic multicast delegate one param just like these.
Only we're going to call this delegate signature F message widget row signature and it's going to broadcast
a value of type f ui widget row.
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
not going to use a pointer, we're just going to use an f UI widget row, which means we need to define
this struct before we define the delegate.
So we can just cut the entire struct definition with control x and move it up to above everything.
I'm just going to put it just below the includes there.
And now it's defined.
Now as soon as we move it up here, well now we're using some types in the struct that are not defined
yet and these ones we can forward declare.
So we're using or user widget, that's really the only one we can forward declare this.
I'm going to go ahead and forward declare it just right here and now.
If I compile this, then I get a successful compile.
So now we're all good on our types.
So now that we have this signature, let's make a member variable of this type right here just below
the others.
So I'm going to call this method message widget row delegate.
Or we could just call it message Widget row doesn't matter and I'm going to make it blueprint assignable,
so I'll put that uproperty there.
And for the category, let's give it gas with the pipe symbol and then messages.
And now we can broadcast this delegate.
So we're going to do that.
Now, I know you're probably thinking if we just have one delegate for all messages, why can't we just
have one delegate for all attributes?
And the answer is you actually could we could just have an F on attribute change signature as they're
all floats anyway, so we'll probably have some refactoring to do that in the near future.
But for the task at hand, we just want to broadcast a UI widget row.
So now that we have this delegate, let's go back into our lambda and just after getting that row we
can take our message widget row, delegate, we can call broadcast and we can broadcast the row.
Now we know that this is a pointer, so we're going to have to dereference the pointer.
So we'll just say star row and the reference it just like that.
Now you might be thinking, isn't there a problem with this system?
What if asset tags has a game play tag that is not a message tag, right?
What if it's some other tag we choose to use for something else?
For the game play effect.
We don't want to restrict our asset tags container to just message tags.
Right.
So how do we enforce or rather restrict this functionality to only when we have a message tag?
Well, tags are super useful and we can do things like that.
The gameplay tag has some functions.
Let's type F gameplay tag double colon and search for match and notice.
We have a bunch of functions that start with match such as matches tag.
Now this is not a static function, but I just wrote this so that I can right click on matches tag and
go to its definition.
So go to declaration or usages.
Here it is.
We can see what it does, but let's control O and find it here in the header file.
It's in gameplay tag container.
And what we do is we call this function on a gameplay tag passing in another gameplay tag.
So it says determine if this tag matches tag to check.
That's what we pass in expanding our parent tags and it says a .1. matches tag A will return.
True if a dot matches tag a dot one will return false and it says if tag to check is not valid, it
will always return false.
So if this explanation seems a little confusing, let's copy this line and come back to the widget controller
and we'll make a little comment here and paste that in.
So a dot one matches tag A will return.
True.
What does that mean?
Well, let's take our tag.
Use Dot and we'll call matches tag.
Okay.
Now we want to match against the message tag.
And if a tag exists in our project, it exists in one of our config files.
Then we can get the tag with the static function f gameplay tag colon colon request gameplay tag which
requires an F name.
So we're going to say f name and then we say the tag we want.
We want a message.
So this returns a gameplay tag.
We're going to store it.
We're going to say F gameplay tag message tag and request gameplay tag has a bool called error if not
found automatically set to true.
So if we call this with a tag that does not exist already in our project, we can't see it in project
settings.
We'll get an error, but we can use message even though we have message.
Dot health potion message dot mana potion.
Well message is considered a tag as well.
It's the top of that little hierarchy so we can call tag matches, tag and pass in a tag.
We're going to pass in message tag.
And now we have something more concrete for this explanation.
So let's make this a little bit less confusing, shall we?
Let's take a hypothetical example.
Now we know that tag in asset tags could be one of those message tags in our project.
So let's take the example where tag is equal to one of them.
We'll say, for example, say that tag is message dot health potion.
So here in this comment, we're going to replace a with message.
And one with health potion.
So here A is message.
And over here A is message.
A one is message dot health potion.
Now we have a more concrete example that kind of makes more sense.
So in the case where tag is message dot health potion then for this function matches tag where tag is
message dot health potion and message tag is just message.
Then the comment says message dot health potion.
Right.
That's our tag calling matches tag with message passed in.
That's what we're doing.
It says that this will return true.
However, if instead we had taken our message tag, which is just message and called matches tag passing
in this tag message dot health potion that would return false.
So that's how the matches tag function works.
If we're taking a tag that has more chains of the hierarchy in the tag and we're seeing if it matches
a tag that's less of those branches say message, then this would return.
True.
And that's exactly the behavior we want because we want to see if the tag is a message tag.
We don't care what message as long as it is a message tag.
If it's any other tag, say an ability tag, an input tag, any other kind of tag we define.
We don't want to look for a widget row in our message widget data table.
We only want to look for a row in the table if the tag is a message tag specifically.
So we'll go ahead and keep that comment there just so we know what's going on and we can remove this
onscreen debug message, I'm going to go ahead and remove those lines.
And we have this expression here.
We're calling matches tag.
Now this returns a bool and it will be true if tag is a message tag.
So what we'll do is we'll say if and then we'll place this expression in the if statement.
I'm just going to drag it on in there and we'll only look for the row and make the broadcast if tag
matches the message tag, which is just message.
So I'm going to go ahead and put those lines in there.
So now we won't even bother trying to find a row in our data table unless our tag that we're checking
in asset tags has message as its root of the hierarchy.
And one last thing this row pointer can be const.
Okay, so now we have a broadcast and all we need to do is bind to this delegate.
We're broadcasting in our widget so we can do that and test it out.
So that's going to be your quest.
I'd like you to receive the data table row.
Do this in the widget Blueprint for the overlay.
BP Overlay and bind an event to message widget row, delegate and print a debug string.
Just make sure that that widget is receiving the delegate.
Now choose the best place to do this.
Make sure that that widget controller is set by the time you try to do this.
So let's get this working.
Make sure the print string says something related to the widget so we know that we're getting the actual
string in the widget blueprint, so we know it's working.
So pause the video and conquer this quest now.
Okay, let's compile and launch.
I'm going to run this in debug mode.
And here in the editor, I'm just going to open my overlay widget.
So let's go to Blueprints UI overlay and open up overlay.
And here in the graph tab, I know that I can bind to the widget as soon as my widget controller has
been set.
Now things are starting to get a little more complicated here because I'm going to bind an event to
the delegate, so I'm going to make a sequence here to organize things.
So I'm going to move these nodes up and out of the way.
Give them a reroute node there.
And the next thing we're going to do is we're going to bind to the delegates on the widget controller.
But remember, our widget controller is just a U object, so we need to cast it.
So in fact, I'd like to do that first.
So then one can be these nodes.
But before I do that, I'm just going to cast my widget controller.
Here it is.
I'm going to duplicate this and cast to BP overlay widget controller, and I'm going to promote this
to a variable.
So hooking that up here.
And promoting it to a variable.
I'm going to call it BP overlay widget controller.
So now we have that there.
And after setting the widget controllers for the health globe and the Mana Globe, now we can take our
BP overlay widget controller.
I can drag off of it and I can type message widget and see I have my message widget row delegate.
I can assign to that.
I'm going to choose that.
Add a pin to the sequence and bring it out and check this out as soon as this delegate gets broadcast.
Here in WB Overlay, we have our event called in response but it receives this a UI widget row structure
and we can drag off and we can even break this and we have access to all sorts of cool stuff here.
Now I'd like to just make sure this is working by using a print string node and I'm going to take my
message and just stick it in there so we can see the message that corresponds to the gameplay tag in
the effect that was applied.
So saving all.
I'm going to pick up some things and see what we get printed to the screen.
Picked up a health crystal.
That looks great.
Let's get a mana potion.
Look at that.
Picked up a mana potion.
Picked up a health potion.
Picked up a mana crystal.
So we're getting the message from the data table.
In fact, we're getting the entire data table row corresponding to whatever gameplay tag was there inside
that gameplay effect.
And the cool thing is we're looping through the gameplay tag container, so there could be multiple
message tags if we really wanted to have multiple and I'm not going to show you that example.
I'm sure you understand that you could just add to the asset tags for a gameplay effect.
And because we're looping through, we would be broadcasting the delegate multiple times.
So now that we know that our system is working, we know that we have access to the gameplay tag, the
message, the widget, which we're not really setting the widget yet.
It's just a widget class actually, because that's a T a subclass of.
But we haven't set that in the data table for any of our tags, but we will.
And then we also have the image as well.
So we have a lot of information now that we can use to display any kind of message we want to the screen.
So we're going to do that in the videos to come.
So great job and I'll see you soon.