Welcome back.
So now we have our enemies.
They're doing something, but we definitely want them to do more, Right?
So we're going to continue and I'm going to start by opening up my behavior tree.
So I'm going to go to blueprints I and open my enemy behavior tree here.
Now we have a service find nearest player and it's setting the values of a couple of our blackboard
keys every half second or so.
And we can use those blackboard key values to determine what we should do next.
Now, what I'd like to do is start using some decorators.
Decorators can also be attached to nodes and they can provide us with conditions.
Kind of like if statements that can allow us to execute a given branch or prevent the execution of a
given branch, depending on those conditions.
So I'm going to get rid of this move to Node, just highlight it and delete it and I'd like another
selector.
So I'm going to drag off, search for selector and add one and I can add a decorator to this selector
by right clicking add decorator and choosing blackboard.
Now I have this blue thing connected to my selector that says blackboard based condition, and we can
prevent going into this selector based on a condition.
The condition is based on a blackboard key.
And if we choose that key under blackboard key, we can set it to something.
I'd like to set it to target to follow.
And key query can be is set or is not set.
If it's set to is set, then target to follow must be set in order for us to execute this selector.
So if I have children hooked up to the selector, then they will only be executed if target to follow
is set.
Now notify Observer says that when the result of this evaluation checking target to follow, if that
is changed when we're evaluating it, then we will not enter this selector.
We will fail and return failure back up to the parent.
Now we could change notify observer to on value change.
And that means if we've already made it past this decorator at some point, if target to follow becomes
unset, then this node could abort itself.
Depending on the observer aborts selection, it could abort the self, it could abort only lower priority
nodes and nodes have priority.
We can see them with these little numbers connected to each node and it can abort both, but we're going
to set it to none and leave this on set to on result change for notify observer.
All I care about is preventing the execution of the selector if target to follow is not set and if we
make it past this first selector, it should be set.
That's why I'm checking it after this selector.
If I attach this decorator to this selector up here, then we would never get to set it because it would
never be set in the first place and the decorator would prevent this service from being run.
So we have a decorator that checks to make sure we have a target to follow, and then it can execute
its children left to right.
Now, I'd like to also check another condition.
I'd like to see if our enemy is hit reacting.
Now, that's not a blackboard key, but we can easily add one.
Let's go to our blackboard and add a new key of type bool and this one can be hit reacting.
So we have this blackboard key hit reacting.
Now this should be false by default.
We want to set it to true when hit reacting and false when we're not.
So how can we do that?
Well, we can do this from C plus plus if we can get a hold of the aura AI controller which has access
to the blackboard component blackboard components can set their blackboard values.
So I'm going to close the editor and save and I'm going to open up my character folder and open Aura
Enemy, and I'll get that header file open as well.
Now we have our Aura AI controller here.
As soon as we have this set, I'd like to set the blackboard value of that hit.
Reacting key to false just so we make sure that it's set explicitly.
So I'm going to search in the CPP file for aura AI controller.
We're setting it here in possessed by and after we run the behavior tree, we can get our blackboard
component from it.
We're going to say Aura AI controller, get blackboard component and from the blackboard component we
can set a value as boolean by calling the function set value as bool.
It takes a name and it's called key name.
We're going to pass in the name of hit reacting.
And we're going to set this to false.
And we also want to set this if we're hit, reacting.
So we have a couple of callback functions for when we're hit reacting.
If we scroll down, we'll see.
We have hit react tag changed.
So it's actually one callback and we're setting max walk speed based on be hit reacting we can also
set that key so I'm going to control V and paste this line where we're setting value as bool and we're
going to set hit, reacting equal to the value of be hit reacting.
So every time we're hit, reacting or no longer hit reacting, we should be setting the blackboard key
hit reacting so I can go ahead and hit the debug button.
And we can get that blackboard back open.
We can go into the behavior tree and we can check that hit Reacting Boolean.
I'd like to add another decorator.
So I'm going to right click add decorator, select Blackboard.
And this second one is going to be checking our hit Reacting key.
But this time key query should be is not set.
I want to enter this branch if hit, reacting is not set.
In other words, false.
We're going to set that blackboard key to hit reacting Now I would like to abort the self if hit reacting
becomes true.
So for observer aborts, I'm going to set this to self and change notify observer to on value change.
So any nodes that we have going on down here will stop if hit reacting becomes true.
So now that we have a couple of decorators, we can start thinking about how we're going to make our
enemy move toward the character and also attack the character, I'd like to have several different cases.
I'd like to have a case for our ranged attackers.
I'd like them to stop just short a little distance away before they start attacking.
I'd like to have a separate case for non ranged attackers that want to get close.
And in order to know that I need a blackboard key that can tell me if I have arranged attacker or not.
So we're going to add one last blackboard key of type bool and this is going to be ranged attacker.
And this we can also set from within C plus plus and we can check whether or not we have a ranged attacker
from our selector.
We can drag off and add more nodes.
Now we have selectors up here, but we also have the option to make a sequence node, which is just
like a selector only it has one key difference.
A selector executes children from left to right until one of them succeeds.
A sequence executes children from left to right until one of them fails.
So I'm going to have a sequence here and I'm going to put a little comment here and say, for ranged
attackers or just ranged attacker.
So we'll have some nodes and some logic here.
I'm going to have another sequence here.
And this is going to be for melee attackers.
So I'm going to comment this and say melee attacker, and we'll check first if we're arranged attacker.
If not, we'll continue, Right.
If this fails, we have a selector up here which will go from left to right until one of its children
succeeds.
So this will fail.
So it will continue if this fails based on whatever decorators we put here, Perhaps the enemy isn't
close enough to attack yet.
Then we can have one last sequence over here.
And this one is going to be for moving to the target.
So this one, I'm going to have a comment that says Move to Target.
And each of these will be able to fail based on whatever conditions we set.
So we're going to flesh this out more.
But first, I'd like my ranged attacker key to be set.
So I'm going to set that from C plus plus.
I'm going to go ahead and save the project and we'll go ahead and check our class to see if we're a
ranged attacker or not.
And we'll do that as soon as our AI controller is set.
That's going to be here and possessed by.
So I'm going to say if and we're going to check the character class, we're going to see if it's equal
to a character class and our ranger is going to be a ranged attacker.
But also our elementalist is going to have ranged attacks as well, think fireballs and things like
that.
So I'm going to consider both of these to be ranged attackers.
So we'll really say, is it a warrior?
In fact, we'll say is it not a warrior?
Is character class not equal to warrior?
If so, it's a ranged attacker.
And we can call this line here set value as bool.
In fact, we could just call it here.
No need for an if statement.
This right here character is not warrior is sufficient and the key is going to be ranged attacker.
So we'll set ranged attacker equal to this value.
If it's a warrior, ranged attacker will be false, otherwise it will be true.
So we can go ahead and compile that.
So these are very general blackboard keys.
They're not specific to any one class.
They're general across the board for the whole game.
So I think it's okay to call them out directly in code like that.
So we have our ranged attacker and I want to check that here for this one.
I want to place a decorator here choosing Blackboard and selecting that The key query will be is set,
the blackboard key will be is ranged attacker or just ranged attacker and we'll leave the rest at their
defaults.
So we'll only enter this sequence if we're arranged attacker.
Now, if this branch fails, then this selector will just not execute it and it'll try the next one.
The next one is going to check to see if we're within attack range.
So let's add a decorator here.
We'll choose Blackboard and this one will check our distance to Target.
Now if we choose a float blackboard key.
Now our key query is is equal to and a whole bunch of other options we're going to choose is less than.
And we can have some kind of threshold, some close proximity value.
We'll just use 500 for now.
So if distance to target is less than 500, then we can get inside of this branch and then we can do
our melee attack.
So what if we fail that one?
Well, if we're not arranged attacker and then we check and we're not within attack range.
Well, that must mean we should be moving to the target.
So in that case, we're going to move to the target so we can do a move to here.
We can get the tasks and get moved to and move to our target to follow.
So the blackboard key will be target to follow for this and we can give it a acceptance radius.
I'll give it 50.
So that's what we'll do.
Now I'd like to have a little bit of a delay, not much, but a little bit of a hesitation before moving
to the target so we can take our tasks and get a wait and select that and the wait time.
I'd like to be zero plus or -0.5 seconds.
So a random deviation of plus or -0.5 seconds before moving to the target.
Now I only want to move to the target if we're close enough to approach.
In other words, we're not super, super far away.
So I'm going to add a decorator here.
Decorator Blackboard.
And for this I'm going to check my distance to Target.
So Blackboard Key is distance to Target, and I'm going to check if it's less than or equal to some
pretty big value, like 4000.
So if we're far enough away to approach, we'll approach.
But if we're too close, I want to fail out of this so we can try one of the others and try to attack
again.
In other words, I want to abort if the distance is too close, so I'm going to add another decorator.
Blackboard.
And for this I'm going to check the distance to target again.
But this one will be is greater than or equal to.
And this will be basically our sort of attack distance.
It'll be about, let's say, 500 and we'll abort unless we're greater than or equal to.
So we can actually change the node names on these to make it a little bit easier to understand.
For this distance to target is greater than or equal to 500.
This is are we far away enough to attack?
Because if we're far enough away to attack, we should attack.
So I'm going to rename this one to is far enough to attack.
And this one is are we close enough to approach is the distance less than 4000?
So this will say.
Is close enough to approach.
We can have question marks here as well, and we can even make it a little bit easier to understand.
We can say, Am I close enough to approach?
And here I can say, Am I far enough to attack?
So we will move to the target.
If we're closer than 4000 or equal, we will move to the target.
If we're not too close, are we far away enough?
It should actually say, am I close enough to attack or far enough to approach?
Let's just say, am I far enough to approach trying not to make this too confusing With all the double
negatives and the conditionals.
If distance is greater than 500, we will approach, but otherwise we will not.
If we're too far or too close, we will not approach.
Instead, we'll evaluate one of these other conditions again.
Now we can rename these as well.
This one is checking if the distance is less than 500.
So this one is checking.
Are we close enough to attack?
So we'll say, am I close enough to attack?
And then this one we're checking am I arranged attacker?
So we'll say, am I a ranged attacker?
And arranged attacker should also check a distance as well.
Arranged attacker should attack when it's a little bit farther away so we can have a distance check
here.
Let's add one more decorator.
I'm going to call this one.
Am I close enough to attack?
And this one will also check distance to Target.
But this one will be if we're less than so is less than.
And we'll do a bigger value like 600.
So if we're close enough by 600 units, then for a ranged attacker, we should start attacking with
those ranged attacks.
If we're not arranged attacker and we're not close enough to attack, we'll move on.
But if we're close enough for the melee, we'll attack with melee.
Otherwise we'll then see if we should approach and we'll approach.
Okay, so we have a bit of a skeleton going.
We do need to flesh out these other two cases and give our enemy the ability to attack.
We'll get to that.
I think this is a good stopping point.
And in the videos to come, we'll flesh this out even more.
Before we wrap up, I think we can go ahead and press play and we can see that these things are approaching.
And they kind of just stand there.
Once they've approached, we can see that we're basically in this move to Target.
Part of our tree.
We see that these nodes do nothing.
So we'll get to our move to portion.
And our very basic behavior is working.
We just need to flesh out those other two branches there and we'll do those next.
Great job.
I'll see you soon.