Welcome back.
Now, in our electrocute spell, we've just added a gameplay cue on an actor, but this time it depends
on what our mouse hit actor is and whether it implements the combat interface.
If it does, then we're adding this gameplay cue to the mouse hit actor.
If it doesn't, then we're adding it to the avatar actor instead.
Now, as soon as we've done that, I want to add more cues to more actors.
I want to get more actors that are close by.
I want to store additional targets.
In other words, I want to generate an array of actors and create target gameplay queue parameters for
each one, and apply our electric beam to each one.
Now, compiling an array of actors generally involves loops, and I'm going to get actors that are nearby.
So we're going to be performing some kind of query.
This is all stuff that we should do in C plus plus.
So I'm going to make a C plus plus function.
So saving all I'm going to open Aura Beam spell.
And we'll be making another blueprint callable function.
It's going to be void.
And I'm going to call this store additional targets.
Now I'd like to pass in a T array by reference non-const.
It'll be a t array of a actor pointers.
So passed in by reference, and I'm going to call it out.
Additional target.
So it's an out parameter and it's going to be blueprint callable.
Oops.
Didn't mean to build.
I'm going to cancel that build.
And we're going to generate a definition for this.
So we need to think about what this is going to do for us.
Now I want this function to generate a t array of actors.
And I want them to be nearby actors that implement the combat interface.
On top of that, I want them to not be dead either.
Now, if we go into our ability system blueprint library.
Or ability system library, and we take a look at get live players within radius.
We can take a look at its implementation.
This performs a query with sphere params.
We have a given radius.
We have a check to see if the actors that are overlapping a sphere of the given radius implement the
combat interface.
It even checks to see if they're dead.
If they're not dead.
Then we add them to the out overlapping actors.
So this is the perfect function for us.
So I'd like to call that function.
So I'm going to call you Ora ability System Library.
Get live players within radius.
Now this requires a world context object.
I'm just going to pass in the avatar actor.
So get avatar actor from actor info and we need a t array of actors.
Now I'm not going to pass in out additional targets.
That's going to be what this function returns.
But this function will get us all players, or at least all things that implement the combat interface
within radius.
And that's not what I want.
I only want the first few that are closest.
So we're going to have to call out the closest ones.
So for that reason I'm going to make a local t array of actor pointers.
And this is going to be overlapping actors.
So I'm going to pass in overlapping actors.
Now, in addition to that array, we need to have an array of actors to ignore.
So I'm going to go ahead and make that.
I'm going to copy this array and rename it to Actors to Ignore.
And in fact I'm going to make this first so that overlapping actors is the closest thing to the function
call.
And I'm going to take actors to ignore and add the avatar.
So get avatar actor from actor info.
Now we won't even have to filter that out.
Now, in addition to the avatar actor, I'm going to add the mouse hit actor as well.
So that way we're only getting additional targets.
We don't care about the mouse hit actor anymore.
We're already adding a gameplay cue to that one, so I'm going to take actors to ignore.
And add mouse hit actor.
And with that, I can pass in actors to ignore.
All right.
At this point I'm going to put these inputs on their own lines.
And let's see what our next input needs to be.
It needs to be a radius.
Now it's going to be a pretty big radius, and the aura beam spell could scale the radius with the level.
You know how to do that with curve tables, you could use a mathematical formula.
I'm going to hard code 850.
But you know how to parameterize that.
And for the sphere origin we're going to use the mouse hit actors location.
So mouse hit actor get actor location.
So after calling, this function will have an array of actors that are within 850 units away.
Now we need to get the closest few and or a beam spell should have a maximum for that.
Now, as I mentioned, we're going to be shocking more and more nearby goblins and monsters depending
on the level of this ability.
And we should go up to a max.
So or a beam spell is going to get a max number of shock targets.
So we'll have a variable int 32 max num.
We'll call it shock targets and we'll set it to five.
It could really be anything, but we'll give that a property with edit defaults only.
And of course you property gets a Y at the end.
There we go.
So edit defaults only.
And that'll be in the category of beam as well.
And we'll use that.
And what we'll do in or a beam spell is we'll have an INT 32 called num additional targets.
And we'll use F math and take the minimum between the ability level.
So get ability level and max num shock targets.
And looks like that is missing a parentheses.
There we go.
There.
That's better.
So num additional targets will be whatever ability level we're at.
But of course I'm going to use ability level minus one.
And that way we get the ability level number of beams total up to a maximum.
Now I'm going to comment that out and use this line when we're finished with everything.
But for testing purposes, I'd like to set a max number of five.
So I'm going to call this local num.
Additional targets local variable I'm going to set it to five.
So now that I have overlapping actors, we could have 20 or 30 actors.
We probably won't have that many, but we could have a lot of enemies nearby, and we're going to need
to get the closest few, and we'll need a function to get the closest few.
We can call it get closest targets, and we can make a static function in our ability system library
to get the closest targets.
So that'll be just under get live players within radius.
It'll be static and it'll be void.
And I'm going to call it Get closest Targets.
So we'll have an INT 32 called Max targets.
That's how many targets we need.
We're going to have a const t array.
Of a actor.
Pointers.
We'll pass it in by reference const reference called actors.
And then we'll pass in a non const t array of actors pointers of course.
And we'll pass this one in by non-const reference called out closest targets.
So we'll pass in two arrays one filled with actors and the other will be empty.
And it will have the closest targets.
It'll be this mini Max targets.
And if we're going to calculate the distance from anything, we need to know the distance from what.
So this function gets a const f vector that we can use to calculate the distance from.
We'll call it origin.
So it'll be the origin of this algorithm.
All right let's generate the definition.
Now, how do we get the closest number of targets?
That number being max targets out of an array.
How do we create an array of actors that contains only that number of actors from the actors array?
Assuming that the actors array has more actors than max targets, well, this could be done in a number
of ways, and I'd like to challenge you to give it a shot.
I want you to at least brainstorm and think about how you could possibly do it, and even give it a
try.
So if you're up to that challenge, pause the video now and implement Get closest Targets.
Okay, so how are we going to do this?
Well, first of all, if my actor's array, let's just say it has five actors in it and we pass in seven
for max targets.
Well, actors doesn't have seven, so it already contains the closest actors.
We can't return an array of seven actors.
We have to return actors.
Right.
So actors has to be bigger than max targets.
Otherwise we just return actors.
So we're going to check if actors dot num.
Now if actors num is smaller than or equal to max targets.
Then we can just set out closest targets to actors and return.
There's no point in trying to find the closest max targets targets if actors doesn't even have max targets
in it, so we can return early in that case.
However, if we make it past that now, we need to search through actors for the closest ones.
So here's how I'm going to do it.
I'm first going to make a copy of actors that's not const.
That way I can remove elements from it and things.
So I'm going to make a t array not const of a actor pointers.
And I'm going to call this actors to check and set it equal to actors.
So I'm making a copy of it.
After that I'm going to make a local INT 32 called num targets found.
That way I can keep track as soon as I find an actor that I know is one of the closest ones, then I
can increment this integer, and then I'm going to use a while loop, and I'm going to continue looping
as long as my num targets found is less than max targets.
Now this should work because as long as max targets is greater than the number of actors in our array,
then we'll find enough actors.
If not, we've already returned out of the function.
Now I'm going to make a double called closest distance, and I'm going to keep updating this to the
closest distance that I find as I loop through this array.
And in order to check to see if something is closer than closest distance, I need to start closest
distance off at a really big number.
In fact, I can make it the biggest it can possibly be for a double.
I can use t numeric limits specifying double, and there's a function on this called max, and this
returns the maximum possible value that a double can be.
So that's what I'm starting double off as the biggest it possibly can be.
And after that I'm going to loop through actors to check.
So I know actors to check contains our actors.
So I'm going to say for a actor pointer potential target in actors to check.
So we're looping through every single one and I'm going to calculate the distance.
I'll make a const double distance.
And I'll calculate the distance between the potential target and my origin.
So I'm going to say potential target get actor location minus origin.
I'll get that vector and get its length and store that in distance.
So for each actor in actors to check I'm calculating its distance to the origin.
And I'm going to check to see if that distance is less than closest distance.
So I'm going to say if distance is less than closest distance.
Then.
Now my closest distance is this distance.
So I'll say closest distance equals distance.
And I'm going to make a closest actor that I'm going to set to the potential target here.
So before looping, I'm going to create, along with my closest distance, an a actor called Closest
Actor.
And as I loop through this array of actors to check each time, their distance to the origin is smaller
than my closest distance, I update closest distance and I also update closest actor.
I set it equal to this potential target.
So by the end of this for loop, my closest actor is going to be the closest in this entire array to
the origin.
And by the time I finish my for loop, my closest actor being the closest one can be removed from actors
to check.
So I'll say actors to check.
Dot remove closest actor.
Now, on top of that, though, I need to remember that closest actor.
I'm going to add that into my out closest targets.
So I'm going to say out closest targets.
And I'm going to add unique.
That way we'll never add more than one of the same one.
So now out closest targets gets that closest actor.
And as soon as we've done this I'm going to increment num targets found.
So I'm going to say plus plus num targets found.
Okay.
So what this is going to do is while num targets found is less than max targets, it starts off at zero.
Let's say max targets is five.
So as long as num targets found is less than max targets, this whole loop will keep iterating.
So first it creates a really big double.
It creates a closest actor.
And then we loop over actors to check which is a copy of actors.
We create a const double and set it equal to the length of the vector from the origin to each potential
target.
That's the distance of that potential target to the origin.
If that distance is less than our closest distance, which starts off really big.
So at first it will be, then closest distance becomes that number, closest actor now becomes that
potential target.
And then the for loop goes to the next actor.
And the distance of that actor to the origin is calculated.
If that's even smaller than the closest distance, which was the distance of the first actor, well
then now closest distance is a little bit smaller.
If it's not, then closest distance doesn't get updated and we go to the next actor.
So we're checking all the actors in the array.
But every time we find the closest actor in the whole array, we remove it from the array and add it
to the out parameter array and increment num targets found.
And then the while loop starts over.
And this time actors to check is one less.
And we keep doing this until we've found the number of targets we need.
And of course if actors to check ever becomes empty, well then we can have a safeguard here.
We can say if actors to check dot num equals zero, we can break.
So we can have a safeguard there.
Okay, so here's my algorithm and I'm really excited to see what you came up with.
And I'd like you to share it in the discord and show how much better your algorithm is than mine.
Because there are multiple ways to do this.
And you could get more advanced, you could get more clever.
So I'm interested in seeing what you came up with.
But now that we have get closest targets, we have something that will fill in out closest targets and
we can specify how many of the closest targets we want.
So back in Aura Beam spell we can call this function and store additional targets.
So I'm going to use your aura ability system library.
Get closest targets which needs a max targets.
I'm just going to pass in num additional targets.
That's going to be five.
I'm going to pass in our overlapping actors because we just got all live players within radius.
So we're passing that in as the actors.
Now we need our out parameter out closest targets.
That's going to be out additional targets.
That'll be whatever we pass in to store additional targets here.
And finally we need the origin.
And I'm going to find all actors closest to the mouse hit actor.
So we're going to say mouse hit actor.
Get actor location.
After this out, additional targets will be filled in with the closest five.
If there are five actors that implement the combat interface that are not dead and we can use that.
So I'm going to go ahead and run and debug mode.
And I'd like to just check to make sure that this is working.
We can check by adding a whole bunch of goblins into the world, and then see what this function returns
for us with some debug spheres.
So I'm going to get my ability open.
And as soon as an electrocute, we've added our first gameplay cue.
I'm going to call our new function and hopefully I made it blueprint callable store additional targets.
Yes, it's blueprint callable.
So we're going to call store additional targets and this will return us a T array.
So we'll go ahead and hook both of these up.
And I'd like to create a for each loop.
And each of these is an actor, and I'd like to get its location and show a debug sphere.
So in the loop body draw debug sphere.
We're going to get our array element.
Get actor location.
Hook that into the sphere center.
I'm going to make it red and make the duration 20s and the thickness we'll leave it zero.
And with that, I'd like to create a whole bunch of these goblins and.
We'll see if we get the closest five.
So I'm going to copy each of these a couple times.
Like so.
And.
We'll do a couple more.
There we go.
And with that, I'm going to save all and press play.
Okay, so those spheres are too big.
Let's make the radius.
Oh, I didn't change the radius.
I'm going to make it about 15.
And as soon as I release their one, two, three, four, five we got the five closest.
And this is within an 850 radius.
So we can also draw a single sphere when completed here.
We can draw a white one and this could be a radius of 850.
And we're drawing it at mouse hit location.
That's the location of the mouse hit actor.
So we'll draw that for a duration of 20 as well.
And that'll show us the radius that we're querying here.
It's quite big.
So we're getting the closest five actors to the thing we're shocking.
So right there let's try a different one.
We'll try this one here.
And we're getting those.
Those are the closest five.
And if we try over here.
Those are the closest five.
So our algorithm works.
Okay.
Now that we are getting additional targets, we got those five closest actors.
It's now time to apply some gameplay cues to those actors.
And then we also need to figure out how we can start doing some damage to those actors.
So we're one step closer.
Excellent job, and I'll see you in the next video.