Welcome back.
So now that we have a spread of 90 degrees and we're launching five projectiles, we'd like to start
making these projectiles a little more interesting.
For one, I think I'd like to add gravity to them.
And that's pretty easy.
I can go to my Firebolt blueprint.
Here it is.
And I can take my projectile movement component and set its projectile gravity scale to one.
And with that we have gravity.
Let's see what that looks like okay, so yeah, they fall straight down.
But again we have pitch override and spawned projectiles.
We can set that to something high like 65.
And we can see what that looks like okay.
So we have an arc now which looks pretty cool.
So that's kind of the first thing I'd like to do.
65 is a little high, maybe 45 is okay, and the Firebolt could probably get some higher speed now,
maybe 750, but we can tweak that as well.
There we go.
Cool.
Now, the thing about having gravity.
Is now.
We don't have infinite reach, right?
And something we can do that can sort of make things a little bit better for us is to make these homing
projectiles.
Now here's the behavior I'd like.
If I'm hovering over an enemy and I click on it, I want to set the homing projectile target to that
enemy.
In other words, when I launch, I want all of these fireballs to fly out, but then arc towards the
enemy.
But if I clicked on the ground, like over here holding shift and left clicking, well, then I want
to home in on that place that I clicked on, which is kind of hard to see because we're not showing
any particle effect for that.
Now we could spawn a Niagara system right there, wherever we click, every time we click.
As long as we didn't click on an enemy, we can make that happen.
But for now, let's focus on the homing projectiles and then we can focus on.
Playing some particles.
So homing projectiles, how do we do it?
Well, we know that in our Firebolt ability, when we call spawn projectiles, there's a homing target.
Now, the homing target is an actor that we pass in, and what we pass in could be an enemy.
It could not.
What are we going to pass in?
Well, we have a hit result, don't we?
And if we take that hit result, it has a hit actor and we can promote that to a variable.
So I'd like to promote it to a variable.
I'm going to remove this on end ability for now and take the hit actor, promote to a variable and call
this mouse hit actor because our mouse hit it.
I'll go ahead and collapse that hit result, and we'll make sure that we set mouse head actor.
And by the time we call spawn projectiles, we can pass in that mouse hit actor.
Now the question is what do we do with mouse hit actor?
Well, let's close the editor and go back to C plus.
Plus to our spawn projectiles function.
Now we could just code this for homing projectiles, or we can pass in a boolean for whether or not
we should spawn homing projectiles.
Or we could have a boolean on the Aura Firebolt ability.
Really?
It doesn't matter.
I'm just going to make them homing projectiles by default.
We know how to make booleans and set them.
So we're going to first take that mouse hit actor, which we passed in as homing target.
And I'm going to check to see if it is an enemy if it implements the combat interface.
So if it's an enemy or another player character.
So I'm going to say if homing target.
Implements you combat interface.
So we know if it implements the combat interface that we're not clicking on the floor or a wall or something
like that.
If that's the case, then I'm going to take my projectile.
And set something on it.
And of course, that means we need to be in the for loop where the projectile is in scope.
And on top of that, we have to be in here before we finish spawning.
So I'm going to take the projectile in this case and get its projectile movement component.
And the projectile movement component is of course an incomplete type.
So I can go ahead and include that that exists in game framework.
So I'm going to include game framework.
Projectile movement component.
Now that it's not an incomplete type, the projectile movement component has something called a homing
target component.
Notice it's a weak object pointer to a scene component.
Now it's weak because the projectile movement component doesn't want to affect the reference counting
for garbage collection if it's holding on to something, right.
Let's say we set the projectile homing target to some object in the world.
We don't want that object just staying alive just because our projectile movement component's homing
target component points to it.
Just know that things can become null up from under a weak object pointer.
So something to be aware of.
But we can take this homing target component and we can set it to a component.
Now it's a scene component.
And we know that we have a homing target which is an actor.
And all actors have a root component.
So if we get that root component we can assign an that value to the homing target component on the projectile.
But what if we hit the floor or a wall.
Well, that's not going to pass this check because it doesn't implement combat interface.
So we need an else case.
Now how are we going to handle the else case.
Because if we just do what we did here and set the homing target to the root component of the actor
we hit.
Well, think about that.
If it's a static mesh actor, like a big floor tile, then the location of that root component is basically
wherever that mesh origin is.
It's not necessarily where you clicked.
So what we need to do is figure out how we can get a component in the location of our mouse hit from
our line trace under our mouse cursor.
Right.
So how do we get that.
Well we could simply create a new scene component.
So what I'm going to do is take my projectile and get its projectile movement component and get that
homing target component and set it equal to a new object that I create with new object.
And I'm just going to make a new scene component.
Now this requires a class.
So I'm just going to use you seen component static class.
And that's just going to create a new you seen component.
And it's going to set it to the homing target component.
Now here's the thing though homing target component is a weak pointer.
That means when the projectile dies in homing target component goes out of scope, this new object is
not going to be cleaned up.
So how do we get garbage collection?
Because we don't want to just spawn a bunch of new you seen components and never have them cleaned up,
right?
Well, we could make a variable on our projectile class.
We can go to actor or a projectile.
We can make a scene component pointer.
We'll just make it public.
We'll make it a t object pointer.
Use scene component and we'll just call this homing target scene component.
And if we give it a new property, it'll be garbage collected.
The aura projectile gets destroyed.
So will this.
And we don't even have to set it to anything.
Now an aura Firebolt.
We can take our projectile and get its homing target scene component and set that to the new object.
Now.
It'll be garbage collected, and then we can just set the homing target component to the projectiles
homing target scene component.
And there we go.
Make sure we have those parentheses there.
Okay.
So we created a new scene component.
And we set the homing target component to that.
Now after this our projectile now has a homing target.
And we can set its homing acceleration magnitude.
Basically how fast do we want those fireballs to turn and arc towards their target.
Well let's get our projectile get our projectile movement component.
And from the projectile movement component we can type homing.
And here's homing acceleration magnitude.
And we can set that to a value.
Now we can make a couple of parameters and have a random number between a minimum and a maximum.
I think I like that idea.
So our Aura Firebolt can get two floats.
We're going to have one float called.
Homing acceleration men, and I'll give it a value by default of 1600 f.
I'm also going to have one for the max, so we'll have a homing acceleration max.
And this will be 3200.
We'll play with these.
But then in Aura Firebolt, I'm going to set this equal to F math.
And I'm going to use f rand range, the float version of rand range, and use homing acceleration min
for the min and homing acceleration max for the max.
And now we have our homing acceleration magnitude.
Now we also need to tell the Projectile's movement component that this is a homing projectile.
So we can get our projectile, get its projectile movement and set the boolean on it.
B is homing projectile to true.
And again you could make a boolean here.
In fact why not.
Since we're making parameters and or a firebolt we'll go ahead and make one more.
It'll be a bool called B launch homing projectiles.
True by default.
And we'll use that right here.
And now we can turn it on and off.
Let's give this a try.
All right.
Moment of truth.
Ooh, look at that.
I'll go ahead and open our asset editors as well.
But did you see that?
Let's see that again.
Okay.
So.
It looks like.
Our projectiles are definitely homing towards something.
But they seem to all be homing towards.
The wrong location.
Let me try launching at an enemy.
So they do go towards the enemy.
So that's good.
And if I'm close enough.
Whoa, there.
That looks good.
We don't have radial damage with the fall off or anything like that.
But we can see that our projectiles are arcing towards their locations.
Now that depends on that homing acceleration magnitude, of course.
But we've got an issue here and that's that when I'm not on a target.
We're going to the wrong location, I think.
So we need to figure out what's going on there.
In other words, if the homing target does not implement the combat interface well, we need to see
what's happening here.
And I see what's happening right now.
We never actually set the location of that homing target.
We need to do that.
So we're going to take that homing target scene component that we just created.
We need to set its world location.
So to set a component's world location we use set world location.
And we already have a projectile target location we can use.
So that's going to fix that problem.
So we can close and relaunch and test this properly.
All right.
Let's check this out.
That's much better.
Look at that.
Now our firebolts don't go that far.
So we can change that in a number of ways.
We can change the velocity.
We can also change the pitch override.
We can make it a little higher 55 degrees.
We could take our Firebolt, get that projectile movement component, set its velocity to say 850.
There we go.
All right.
So when I'm this far away, that guy is out of reach.
But you know, we know how to tweak parameters, don't we?
And we don't want to be too op.
Excellent.
Really nice, looks great, and we have gravity working.
And of course that's another thing you can play with.
You can set that projectile gravity scale to a lower value.
You can set it to zero.
And then things are not going to be slowed down at all.
So that's another thing.
You know, if you take gravity out of the equation, well then there is really no limit.
We can.
We can get way far away.
I'm going to get really, really far away without gravity.
It's almost off the screen.
And we definitely we definitely hit them.
So I actually kind of like it without gravity.
So I'm going to leave it off.
And am I okay with that pitch?
I think the pitch can be 45, and I do think the firebolts a little fast.
650 would probably do.
All right.
Things are looking great.
Okay, so before we wrap up, the last thing I want to do is not have a default of five projectiles.
I just want to have that projectile parameter Max num projectiles for the number of times we level up.
Every time we level up, I want to get one more.
So in other words, I'm going to come back into my spawn projectiles.
And there was a line that I commented out and I must have deleted it.
It was where we calculated the number of projectiles.
It's gone.
But now when we call evenly spaced rotators, we need to use a different number than num projectiles.
So we're going to have an int 32 called effective num projectiles.
And it's going to be the result of an F math min between num projectiles.
And get ability level.
And then we're going to use effective num projectiles instead of num projectiles.
This can be const.
Now here's the cool thing.
We'll start at level one, right?
And if we level up, we can spend a point on our Firebolt spell.
And once we spend a point, it'll be level two and then we'll be spawning two projectiles.
So now we have an incentive to level up our ability.
Which is actually really nice.
Let's check it out.
So I'm going to press play.
We get one projectile.
Big deal.
Cool.
But.
Let's kill one of these things.
And level up.
Now that we've leveled up, we can get our ability spend a point on it.
And now our description says launch is two bolts of fire, right?
And we actually do.
If that doesn't make you happy, you have no feelings.
All right.
This is looking great.
And of course, we can rain twice as much damage on things, which is really exciting, if you ask me.
And let's just test leveling up again.
I ran out of mana.
I almost said ammo.
I ran out of mana.
And why did I run out of mana?
All of a sudden?
Because my Firebolt cost 12 mana instead of two at the next level.
That might be a little harsh.
And as we start progressing more and leveling up more and testing more, we're going to find that some
of those starting ballpark values that we gave some of our stats might need to be tweaked.
So we'll do that as we go.
We can go to ability system data set cost.
Here's our Firebolt cost.
We're going from 2.5 to 12.5.
That's a little harsh.
We can go from 2.5 to 3 to 3.5.
3.4 is fine to 5 to 7.
To 11.
To 15.
Wow.
I went really up there, didn't I?
We'll go up to 20, 25, 35.
So there's our step curve.
All right.
So leveling up.
Oh, didn't mean to hit equip, but I did level it up in our Manacost is now three.
Launching to.
Let's see if they give us.
I don't know how much XP.
I don't remember, I think they gave us 300 each.
Yeah, that was enough to level up.
So now I can go up to level three and launch three.
Look at that.
Excellent.
So I guess it makes sense that it should cost more mana.
I'll probably go and nerf this ability in the future by changing those mana costs, but that's fine.
The important thing is it works.
Everything's looking great.
Firebolt is looking great.
I'm going to give you a extra challenge if you want to go in here and add more info to this if you want,
make this more descriptive.
Now, before we finally wrap up for the last time, I'm going to go ahead and show you one issue.
And that's if we are launching Firebolts.
And then we go and click I'm going to shift click over here.
Oh what's going on.
Well our homing target is null because we didn't click on anything that gave us a hit result because
those blocking volumes don't actually block the visibility channel.
So in that case well that means homing target being null is a legitimate possibility.
It's not an error or anything.
It's just something that we can run into which for that reason, we need to make sure homing target
is not a null pointer.
So we'll check that here.
We'll say homing target.
And.
So if homing target is valid and it implements the interface.
Either of those is false.
Then we just make a new homing target.
Right.
And next time we play test we'll test out that scenario.
Excellent job.
I'll see you in the next video.