Welcome back.
Now we've done a few improvements.
I'm going to close all these tabs and I took all my enemies out.
So I'm going to bring a couple back in.
I am going to leave my nav mesh bounds volume off to the side though, so they can't come at me.
And I'm going to go into blueprints character Goblin Spear, and I'll bring in a couple Goblin spears.
I'm going to put one here and I'll put another one right there.
And press play.
Now here's what I wanted to observe by dragging these two in.
Now, if I right click on this one, I'm shocking it with the beam.
Right?
But if I right click on the goblin behind it, we're going straight through the first one.
And that's a problem.
So we need to fix that.
Now in addition to that we're going to have multiple targets.
You probably don't know this yet, but as we level up our electric beam or our electrocute spell as
we spend points on it, I'd like this electric beam to propagate to nearby enemies.
So if I'm shocking this one here, once we level it up, I'd like it to propagate and create a connecting
beam between these two enemies if they're close enough.
And then if we level it up again, well, then if there's two enemies nearby, if I can.
Duplicate this one.
If, let's say my electrocute spell is level three.
Then if I shock this guy, I want two beams to propagate to nearby enemies.
So that's the kind of thing I have in mind for this type of spell.
So whenever I start electrocuting something like this guy over here, I'm going to need to get.
The first thing that my beam would hit, which would be this guy here, because this one's in the way,
right?
So if I shock over here, I need to hit this one before I hit that one.
And I'm going to call the first enemy that I hit the first target, I'm going to call it my first target
okay.
So we need a way to get that first target.
So let's go into our gameplay ability.
Ability system or a abilities lightning electrocute.
And here in electrocute, if we go out to the event graph, we'll see that we're creating the beam by
adding a gameplay cue on an actor.
We're actually adding it to the avatar actor specifically, but we're passing in the mouse hit location
through with the gameplay parameters, and that's why our beam is positioned correctly.
But now I'd like to handle this with more care.
I'd like to take this whole bit here where we're getting the weapon.
We're making the gameplay parameters and adding the gameplay cue on an actor.
I'm going to collapse this to a function, and this is all going to be related to spawning the electric
beam.
So I'm going to right click collapse the function and call this spawn electric beam.
And now this function will handle all that we need to do to spawn the electric beam.
And the first thing we need to do to spawn the electric beam is to get our first trace target.
In other words, if I'm again zapping behind this person, then I need to actually hit what's in the
way.
Right.
It's kind of like in shooter games, if you're doing a line trace with a hitscan weapon and you're aiming
over here, well, you should hit whatever's between the gun and the target, right?
Because that's how it would be in real life.
Okay, so for that reason, I need to get the first trace target.
And this is going to be in a C plus plus function.
So I'd like to do this in the most optimal way possible.
So I'm going to close the editor.
I'm going to open up my ability which is or a beam spell.
And we're going to add a blueprint callable function to or a beam spell.
And we'll make it public.
And I'm going to call this trace first target.
It's going to take a const f vector by reference called beam target location.
Because we're already going to have a beam target location.
Now we need to trace and see if there's something in between Ora's staff and the target location.
So we're going to generate this definition.
And what we're going to do is we're going to perform a trace.
But this trace in particular, I'd like it to be a sphere trace.
So we get a little bit of leeway just because we don't really want to be too precise here.
You could do a line trace if you wanted to, but I'd like to capture anything in the way, even remotely
in the way with a bit of a sphere trace.
Now, to do a sphere trace, one of the functions the engine has is you Kismet system library.
So as soon as I typed, that writer included the header for me.
And the function on this library I'm interested in is sphere trace single.
Now sphere trace single requires a world context object.
And I can pass in owner character, and I can even check owner character.
At this point it should be valid by the time we call this.
Now for Sphere Trace single, it needs a start location and we need to know the socket location.
So this is going to be tracing from the tip socket on the weapon right.
So for that reason I'm going to get the owner character.
And see if it implements the combat interface.
We can wrap this in an if statement, and then we can take the I combat interface and execute.
Get weapon and we can pass in owner character.
And if we get that weapon, we can get its socket location.
So I'm going to store this weapon, returned the skeletal mesh component.
And to use skeletal mesh component pointer called weapon.
And we'll wrap this in an if statement as well, just to make sure.
That we have a weapon.
And then I'll make a const f vector called socket location.
And I'll get the weapon and call get socket location passing in an F name with type socket.
And of course this could be a parameter, this f name.
It could be a member variable on or a beam spell.
And then you could subclass this and use it for enemies.
For example I'm just going to use type socket for now.
Just putting it out there.
You could do that.
And once we have the socket location that's going to be the trace start for the sphere trace.
So right here we'll say sphere trace single socket location will be that start the end.
We have that.
It's the beam target location.
Now for the sphere radius.
It's not going to be that big about ten for the trace type query.
I'm just going to use trace type query one trace complex is going to be false.
I rarely trace against complex geometry.
And the next input we need an array of actors to ignore.
So we're going to create one of those.
So we're going to make a t array of actors.
Those are pointers we'll call this actors to ignore.
And we can add the owner character.
So actors to ignore dot add owner character.
And we can pass actors to ignore into the function.
Now we need a debug trace type and for now we can say E draw debug trace for duration and we need an
f hit result next.
So we'll make one of those.
We'll call it hit result and we'll pass that in.
I'm going to start putting these on their own lines here.
So hit result is next.
Be ignore self is going to be true.
We do want to ignore the self.
And I don't think I need any more parameters.
We'll leave those trace colors at their defaults, and we're not even going to draw a debug once we're
done with this.
For now, though, we can draw one.
So once we perform a sphere trace, we need to see if we got a blocking hit.
So we'll say if hit result dot be blocking hit, then once we get that blocking hit we're going to reset
the mouse hit location.
I'm going to set it to our hit result dot impact point.
And I'm going to set the mouse hit actor to hit result dot get actor.
So now, if we had something in between the staff and our target point, we're resetting the mouse hit
location and that target actor.
All right, so we're ready to launch and try this out.
But we do need this to be a blueprint callable function.
So we'll make that happen.
And let's go ahead and launch the editor.
Okay, so we're back in the editor and right here in Spawn Electric Beam, we can now call our trace
first target blueprint callable function.
And we're going to need to pass in the beam target location.
And luckily we have that.
It's called mouse hit location.
We can get that and we can pass it in.
Now at this point we'll be performing a sphere trace with debug.
And since we're resetting our mouse hit location in actor, that mouse hit location that's being passed
into our gameplay parameters should now be updated.
Let's test that theory.
And sure enough, we are getting the trace, we're getting the hit, and our beam is stopping right
there on the actor that's in the way.
So now that that's working correctly, I can go in and remove the debug.
We don't need to see the debug.
Instead we can just use draw debug trace none.
And now we won't see anything except our beam of course.
So back in the editor, after making that little change, we should now see that.
Sure enough, if we're zapping this dude back here, we hit this dude here.
So.
That works well.
And because we're doing a sphere trace, we have some leeway.
Only if we miss by a great deal.
Are we going to miss?
Right.
Okay, so that's looking good.
Spawn Electric Beam is now using a Sphere Trace performed in C plus plus for optimal performance.
And once we have our first target, we're going to start doing things.
And once we hit something, I need to know if we hit the floor or we hit an enemy, right?
Did we hit a wall, a floor, something that's not an enemy?
Or did we hit an enemy?
If we did hit an enemy, then that's going to matter depending on what we want to do next.
For one, if we add a gameplay cue, I want to add this gameplay cue on the actor we hit if it is an
enemy.
Why?
Because we're going to be adding gameplay cues from one enemy to another enemy.
We're not going to be adding all of these gameplay cues to the same actor aura, because that wouldn't
work.
We'll have to add a gameplay cue to separate enemies each time, and so the first time we trace, after
we trace our first target, I'm going to make gameplay cue parameters specifically for that target.
So I'm going to right click and say make gameplay cue parameters.
We'll make that struct and we'll fill this in.
And I'm going to fill it with a location that's going to be mouse hit location.
We'll get that.
We'll pass it into location.
I'm also going to set the source object.
As this is an object reference, it's a good way to pass an arbitrary object in, and I can pass my
mouse hit actor through as the source object.
And since I need a target attached component, that's going to be my owner character's weapon.
So I'm going to call get weapon passing in the avatar or the owner character.
Either one should work.
And we can pass this straight in to the target attached component.
So.
We're going to call get weapon first.
As we get the weapon.
We take its value, we pass it in as target attached component to our gameplay parameters.
So now we have these gameplay parameters, right?
I'm going to promote this to a variable.
So promote a variable and I'm going to call it first target queue params.
The reason I need the first target params is because it's going to be different.
The target attach component is going to be the weapon, but for subsequent targets, that's not going
to be the case, because I'm going to want the second beam to go from my first target to the next enemy
over, and the third beam to go from that first target to the next enemy over, and so on.
Now, once I've stored my first target params, I'm going to take these lines and move them away for
a second.
I need to see if my mouse hit actor.
The thing I hit implements the combat interface.
That's what's going to tell me if it's the floor or an enemy, right?
If it's an enemy or not an enemy rather.
So I'm going to use does implement interface specifying the combat interface.
And we're going to use the mouse hit actor.
And we'll hook that in and we'll have a branch.
And we'll check that.
Now this we can just say is mouse hit actor an enemy?
Okay, so the answer to that question determines what we do next.
If the answer is yes, we have this true right.
And the thing that we apply or add this gameplay cue to depends on the answer to this question.
If we did hit an enemy, then I want to add the cue to the enemy.
That's going to be our mouse hit actor.
If we did not hit an enemy, I want to add the cue to the avatar actor.
Or in other words, so what I'm going to do is the target for the gameplay cue is going to be I'll go
ahead and make it a local variable and call this cue target.
And I'm going to set the target based on the answer to this question.
If we just hit an enemy, the target will be the mouse hit actor.
So we're going to set target equal to mouse hit actor.
So that goes to true.
In the false case, we're going to set it to the avatar.
So get avatar actor from actor info.
That's who the target is going to be.
Now either way we're going to apply a gameplay queue.
So we're going to call Add gameplay queue on actor.
I'm going to go ahead and just.
Take these two nodes.
I'm actually going to move everything way over here and just right here.
Add gameplay cue on actor.
No matter whether the thing we hit is an enemy or not.
Both of these go into add gameplay cue on actor.
The difference is the target.
What we set the target to depends on if we hit the enemy or not.
If it implements the combat interface rather.
Now our parameters are going to be the first target params.
We've set those and now our target might be an enemy and it might be Ora.
So if we go back to our gameplay cue shock loop.
An ability system gameplay cue notifies GC shock loop and go to while active.
We're going to check our source object now and see what it is.
Now the source object could be aura, it could be a player interface, or it could not be.
It depends.
So I'm going to store the source object.
I'm going to promote it to a variable.
Called source Object.
And then after we've spawned the system and set it to our beam system variable, I'm going to perform
a check.
I'm going to see what that source object is.
So I'm going to get it.
And I'm going to say does implement interface.
And I'm going to check to see if it implements the combat interface.
And we'll place a branch here.
So what does that mean if this source object is implementing the combat interface?
Well, if we look back in electrocute, we first checked that mouse hit actor to see if it implements
the combat interface.
And if it does, that's who we're applying this gameplay cue on.
In.
Either way, it's that mouse hit actor that we're passing in for the source object.
So we know a couple of things, right?
We know that if we hit a combat interface, we're applying the cue to that actor that we hit.
If we didn't hit a combat interface, we hit a floor or something.
We're applying that cue to the avatar, and we know that in shock loop by checking the interface here,
true means that we hit something like an enemy.
False means that we hit something like a wall.
Now that means something different for our Niagara parameter.
If we want to set that Niagara parameter to the mouse hit location, well, the mouse hit location better
be correct, right?
Well, it'll be correct if we hit a wall or a floor or something like that.
In other words, in the false case when our combat interface check fails.
And of course we need to set that Niagara variable to our beam system.
We're going to go ahead and take that beam system variable.
That's what we're going to set the parameter for.
We'll set it to mouse hit location because we hit a floor.
We didn't hit a combat interface.
If we did hit a combat interface we want the location of that combat interface.
So we want the location of our source object.
Let's get that.
We're going to have to cast it, at least to an actor.
And.
We're going to get its location with git actor location.
And that's the location we're going to use to set the Niagara variable.
So we're going to duplicate this.
And instead of mouse hit location we're using this actor location here.
And that will be here if we don't fail with the cast.
Just going to stack these nodes here.
So whether the source object is a floor or a wall or a combat interface, either way we're setting that
Niagara variable.
So we'll just say up here.
Mouse hit actor was a combat interface.
And we'll say down here.
Mouse hit actor was not a combat interface.
Okay, so organizing these nicely.
Like so.
Now.
We've set our vector parameter on the Niagara system.
We're going to spawn sound attached no matter which one we did.
So we're going to plug both of these in to spawn sound attach.
We're going to attach it to attach component.
We're going to save that shock sound audio component.
And we're going to end by reaching the return node.
So basically all that we've changed is that if we don't hit a combat interface, we don't hit one of
our goblins or something.
Then we're going to set the beam end location to the place we hit.
Otherwise we're setting it to the location of that actor that we hit that implements the combat interface.
We can test this by right clicking.
And of course, now that we're adding a cue to an actor, we're only going to get to remove that cue
if we've added it to self, because we're only removing it from the self.
If we add it to another actor, we can not remove it.
It's stuck.
So that's something to be aware of.
But luckily our electrocute has saved first target params.
So we need to know if we should remove this first target q params from the self, the owner from the
avatar actor, or from the mouse hit actor.
Because if the mouse hit actor implements the combat interface, then we're adding the looping gameplay
cue on the mouse hit actor.
If it doesn't implement the interface, we're adding it to the avatar actor.
So what we should do is when we know this boolean value, we should save it.
So we're going to promote it to a variable.
So right here, as soon as we know if the mouse hit actor implements the interface, we're promoting
this to a variable not even a local variable a regular variable.
And it's going to be called implements interface.
It should actually be called first target implements interface.
But that's a long name.
But even so we can call it that first target implements interface.
That means we'll need to make room for it.
But that's fine.
At least we know what we're talking about.
So now that we know that our first target implements the interface, that means we added a gameplay
cue to it and we have to remove it.
So we have to go to prepare to end.
And instead of just removing the gameplay cue from owner, now we need to check this boolean with a
branch.
We need to see if the first target implements the interface.
If it does, then we need to remove the first target cue params.
So rather than removing a gameplay cue from owner, we need to take our mouse hit actor and we need
to call remove gameplay cue on actor.
So we know that it implements the interface.
Therefore we added the queue to it.
We need to remove it and we remove it by gameplay tag shock loop and by parameters.
We have to use those parameters.
So we plug in those gameplay queue params.
However, if this boolean is false, then we know that we added the gameplay queue to the avatar actor.
So I'm going to delete that node and reuse remove gameplay queue on actor and use the avatar actor.
So get avatar actor from actor info.
That's the target and it's the same gameplay queue params.
We added it.
Instead to the avatar.
So now we're checking this boolean to see who we applied these first target params to.
And now.
We remove them.
And if we hit a wall or something, well, we remove them from the self from the avatar.
But if we hit one of these enemies, a combat interface, we remove it from that actor.
Because that's the mouse head actor.
Okay.
And by the way, if you're wondering why I was taking some.
Passive damage right here.
That's because the enemy's attack abilities have a debuff chance.
I believe I set that to 100.
So anyway, we won't dig into that right now.
But now we're removing the queue from whoever we added it to, whether it's the mouse hit actor or the
avatar.
This is very important because the difference is crucial.
If we didn't hit a combat target, then we don't need to propagate our electric beam to future targets.
But if we hit a combat interface, we do.
That's why we need the distinction here.
So our next step in spawn electric beam.
After we've added a gameplay queue to our first target, our mouse hit actor or our self.
If we didn't hit a combat interface, now we need to propagate the beam towards nearby enemies.
So in other words, we're going to start off by.
Every time I launch a beam and a hit one of these enemies, it's going to go to the next enemy over.
In fact, it'll go to the next, however many enemies we choose, if they're within a certain radius.
So that's going to be next.
For now, we have our beam working, and the difference now is crucial.
It's that we're adding our gameplay cue to the self or the avatar.
I'm calling the avatar the self unless we hit an enemy or a combat interface, in which case we now
apply it to the mouse head actor and remove it from the mouse hit actor.
Remembering by storing that first target cue params and the mouse head actor.
So next we'll apply multiple cues to multiple enemies based on how close they are.
We'll do that next.
I'll see you soon.