Welcome.
In this video, we're going to add a player level to our player state class, and then we'll create
a combat interface and implement that in our project.
So first, let's go to our public folder into player and open up Aura Player State.
And in Aura Player State, we can have a variable for the level.
And I'd like this to be a private variable.
This will be private here in the player state and it's going to be an int 32.
So level is just going to be an integer and it'll have a default value of one and I'm going to give
it a new property with visible anywhere just in case we want to see it in our blueprint Now level is
going to be replicated.
I'd like it to have its own rep notify as well, so that later on when we're going to be showing this
in the HUD, we're going to want to make a broadcast whenever this replicates.
Now to replicate anything, we need to override git lifetime replicated props, don't we?
So we're going to do that here in the public section.
We're going to say Virtualvoid git lifetime replicated props.
We'll go ahead and create the definition for it and allow the super call and then we can add a rep notify
right here in the private section for level.
So this will be void on rep underscore level and we're going to have an INT 32 as the input called old
level.
That way we can have access to that old level and this gets a new function property.
Otherwise it can't be a rep notify.
And so now we can mark level as replicated and we're going to use replicated using equals on rep level.
Okay.
So we can generate the definition for on rep level and we're going to use that soon enough.
But for now let's just mark it as replicated here and get lifetime replicated props.
Now for this we're just going to use do rep lifetime.
This is the most basic macro for marking something as replicated and writer is going to tell us that
we need.
Net slash unreal network H so I'm going to hit Alt enter to go ahead and include that header file.
And now this is defined.
So we need to use our class name or a player state followed by level the name of the replicated variable.
And now with this level is a replicated variable and we're good.
So the player state is where our level will reside.
But I'd like that to be the case only for the player controlled character.
For enemy characters, their level should not reside on a player state because they're not using or
a player state for enemy characters.
I'd like the level to be on the enemy character itself, on Ora Enemy.
So for that case, let's go back to the character folder and open ora enemy and we'll give Ora Enemy
a private section with its own level variable.
So this will be an int 32, we'll call it level, we'll set it to a default value of one and we'll give
it a new property.
And for this I'd like it to be edit anywhere blueprint read only and I'll give it a category of character
class defaults.
Now the reason I'm not going to make this replicated for the enemy is because we're only going to be
concerned with checking the level on the server for AI controlled enemies.
And that's because important things that will require that level in calculations will only be done on
the server.
So that's all we need to do for the enemies level.
Now for the interface we were talking about earlier.
Ora enemy has a level variable and or a player state has a level variable, and I'd like to create an
interface that can retrieve the level and we can implement that on our character class.
And then any character can call that function to retrieve the level.
And it's up to the individual character to determine how to get that, whether we get it from the player
state or just return that value from the character itself in the case of the enemy.
So we're going to go ahead and launch the editor And of course, Blueprint Read only should not be on
private members, right?
Of course, that's something that is going to pop up.
So rather than trying to get around that, I'm going to move it actually up to the protected section.
I think that's totally fine.
So level is now protected instead of private.
Let's go ahead and launch the editor.
Okay, so what we need is an interface.
So I'm going to go into our C plus plus classes ora public, and we have an interaction folder for our
enemy interface.
We're now going to have a combat interface that will be shared between both enemies and the player controlled
character.
Enemy interface is unique to enemies only, so this one will be shared.
We're going to have this class in the same folder interaction and it will be an unreal interface.
Let's click next, and here in interaction we'll create our combat interface.
So we'll go ahead and close the editor and let writer populate our folders with our new interface.
And we should see it here in interaction.
Here it is combat interface.
And I just want to implement one function here in combat interface right here in the public section.
So it's going to be virtual and it's going to return an INT 32 and we're going to call this get level.
I don't want it to be required that we implement this.
If we don't implement it, I want to simply return zero.
So I'm going to generate a definition.
This will be a default definition that returns zero here and then we can implement this in, say, the
base character class who doesn't need to implement it.
But because the base character class has combat interface, then we don't have to implement it individually
in each subclass of the base character.
So let's go to Aura character base in the character folder and let's implement this interface.
So not only I ability system interface, we're also going to inherit from i combat interface.
And writer should give me the opportunity to include the header file.
And there we go.
So now our base character class or a character base is also a combat interface.
And then we can implement get level in both aura character and aura enemy.
We'll first do it in Aura Enemy, and this is going to be public.
And right here I'm going to make a multi-line comment that says combat interface and beneath it.
We'll close it out with end combat interface and we'll implement that function virtual int 32, get
level override.
And for the enemy, we're simply going to return the level variable.
So let's go ahead and generate this definition and return level.
We don't need to call super.
We're going to return the level variable.
And for a character it's going to be different, isn't it?
Because our level will be on the player state.
So let's go to a character and we'll override that function here.
It's in the public section.
So we're going to have a multi-line comment that says combat interface.
And we'll have another multi-line comment beneath it that says end combat interface and we'll override
the function virtual int 32, get level override.
Let's go ahead and generate a function definition and this one will return something else, won't it?
We have to get our player state.
We're doing that right here in init ability actor info so we can copy that line right here.
We can simply copy that.
We can even do the check for a player state here and we can simply get the level from a player state.
Now an aura player, state level is private, so we should make a public getter to retrieve that level
variable.
So right here, we'll do it.
We're going to say int 32, not 43, but 32 get level.
It'll be const and it'll return level.
Now, in this case, we're hiding a function.
There's a function called get level on the actor class.
Now, that tells me it's going to be a problem for all the other classes.
So for that reason, I'd like to change the function name to get player level on all fronts.
So I'm going to change it here.
I'm going to change it in the interface itself.
Let's go to Combat Interface.
Let's just go ahead and change this to get player level and that means I need to change it here in Combat
Interface TCP.
We also have to change it in Ora enemy dot H and CPP.
So let's change it to get player level there.
CPP will change it to get player level there and an Ora character will change it to get player level
here and get player level here and we can call that getter.
And before we do, let's just go back to Ora Player State for a second.
And I was going to say that this is a nice simple little function.
We can mark it with force inline.
Now you'll notice that I'm not using force inline very much in this course, and I've used it quite
a bit in other courses with getters.
This is one of those micro-optimizations that you tend to kind of see overused a lot and it doesn't
make a huge difference at runtime.
It is a small optimization.
It basically means that whenever we call get player level, the preprocessor is going to replace that
function call when preprocessing before the compilation step with the function body, in this case the
level variable itself.
So ultimately the compiler has the say over whether it ends up doing that or not.
For small things like this, it's usually okay, you're not really going to cause any harm by overusing
it, but that's why I don't use it very much.
I'm going to go ahead and use it here though.
And since we have a getter, we can go back to Ora character and we can get that level.
So we can return with lowercase, of course, return or a player state get player level like so.
And this could be a const local variable here.
So now ora character implements get player level or an enemy implements get player level.
It just returns level.
This could really be on one line know as a matter of style.
You could change it if you wanted all in one line like that.
But now that our character and enemy can have get player level called and in the case of the enemy,
they'll return the level variable that's on the enemy class.
In the case of Ora character, it'll return the player level that's on the player state class.
That's all great.
Now we have an interface we can use to easily get the player level if we want to.
In a custom calculation class and the custom calculation class is what we will make next.
So let's go ahead and make sure our code compiles here.
And suddenly my player controller doesn't like to object.
Pointer being used for last actor in this actor.
It was legal before, but now it's telling me to stop using object pointer for the enemy interface.
So that means we're going to need to use raw pointers for the enemy interface.
We'll go ahead and leave that as a raw pointer.
Instead, let's go ahead and compile again.
And there we go.
We have a successful compile.
Great.
So great job.
And I'll see you in the next video.