Welcome back.
So we have our aura projectile spell and this gameplay ability is not doing a whole lot.
It's printing a string and it's activate ability function.
We want to do more than that and we're going to start with spawning a projectile.
So I'm going to close some of these files, but I'm going to leave some of them open.
I have my aura projectile spell and I've opened gameplay ability H.
I'm going to keep that open for now and my aura projectile that can stay as well.
Now Aura projectile spell is going to require a class to spawn for the projectile.
We need a projectile class.
So I'm going to add a subclass of variable for that.
So to subclass of and the class is going to be the aura projectile class.
Now I'm going to forward declare that up here.
So class a aura projectile.
And the subclass of will have the same type and this will be projectile class.
Now we'll give it a new property with edit anywhere and I'm going to make this blueprint read only and
we'll keep it protected so that we can have that blueprint access as well.
Now we want to spawn this, right?
So how are we going to spawn it and where are we going to spawn it?
Those are the questions at hand.
So here in Aura Projectile Spell, we no longer need this message from Kismet System Library.
We don't need that header either.
So we want to spawn this projectile.
Now, here's what I want to do.
I want to spawn the projectile on the server.
I don't want to spawn this locally.
I want this projectile to be a replicated actor.
And that way if the server spawns it, then the server will be in charge of moving it, handling its
location and all that good stuff, and the clients will just see a replicated version of the projectile.
So for that reason, I'm going to go up to Aura Projectile and just under primary actor tick we're going
to set be replicates equal to true So we now have a replicated projectile class now back here in aura
projectile spell, we're going to spawn a projectile, but only if we're on the server.
So how do we know if we're on the server?
Well, if you pause the video and look through gameplay ability, you may recall that gameplay ability
has a has authority function.
It says true if this is the server or single player.
Now this returns a boolean, so this is a nice convenient function that we can call without having to
go out of our way to find out if we're on the server.
Because there are other ways.
There are always other ways in gas.
We have lots and lots of ways to do the same thing.
We can get our owning ability system components and get the Avatar actor from that and see if that actor
has authority.
There's lots of ways, but we're going to call has authority now has authority, requires a gameplay
ability activation info pointer called activation info.
Well, we can pass one of those in because Activate ability has a gameplay ability activation info called
activation info.
Now it's passed in to activate ability not by pointer but has authority requires a pointer.
So what we can do is pass in the address of activation info.
Now has authority is going to return.
True or false if we have authority?
I'm going to go ahead and just store that in a const.
Bool called B is server.
So we know if we're on the server, it's if this is true.
Now for this video, I'm just concerned with spawning something, so I'm going to return from this function.
If B is server is false.
In other words, if not, B is server return.
And then if we make it past this, we're on the server.
Now we want to spawn a projectile right now.
We can do that with Spawn actor.
We get that from the world.
So we call get world and call spawn.
Actor and spawn actor can spawn something and we can set its location.
We can pass the location in and all that good stuff.
But I'm interested in spawning an actor that's going to fly through the air and hit something and apply
a gameplay effect.
In other words, we're going to set a gameplay effect or a gameplay effect spec on that actor.
And if we're going to be setting variables and things on the actor, there's a way to handle this such
that once the actor is finished spawning, all of those properties are already set and we can do that
by using spawn.
Actor deferred.
Now spawn actor deferred is a template we can pass in the type we'd like to spawn.
It's going to be a or a projectile.
And there's that header, auto included for me.
And this can take in a number of parameters, including the class.
We have our projectile class for that.
We also have a spawn transform that we're going to want to pass in.
So if we make one here F transform called spawn.
Transform.
Then we can pass that in here as well.
But we're going to want to set some properties on that spawn.
Transform, aren't we?
Now we can set an owner actor.
Now, if we're going to set an owner for this projectile, I think it should be the owner of this gameplay
ability and we can get that from the actor info.
In fact, the ability has a function Get owning actor from actor info, so that's pretty easy.
Now next is the instigator, and the instigator is just the pawn that instigated this thing that we're
doing in our case, spawning a projectile that's going to fly through the air and burn someone.
Right.
So what is the instigator?
Well, it's really just that owning actor, but it's got to be a pawn.
So we could just cast it to a pawn cast, to a pawn here and we can cast the owning actor so we can
just pass that right in there.
And there's the pawn.
Now, the next input parameter is a Spawn actor collision handling method, so we can specify that.
Now I'd like it to always spawn regardless of collisions or overlaps, so I'm going to use E spawn actor
collision handling method always spawn.
And now I have this big long line and I'd like to put each of these arguments on their own line here.
So let's just get these each on their own line.
Like.
So now this is going to spawn an actor at this transform.
But this transform is not really defined.
It doesn't have any location or rotation set for it or anything like that.
So where do we want to spawn this projectile?
Well, to just get things working, we could spawn it at the owning actor's location.
But ultimately I'd like to spawn this at the tip of the staff.
That's Aura's weapon, right?
That's where I'd like to spawn it.
However, if that's going to be the case, I don't really want to have to cast to or a character because
this is aura projectile spell.
I don't want it to be dependent specifically on the Aura character class.
I want to be able to get a socket location from the weapon of whoever owns this.
So for that reason, I'd like some kind of interface function, right?
And we know that we have a combat interface over here in our interaction folder.
And this is for functionality shared by both the Aura character and the aura enemy.
So really quick, I'm going to open Aura Character base to show you that Aura character base inherits
from I combat interface.
That interface that the character base class has, that means Aura, character and Aura Enemy both implement
this interface so we can have a function that returns a socket or at least a socket location if we need
that.
And then anything that implements combat interface can implement that function that returns a socket
location.
So why don't we create a function for returning that socket location?
I'm going to close our character base and I'm going to open that interface class.
So combat interface dot H, and I'm going to create a virtual function that will return the socket location.
So this will be virtual F vector and it'll be called get combat socket location.
I'll go ahead and create a definition here that just returns an empty F vector.
Like so.
And now that this function exists in the interface, we can override this now on a character base.
We have a weapon.
So the weapon is going to have some kind of socket on it, presumably, and that socket should have
its own name.
So provided that we have a socket on our weapon and that socket has some kind of socket name, then
as long as we set that in our character blueprint for the character and enemies that have a weapon,
that have a socket on it, then or a character base could easily implement that function from our combat
interface.
So just under weapon, I'm going to make an F name called weapon type socket name.
This will be the name for the tip of the weapon.
This is just to distinguish it from any other sockets that might be on the weapon.
This is the tip socket usually for casting spells or things like that.
So I'm going to make this a uproperty I'm going to make it edit anywhere category combat, just like
the weapon, and then we can implement that interface function.
So I'm going to implement that and we can just put it right here under weapon tip socket name.
So it's a virtual vector function called and what's it called?
Get combat socket location.
Get combat socket.
Location.
That's an override.
Will generate the definition and what is it going to return?
It's going to return the weapon socket.
So we're going to get our weapon and call get socket location.
And this requires an F name.
We're going to use that weapon type socket name.
So now it's up to us to set that weapon socket on the weapon and make sure that we set weapon tip socket
name to the name of that socket.
And then we choose where that socket goes on the weapon and then we can use it for whatever we want,
such as spawning a projectile at that location.
So now we don't have to have our projectile spell ability dependent on a character or even or a character
base or an enemy.
We're just going to cast to the eye combat interface.
So let's get that interface.
We're going to say eye combat interface that's going to result in the combat interface header included.
We're going to call this combat interface.
And set it equal to the result of a cast to eye combat interface.
And what are we casting?
We're going to cast the Avatar actor and we can get that.
We can use get Avatar actor from actor info.
That's a function that we have access to here on the ability class.
And as long as the Avatar actor associated with the ability system component that owns this ability,
then as long as it implements the combat interface, then we can get that weapon socket.
So I'm going to check if combat interface and then we're going to get that socket location by taking
the combat interface and calling get combat socket location that returns an F vector.
We'll store that in a const local F vector, and we'll call this socket location.
And there we go.
So now that we have a location, I'm going to move this call to spawn actor deferred along with that
transform, I'm going to cut and move that up into here and my spawn transform now can have its location
set.
I'm going to take spawn, transform dot location actually dot set, location and pass in socket location.
So now that Transform has its location set to the socket location.
Pretty nice.
Now we don't have really any meaningful way to set its rotation just yet.
There needs to be some kind of way for us to access where we're aiming at, right where we're clicking
in the world.
But as it stands, there's no easy way to do that just yet.
I'm sure you can think of ways to do it, you know, access the Avatar actor, perhaps get its controller
and cast that to an aura player controller and then access that hit result.
And but there are better ways and worse ways to do it right.
We went through all this trouble to make an interface function so we don't have to be dependent on the
Aura character class here.
We're depending on abstractions rather than specifics, and I'd like to keep it that way.
So one step at a time, we'll deal with the rotation of our projectile later.
For now, we just want to spawn it and we want to spawn it at our socket location.
So a couple things.
When we launch the editor, we have to make sure to set that weapon tip socket name on our character
and we have to make sure that auras weapon has a socket with that name.
Because here in Aura Character Base, we are implementing our new interface function get combat socket
location by getting the weapon, getting that socket location on it and passing in weapon tip socket
name.
We're not checking the pointer here, which means that the weapon should always be set on our aura character.
Now we can do a check here, check weapon if we want to do that, but I'd rather not check the pointer
and only return this if it's a valid pointer.
Because in the case where there's not a valid pointer, I'm considering that a problem, an error.
So we'll leave the check there.
Okay.
So great.
Now if we go back to Aura projectile spell, we know that we're going to have a good socket location
provided that we set that weapon tip socket name but we're calling spawn actor deferred.
This is different than calling Spawn actor to actually get that actor spawned.
We have to finish spawning now spawn actor deferred returns a t star, which is of course the type passed
in that's or a projectile.
We're going to take that return value and store it in a local variable.
We'll call it projectile with an E at the end.
And to finish spawning the projectile, we have to take it.
So we take that projectile and call, finish spawning.
And this takes in a transform.
So we'll just once again pass in spawn.
Transform.
So finish spawning is what's going to finish the spawning.
Now, why would we do this in two steps like this?
Well, that's so that we can set things here and we're going to make a big fat to do.
So to do here.
And that's going to be to give the projectile a gameplay effect spec for causing damage.
That's why we're going to do this in two steps.
We want to set this gameplay effect spec for the projectile before we finish spawning it.
For now, we're not going to do that yet, so we have quite a few things left to do.
Let's put another to do up here.
We'll say slash, slash to do, set the projectile rotation.
So we're not doing that yet either.
A couple things to do, but now we can test this out and see if we get a projectile spawned and spawned
at the tip of the staff to boot and combat interface could be moved inside the if statement as writer
is telling me.
Go ahead and do that if you like.
I'm going to keep it like this.
Let's go ahead and launch the editor and see if this works.
All right.
So back in the editor, I have my aura character.
I'm going to take my weapon and browse to it to its skeletal mesh and open that up.
And sure enough, it has a couple sockets on it.
It has a tail socket down there and it has a tip socket up here at the tip.
Looks like it's right here where that little stone is.
If I press w, I can see exactly where it is right there.
So it's called tip socket, which means I have to go back to our character select or a character self
and search for weapon tip socket name and set that name its tip socket.
So now that that's set, we can see if we can get a fireball launched at the tip of the staff.
So save all, let's press play and click on an enemy.
So looks like we got an exception.
Now, when we get an exception like this, we can look at the call stack and see what function calls
led up to it.
So we have ability input tag held.
We have try activate ability right here and we get all the way up to activate ability where we're at
projectile finish spawning here and now I'm seeing exactly what happened because we reached right here
projectile finished spawning and it would crash here if this projectile pointer was null.
And why would that be?
Null?
Well, we're not passing in a valid projectile class here.
And if I hover over it, it just says null.
So that's something that I forgot.
So what I can do is go ahead and launch again and make sure to set that projectile class because of
course, that is something we're going to need to set on the projectile spell gameplay ability.
So another useful example of those debug symbols, right?
So first I'm just going to verify on my aura character that weapon tip socket is still set and it is
it's set to tip socket.
That looks good.
Now I'm going to go to blueprints ability system, gameplay abilities, fire Firebolt and Firebolt and
make sure projectile class is set.
And I'm going to set that to BP Firebolt.
Now I'm going to try this out.
And there's the Firebolt Now it looks like it's working as expected.
Like I'm aiming at the enemy and I shoot a fireball at the enemy.
That's just coincidence that it's going over there to the enemy.
If I come over here next to the enemy and click on the enemy, it still goes that way because our rotation
for this projectile is not defined.
It's the zero rotator, right?
We're not setting it.
And of course, I can only click once because we're never ending the ability, so we can't activate
it again.
And the blueprint isn't doing anything except print a string.
I'm going to go ahead and remove that.
Now, the blueprint event graph is completely empty, but we see that we're able to spawn the projectile
and it's spawning, it looks like, at the tip of the staff, which is where I wanted it to spawn.
So that's perfect.
So everything that we've tried to do so far is working.
We do have a couple to do's.
We need to make sure to set the rotation.
We need to be able to aim this fireball.
We can't just shoot it in that same direction every time.
And of course, later we're going to implement damage with a gameplay effect.
We want to do that too.
So there are a few things to take care of.
But it's a great milestone to know that our gameplay ability can spawn something.
Now, we also mentioned earlier on that we wanted to play a montage and just to remind you, if we go
to assets, characters, aura animations, abilities, there's an animation called Cast Firebolt.
It looks like this.
Now, it would be a lot cooler if we were playing this animation and spawning the fireball like that.
If we were letting her play this animation and perhaps spawning the fireball right there, right at
the tip of the staff.
That would look great.
So that's something that we want to do as well.
And implementing these more complicated things and fleshing out this ability even more is going to require
that we learn more about gas, more about what we can do in abilities.
And we're going to need to learn about ability tasks.
And those are going to be things that we're going to learn about in the videos to come.
So for now, this is a great milestone.
Congratulations on making it this far, but we are not done.
We have some work to do and we're going to get this fireball looking really nice and feeling really
nice when playtesting.
So stick around.
We're going to start our next section on ability tasks and start making our gameplay abilities much
more interesting.