Welcome back.
So we've taken a look at the gameplay effect context struct.
We've seen that it exists here in gameplay effect types and we've seen the benefits and the limitations
of it.
And I'd like to create a custom gameplay effect context struct derived from this one.
And that way we can add additional fields to this struct that we may wish to set on the effect context
and pass through and perhaps change and manipulate based on situations.
I'd like to have specifically a couple of booleans in here for whether or not we've gotten a block or
a critical hit.
So since I'm going to be creating my own gameplay effect context struct, I'd like to create it in a
new header file and because I may be creating more of my own types for the ability system, I'm going
to store them in a header file here in the public section and I'm going to create that header file here.
I'm going to right click on my public folder, go to add and select file.
And this is going to be for my ability system custom types.
So I'm going to call this aura ability types.
It could be ability system types, but I'm going to keep the name a little bit shorter and call it aura.
Ability types Dot H.
I'm going to click okay.
And Ryder asks if I'd like to add this to Jet.
I'm going to click Don't Ask again and cancel because I prefer to add these things by myself through
the git bash.
So I'm going to hit cancel and now I have aura ability types, dot h and I'm going to be creating definitions
for functions on my types and I'd like those to be in their CPP file.
So I'm going to right click on the private folder, go to add and select file and this will be Aura
ability types dot CPP.
I'm going to click okay here and the first thing I'm going to do in Aura ability types, CPP is include
that header file.
So I'm going to include aura ability types dot h here.
Now here in aura ability types, I'm going to declare a new struct and this will be derived from the
gameplay effect context struct.
So I'm going to say struct and I'm going to call this f aura gameplay effect context and it's going
to be publicly derived from F gameplay effect context.
That of course means I need to include the header file for gameplay effect context and writer just went
ahead and did it for me.
It included gameplay effect types.
Dot h.
That's where gameplay effect context is defined.
Now writers telling me that the public for a struct is redundant, right?
This is the behavior we get with a struct.
Anyway, I'm going to leave it there.
I'm also going to make this a use struct with blueprint type and give it a generated body.
And I'm going to have multiple access levels.
So I'm going to stick a public right here, even though I know that structs have a public body by default.
I'm going to have a public section labeled there and a protected section.
And again, the public here is redundant.
Even if I add variables and functions here, they would be public anyway.
So this is just because I want this to say public.
Okay, so we've created an aura gameplay effect context struct.
Now we can't just use this struct just because we've created one.
There are a number of steps to go through before we can actually use this and we're actually going to
need to set the gameplay effect context used by our project to this particular struct and we'll get
to that later.
But for now I'd just like to add a couple of things to the struct and before we even add our new booleans,
the whole reason why we wanted these, there are a couple of things that we need before we can get started
on that and we can learn what those things are by looking at the gameplay effect, context, struct
and gameplay effect types.
So here in gameplay effect types, there are just a couple of things that our gameplay effect context
needs to have.
And if we scroll down towards the bottom of this struct we'll come across a function called get script
struct.
Now what is a script struct?
Well, if you're familiar with the static class function on most you objects, you'll know that it returns
a new class.
Now, if you don't know what a class is, it's generated for each class in the engine that's derived
from a new object for the reflection system.
So if you have a new actor class, for example, a new class is generated for that for the reflection
system structs also have a version of this.
It's called a script struct.
So when you create a struct that's capable of being exposed to the reflection system, a script struct
is created for the reflection system.
Think of it as a reflection of that struct, much like a class is a reflection of the object.
Now static struct is a function just like static class that returns that and our gameplay effect context
has a virtual function.
Get script struct which just returns that static struct.
As you can see it just calls static struct and returns that.
And notice the comment says subclasses must override this so we can override it.
I'm going to go ahead and copy it.
This is in the public section here, so we're just going to override it and stick it in our public section
and aura ability types dot h.
And it looks like I actually defined my class in the CPP file.
You might have noticed that I actually meant for this to be in the header file, but that's okay.
I can just cut it and I can stick it right here in the header file.
No big deal.
And in the public section we're going to override get script struct.
So I'm going to copy these lines here and just paste them here in the public section.
Okay.
So that's one thing that we need.
Let's go back and take a look at what else we have.
We're going to scroll down and there's a very important function at the end of the public section called
Net Serialize.
And the comment says custom serialization subclasses must override this.
Now, net Serialize determines how this struct is serialized.
Now serialization is necessary if you're going to save one of these structs, for example, or send
it across the network.
These are things that require serialization.
In other words, take a struct, convert it into bits, zeros and ones and send those bits in a stream
across the internet.
If you want to be able to replicate something, it needs this net serialize.
Interesting, right?
So we're going to learn all about this in the next few videos, but for now we're just going to override
it as we have to.
So we're going to go to aura ability types and override net serialize.
I'll go ahead and.
Generate a definition for it.
I'm going to empty it out.
So we're going to need to return something from this.
For now, I'm just going to return.
True until we fill this out.
But we do need to fill this out.
And what are we going to fill it out with?
Well, we need to specify how our struct is going to be serialized, which means we have to learn about
how that works.
Now we can learn about how that works by seeing the definition for net serialize for the gameplay effect
context.
So I can go to gameplay effect types dot CP and search for gameplay effect context net serialized function
here.
And if you take a look at net serialize for the first time it's going to look quite cryptic.
There are some things in here that look a lot like magic.
So for that reason we're going to need to have a discussion about this.
Notice that net Serialize takes three inputs.
One is an archive passed in by reference and it's not a const reference, so that should tip you off
about this input parameter.
It should tell you, well, maybe this function is designed to fill it in somehow to change this f archive
mystical object here.
There's also a u package map called map passed in and a boolean called B out Success.
Now let's take a look at what's happening here.
Notice that we're performing some if checks and all of these if checks, every single one of them has
to do with one of the variables stored on this gameplay effect.
Context struct notice we have the actors, we have the hit results has world origin.
Right?
So it's checking something about these, right?
It's looking at if instigator is valid, if effect causer is valid.
So it's checking things and then it's doing something that looks a little bit strange.
And all of this is in an if r dot is saving.
So this F archive has a dot is saving, right?
This is saving function.
Then we call a function called serialized bits on it and then have another series of if statements checking
another sort of cryptic expression here before doing something with the R, this archive object.
And it looks like each of these has to do with the variables here in the struct again.
So at a high level, in a nutshell, net serialize is just serializing each of the member variables
in this struct, saving it into an archive if the struct is being saved.
But if the struct is not being saved, if it's being loaded, well then we're getting that data out
of the archive.
Kind of confusing.
Right?
So we're going to talk about this in the next video.
For now, it's enough to know at a high level what this net serialized does and that we need to override
it.
But how are we going to override it when we don't know what's going on here?
And especially if we're going to have even more variables here that don't exist in gameplay effect context.
So in the next video, we'll learn about how Net Serialize works.
But before we wrap up, let's go ahead and add those variables that we'd like on our custom gameplay
effect context.
So I'm going to add those.
They're going to be protected and they're just going to be balls.
There's going to be one bool called B is critical hit and it'll be set to false by default and we're
going to give it a new property and I'm going to have another one.
B is block or is blocked hit.
I'd like that one to be first, actually.
So B is blocked.
Hit equals false.
We have both of these and they're protected.
Now, I'd like to create functions to retrieve these that are public so that we can get them from outside
the class and functions to set them basically getters and setters.
So up here in the public section I'm going to make a bool is critical hit const function that returns
B is critical hit.
And I'll make a bool is blocked hit.
Also const that returns B is blocked.
Hit.
And then I'll make a void.
Function called set is critical hit, which takes a bool called B in is critical hit.
And sets B is critical.
Hit equal to b n is critical hit simple.
And we'll have another one for is blocked hit so void and this will be set is blocked hit.
It'll take a bull called B in is blocked hit.
And it's going to set B is blocked, hit equal to B in is blocked, hit.
Cool.
So we have our new variables justifying going through all this trouble to make our own effect context.
But the only problem is we don't have net serialize filled out.
This function needs to be filled out.
And one last very important detail before we give this a test compile is we have a generated body here.
That means we need a generated h file for this header file.
And in fact, another safeguard is to use pragma once at the top so this header can't be included more
than once anywhere.
So we got pragma once and we're also going to include all the ability types.
Dot generated Dot h.
Now I'm going to compile this.
And with that, we have a successful compile.
Everything's looking good so far.
The next step is to fill out.
Net serialize and that involves learning how the gameplay effect context.
Net serialize class works and that's in gameplay effect type scope.
So in the next video we're going to discuss this and demystify it so that we can put this type of thing
to use in our gameplay effect context.
And we'll do that next.
I'll see you soon.