Welcome back everyone.
Now we've just went about saving all of our abilities.
It's now time to load them up.
Now in our character in Possessed By, we're calling load progress and in load Progress.
We're checking if it's our first time loading in.
If not, we load up our player state variables and our attributes.
But it's time to load in our abilities to now.
Giving abilities is a responsibility that I'd like to leave up to the ability system component.
So I like the ability system component to be able to load in abilities from disk by taking in a save
data object.
So I'm going to go to ability system component where we have add character abilities and add character
passive abilities.
I'd now like a function to add character abilities from disk.
So I'm going to call this void Add character abilities from Save Data.
And all I'm going to do is pass in a you load screen save game.
We're going to forward declare that and call this save data.
So let's go ahead and generate this definition.
And all we have to do here is take the save data and loop over it saved abilities array.
So we're going to say for it'll be a const f save data reference called data.
And we'll loop over save data saved abilities.
Now this is an F save data.
It's actually F saved ability right?
This is the struct we added to load screen save game to save all of our data pertaining to our abilities.
So we're looping through those saved ability structs.
And the first thing we should do is find out what that class is for the ability.
So let's make a const t sub class of you gameplay ability.
And we'll call this startup ability class.
And that's going to be our data gameplay ability.
So we have that.
And we need to make an F gameplay ability spec for it.
So we're going to say F gameplay ability spec called startup ability spec.
Now, it's not really a startup ability, is it?
It's actually a loaded ability.
So let's call this loaded ability class and loaded ability spec.
And we're just going to create a new F gameplay ability spec.
Using our loaded ability class, and we need the level we're going to take data ability level.
So we have a spec now.
Now here's the thing.
If it's passive we want to activate it.
If it's not passive we just want to give the ability.
So we're going to say if data dot ability type.
And we'll check this ability type we need to use F or a gameplay tags get.
Dot abilities type.
And we'll first check offensive and we'll have an else case for the rest of them, although they might
not all be passive.
So we'll check data dot ability type.
And we'll see if it's passive.
So equals abilities type passive.
Now we can't just give the ability.
We also need to set its ability status and its ability slot.
So we're going to take our loaded ability spec dot dynamic ability tags and add a tag.
And we're going to add data dot ability slot.
But we're also going to add another tag data dot ability status.
And we can give the ability passing in loaded ability spec.
Now we actually want to give this abilities dynamic ability tags, the ability slot and the ability
status regardless of whether it's offensive or passive.
So let's do that outside of the if statement and just give the ability if it's offensive.
But if it's passive we want to activate it.
We're going to say give ability and activate once passing in loaded ability spec.
And now here on our ability system component, we can set be startup abilities given to true.
And we can also broadcast abilities given delegate.
As our abilities have now been given.
So with that, our ability system component now has a function that can give abilities and activate
passive abilities.
So from our character, we can now fulfill this.
To do we need to get a U or a ability system component or ask.
We're going to cast to you.
Ora ability system component.
Our ability system component.
We'll wrap it in an if.
And take or ask and call our new function.
Add character abilities from save data.
What is fueling pass in Save Dayton.
And with that, we're now loading in our abilities.
Now we just need to make sure that all of our abilities either have offensive or passive.
Even our passive abilities that aren't spells.
So let's go ahead and run in debug mode.
Okay.
So what I'm going to do is I'm going to take my load menu and I'm going to remove this slot.
I'm just going to delete it.
We're going to start fresh.
But before we do that I just want to double check a couple things.
For one I'm going to go to blueprints ability system aura abilities.
And we have our passive start up abilities GA listen for event.
And we have our GE event based effect.
That's not an ability but listen for event is.
And we need to make sure that this has a passive ability type.
We can make sure of that in blueprints ability system data and go to ability info and make sure that
it's in here with an ability type.
So let's go through these.
We have Firebolt electrocute, Halo of protection, life siphon, mana siphon, Arcane Shards, and
Fire blast.
So our listen for event is not here.
We can add that now most of these don't matter because it's not going into our spell menu.
It's not going into our overlay.
We're not going to see it visually, and we'll never actually even try to push it into those widgets,
because we're not going to set a slot for it, an input tag, but it can get an ability tag.
Now, we don't have an ability for this.
If we go to passive, it's not here.
So listen for event needs an ability tag, let's go to Project Settings and add a gameplay tag.
We'll get abilities passive.
We'll add one called listen for event.
We'll add this tag to the ability Tags abilities passive listen for event.
Now that this gameplay ability has the tag here in Ability info, we'll give it its ability tag listen
for event and we'll set the gameplay ability itself.
Gar listen for event and we don't need a level requirement.
We can leave it at one.
We don't need a background material or an icon, but we want this to have an ability type of passive.
And with that, we should grant that ability.
Let's make sure.
So that's the first thing I wanted to check.
Another thing I want to do is I want to go into blueprints.
Character.
Aura.
BP, aura and go to my start up abilities.
Because I only want to start up with Firebolt.
I want to remove the rest of these.
So I'm going to delete the others and just start with Firebolt.
As far as my other abilities, the only other one is my start up passive ability.
Gar listen for event.
So if we load in and then quit, we should load back up Firebolt and listen for event.
Let's make sure we can do that.
So we're going to press play.
I'm going to create a new slot, give it a name, select it and play.
Now we have Firebolt.
We have no spell points, but there's Firebolt in our spell menu.
We have no attribute points and we have our default attribute values.
Okay, now we can try leveling up.
So I just want to quit and load back up and make sure that we see these eligible spells.
So that won't happen if we don't save.
So I have to hit the checkpoint and load out and come back in.
We see that I'm level four.
And I see that we have some print strings here.
Our passive spells have been activated, so we should actually check the status before we activate our
passive abilities because we don't know which ones are equipped.
But if we open our spell menu, we see them here.
So that's good.
But because I saw each of these become active, that tells me that I should only activate them if they're
actually in this.
So we need to know of their status things of.
But now why can't I ahead and can't I do list what happens that all we save with a different status
a large.
So I'm going to spend a tornado of way to electrocute in.
But I'm going to spend a check in with on arcane.
Equip it so to electrocute it to now unlocked arcane shards is now equipped.
And let's go ahead and just spend a point on Mana Siphon and equip that to.
And with that, I'm going to try saving the game and loading back in.
So we'll hit our second checkpoint.
Load out.
Come back in.
And I see that my abilities, my passive abilities appear to have been activated twice.
My electrocute is unlocked, my arcane shards appears to be equipped, and I can indeed use it.
So that works.
The only thing is my passive abilities.
I didn't see my blue particle effect for this passive ability, so that's something.
That I need to look into.
I'm also seeing that my status doesn't appear to be updated.
Even though we have our abilities showing, only my equipped ability enables my equip button, so the
status is something we need to make sure we're loading in.
Now I see that we are giving our ability status, but for our passive abilities, we need to check that
status and only activate if the status is equipped.
But if that's the case, if we're going to do that, then we need to set the status for our nonspell
passive abilities too.
In other words, if we go to add character abilities, actually add character passive abilities is where
we do it.
Then if we give the ability and activate once for a passive ability, we're going to need to set its
status.
So we're going to have to take that ability spec add to its dynamic ability tags.
So add tag for a gameplay tags.
Get dot abilities status.
And because we're activating it, I'm going to give it the status of equipped.
And that way, the first time we give this passive ability, it's going to be equipped.
It's activated.
So we'll consider that equipped.
And when we give character abilities from save data, if it's passive, we're only going to activate
it if that saved status was equipped.
So we're going to check its status.
We're going to say if data dot ability status and we can use matches tag exact.
We don't have to use double equals but matches tag exact F or a.
Gameplay tags get abilities status equipped.
If it's equipped then we'll give an activate and this should say matches tag exact not matches any.
So we'll give an activate if when we saved it it was equipped.
Otherwise we'll just give the ability.
Like this.
So if it's offensive, we just give the ability.
If it's passive, then we check if it was equipped, when we saved it.
If it was, we'll give an activate once.
Otherwise we'll just give ability okay.
So add character abilities from save data will only activate passive abilities if they were equipped
when we saved them.
And if we activate them, we need to make sure that we see the particle systems.
So if we go to ability system passive passive Niagara component, when are we activating?
Well when we get the passive spell tag.
So we should get those tags if we activate.
Let's go ahead and close the editor.
And we'll now see if we're only activating those abilities that were active when we saved them.
We'll go ahead and run and debug mode.
All right we're back up and running.
Let's get Galison for event.
And when we activate it, let's print a string to let us know.
Were, we're going to say my in for an event active in go on her.
And we'll make it a cool color.
Okay, let's press play.
Let's actually go to.
Maps, load menu and press play and I'm going to delete this.
We're going to start a new.
Okay.
So listen for event is activated the first time.
As expected we only have Firebolt.
So let's level up.
And we can save the game and we can leave now.
We can come back in.
So we're not getting listened for event.
So I'm going to come back in here and make sure that we add dynamic ability tags before activating once.
I'm going to rerun now.
Okay.
So ability system aura abilities I'm going to go into passive startup open listen for event.
Make sure I have that listen for event activated.
And let's go into Maps Load menu I'm going to clear this out.
And make a new one.
Listen for event is activated, nothing else was activated.
And if I save without doing anything, just save the game and close and come back.
We see that we're level one.
Listen for event was activated as expected.
Now if I level up.
I'm now level four.
And we have some abilities.
I'm going to spend a point on a passive ability and equip it.
I'll spend a point on electrocute, but not equip it.
I'll spend a point on arcane shards and equip that to the right mouse button.
So we have some changes.
Let's go and save the game again.
Second checkpoint here.
We can close.
We can play.
Where?
Level four.
We'll load and we're at the right spot.
And now it looks like I got my listen for event activated twice.
So now I'm expecting to see strength go up to 12 when I click this once.
Sure enough that's true.
So that's a problem I can activate with my right mouse button.
This ability I can select these.
Their statuses appear to be correct.
This Manage Rain ability is correct here, but I don't seem to recall seeing any message showing that
it's been activated.
So I don't think it was activated, which means I don't think we gave it an equipped status when equipping
this passive ability.
So a couple things here.
So the first problem that we're activating our passive ability listen for events is because we're adding
it every single time we save we need to add unique.
So if saved ability being added to our save data saved abilities this whole thing needs to be prevented.
If this saved ability is already in that array.
So we can try add unique.
But there's a problem.
You see, add unique isn't going to work unless f saved ability overloads the equals operator, the
double equals.
And because we created this f saved ability, that operator doesn't exist for this type and add unique
needs to be able to compare to see if any of the elements in the array are the saved ability we're trying
to pass in.
So if we go ahead and try to compile this, then we get an error and it's complaining.
Specifically, there is no binary equals double equals operator found which takes a left hand operand
of type F saved ability or there is no acceptable conversion.
So add unique needs to be able to compare to saved abilities to know if they're equal or not.
Now that's because really, there's no way to know unless we decide how that operator should behave.
Now, I think two saved abilities should be equal if their ability tags are equal.
And we can define this double equals operator for the f saved ability by overloading that operator for
it.
We can do that here in load screen save game.
Now I'm going to do it outside of the struct.
But if we do this here we have to make this an inline.
And to overload the operator we say the return type which we're going to have bool be the return type.
We say operator with the operator we want to overload.
That's the double equals followed by any operands.
Now operands are what goes on the left side and what goes on the right hand side.
So we're going to say const f saved ability reference.
This will be what goes on the left.
And we'll have const f saved ability reference right.
So we have what goes on the left and what goes on the right.
And we're going to return left dot ability tag dot matches tag exact.
Write that ability tag.
That's how are gay this operator.
No one's defined.
Okay, now that this is sorted here, that's the character we can do add unique if is fully so and compile
this.
I don't know that.
Should he fix so errors in the monitor.
So that's going to fix that problem.
We should only ever save one match per match tag.
And let's show my successful a porter.
Now that I'm problem that we're into Wom weren't seeing so massive spells get activated.
Now what happens our ability system component when we equip an ability well let's see if we're actually
setting the status.
We're checking the status if it's equipped or unlocked.
And then we continue.
But I don't think we actually set our status to equipped.
We're calling client equip ability.
So we handle activation and deactivation for passive abilities.
And right here we see that ability doesn't yet have a slot.
That means it's going to be active when it wasn't before.
So here we're actually calling try activate ability.
This is where we should set its ability status to equipped.
And that way when we save the ability, it'll have that status when we load it back up.
So whether or not it's passive or offensive, if we equip the ability here for the first time, it doesn't
have any slot, then I'm going to take the ability spec, take its dynamic ability tags, add a tag,
gameplay tags.
Abilities.
Status equipped.
Now, I think we should clear out its status tag that it had before.
If we're going to do this just to be safe.
So before we do this, let's take ability spec dynamic ability tags and remove tag.
And we'll remove its status.
Now we can always get the status with git status from spec passing in ability spec.
And we have to dereference that pointer.
So this way we're sure to remove whatever its status was and set its status to equipped as we're actually
activating it right now.
Now back to our A character.
Before we actually start adding to our save data save abilities, it's possible that we might have removed
some abilities, or if we've changed the abilities, we won't add them if they already exist in here.
So we want to make sure to clear out this array first before we go and call all these lambdas.
So I'm going to take save data saved abilities and call empty on it.
That way we'll empty it completely.
And then we'll go through and fill it in as we're saving okay.
So the last thing we're going to make sure we take into account is we're going to go into passive Niagara
component, as here is where we're activating and deactivating those passive Niagara components for
our passive abilities.
Now we're binding on passive activate to activate passive effect on the ability system component.
But if these delegates are broadcast first then when our passive Niagara component is constructed,
it will have missed the delegate broadcast.
So what we need to do is as soon as we have our ability system component here, we have to check the
ability status of this passive spell tag for this component.
So after binding to activate passive effect we can check we can make a const bool called be startup
abilities activated and check the or ask for be startup abilities given.
We can call it the same thing, be startup abilities given, and if startup abilities have already been
given.
So if be startup ability is given, then we can check the status of the ability with our passive spell
tag.
If it's equipped, we need to activate this component.
So we're going to say if.
Or as get status from ability tag using our passive spell tag.
If that is equal to and we need to compare this to F or a, gameplay tags get dot abilities status equipped.
If it is equipped, we can just call activate and be done with it.
And we can take these lines of code here.
And we can do the same thing in our lambda that we bound to get on as a registered delegate, just in
case we missed it up here.
We'll have it down here.
So checking start up abilities given and checking the status.
If the status is equipped, we can go ahead and activate.
And of course this is repeat code.
So we could easily make this a function activate if equipped for example.
So we can make a void activate if equipped.
And I'm going to move this.
I don't want it in line.
I want it in the cpp file.
I'm going to put it right here.
Activate if equipped.
And what we're going to do is we're going to check the status and activate.
Now we need or ask.
We can just pass that in.
You or uh ability system component will forward declare here or ASC.
We'll add on a lot around frame input.
And now the function can take and we can call this option run here taking in or ask.
Right.
And when you got all the same function what from right here.
Activate if equipped.
Okay, so with that we can compile and test this out.
Okay.
So I'm going to go back to the load menu.
And I'm going to delete both slots and make a new slot.
I'll select it and play.
We're starting fresh.
I'm going to go ahead and level up.
Make sure that we get one and only one point per attribute point spent.
And we do.
I'm going to leave it at one attribute points 11 strength 18 intelligence.
For spells I'm going to equip.
Let's equip a couple of passives.
I'll spend a point and equip Halo of Protection and Life siphon, and I'll go ahead and spend a point
on electrocute.
Okay, I'm going to save and exit and come back.
And there we go.
Our passive abilities have been activated.
We get the particle systems.
I have one point left.
11 strength, 18 intelligence.
My spells are in the same state.
I have electrocute unlocked and these two passives are assigned.
Everything has loaded properly.
Excellent.
And just to make sure that listen for events is only activated once, I'm expecting to increase one
of these attributes only by one when I spend a point.
Let's try vigor.
It's at nine.
Now it's at ten.
Perfect.
Everything is working as expected.
Now those changes I just made are not going to take place unless I save again.
So I have to reach that other checkpoint.
Now, the last thing I'd like to polish is if we load into this level, say we want to play test it
without actually loading anything.
Well, if we press play and run up to one of these, well, we get an exception because we have saved
World State, which is calling save actors on a save object.
But we don't have a save object.
So what we could do here is just place an is valid check.
Here we can say if not is valid save object.
Return.
So with that, at least we should be able to load in straight into the level and play test it.
We don't have to actually save the world state as we don't have a valid save object in that case.
So with that we can just load right in, come over here and overlap.
And even though it's not functional, other than showing the glow, at least we don't get a crash when
we're trying to play test.
So that's one issue.
And with that that's polished up.
And one last thing that, at least in my case, has happened.
And this is more a side effect of writer's autocomplete.
If I go into aura ability types right here, aura ability types dot h.
Notice that there's this mysterious include of std bool dot h.
That's not something that I wanted.
That was an autocomplete.
And in fact, if I bring it back real quick, notice that this is actually searching for a folder on
my machine.
So if you had pulled this project from GitHub, you wouldn't have been able to build without removing
that.
So something to be aware of with autocomplete features in writer.
So other than that we've fixed those issues.
We now have the ability to save world state and load up our abilities.
Things are looking great.
Excellent job and I'll see you in the next video.