Welcome to your next quest.
In this quest, you're going to make your resistance attributes.
So this is all familiar stuff, but it's good practice for you to remember all the steps.
So create your attributes for your resistances and complete all the boilerplate code.
So no need for me to spell it all out for you.
You know the steps at this point.
Now I'd like you to add your attributes to the attribute menu as well.
This involves another set of steps that you'll have to go through.
And in addition to this, I'd like your resistances to behave as secondary attributes.
In other words, they're going to be based on other attributes, and you're going to choose which attributes
and what those mathematical relationships will be.
And then you'll add the modifiers to your secondary attributes.
Now, be as simple or complex as you wish with these, if you want to make some MKs for them and take
other things like level into account, feel free.
But just simple modifiers will do as well.
So pause the video and conquer this quest now.
Okay.
So this quest is a little bit of a tall order, isn't it?
Because we have to do quite a number of things.
So let's see if we can cover all the bases here.
The first thing we need are the resistance attributes.
That's going to be in our attribute set.
So I'm going to go into my public folder into ability system and aura attribute set.
And these are going to be just like the rest of our secondary attributes.
In fact, we can put them just under secondary attributes if we like.
We can use our own multi-line comment that says what they are resistance attributes and we can just
place the four new attributes here.
So I'm going to copy the three boilerplate lines for Max Mana and paste them right here four times and
I'm going to change the first one.
And this is going to be fire resistance.
Now that means the on ramp needs to be changed to on rep fire resistance.
I'm going to change the category to resistance attributes and the attribute accessors needs fire resistance
instead of max Mana.
Now I'm going to go ahead and copy resistance and paste it into the category for all three of the rest
of these.
And I'll go ahead and place an empty line here as soon as I finished one of the attributes.
So next we're going to do our next attribute instead of Max Mana.
It's going to be lightning resistance.
And I need to copy this for the on ramp.
So that's on Rep Lightning resistance Attribute Accessors gets lightning resistance and we're done.
And if you like, you can use that little trick that writer has by using control H You can search here,
I can search for Max Mana and replace Max Mana for the next one, which is going to be arcane resistance.
And I see that it will replace it in the three spaces here.
I'm going to go ahead and replace all and then I can do the same thing here and replace this with physical.
So physical.
Resistance and I can replace all their.
Now we need our rep notifies.
So we'll scroll down to our rep, notifies down here at the bottom, and we'll make four copies of Max
Mana and we'll just change these one by one.
This first one will be fire resistance.
The input will be old fire resistance.
The next one will be lightning resistance.
Changing the input to old lightning resistance.
Next, we're going to have arcane resistance.
Changing the input there.
And finally, physical resistance.
And we'll change the input there.
And it looks like this last on Rep Max Mana needs to be there because I went ahead and changed the original.
This is one of the copies.
That's fine.
We'll move it up there and we still have Max Mana.
Now that we have the declarations, we can go ahead and define the functions.
Generate definition.
Looks like it just gave me fire resistance.
I'm going to want all the rest of them, so I'm going to highlight them again.
And there we go.
Generate definitions by declarations.
That's what I wanted.
And we have the rest of them now.
We just need our gameplay attribute rep.
Notify another piece of boilerplate and we need to change this to fire resistance and old fire resistance.
And we'll need to do the same thing for the rest of them.
So really quickly, just doing the same thing.
Okay.
So there are the rep notifies.
Now we need these to be replicated, which means we add them up to our git lifetime replicated props.
I'll go ahead and put these just under secondary attributes and say resistance attributes.
We'll copy one of these lines and change the variable to fire resistance.
And we'll go ahead and do three copies of that and change these.
We have lightning resistance.
We have arcane resistance and we have physical resistance.
Now, that's not quite all that we need to do.
Remember, we added one additional boilerplate step if we wanted these attributes associated with their
corresponding gameplay tags.
Now, these we plan on having in our attribute menu, which means we do want these associated with their
corresponding gameplay tags.
Now we created that association with our tags two attributes map, so we can add that here.
So I'm going to go ahead and add another comment that says resistance attributes and we're going to
add the resistance attributes and associate them with their resistance tags, which means we're going
to have gameplay tags, dot attributes resistance looks like it's showing me in alphabetical order,
so I'll go in alphabetical order and I'll use get arcane resistance attribute.
Now Autocomplete thinks I want to call the function.
I don't.
I'm going to remove those parentheses.
And now I've associated the arcane resistance tag to the arcane resistance attribute.
Careful not to map the damage type tag.
We want the resistance tag.
There's a difference.
Now, in addition to arcane, I'm going to let Autocomplete show me the next one That's fire and I'm
going to change this to get fire resistance attribute.
I'm going to go ahead and paste again after fire.
Is lightning changing this to get lightning resistance attribute copying and pasting one last time.
We have physical.
So we have get physical resistance attribute and now our tags are mapped to our attributes.
That's an important step.
Okay, so now that our attribute set has the attributes and we've performed all the boilerplate code,
the next step is to handle things on the blueprint side.
And I'd like to make sure to set up the mathematical relationships between the resistances and their
backing attributes.
So what I'm going to do is go ahead and compile and launch the editor.
Okay.
So back in the editor, I'm going to go into blueprints, ability system and gameplay effects and go
into default attributes.
Now we know that Aura is using the secondary attributes and secondary attributes.
We have a modifier that's attribute based for most of our secondary attributes.
They're based on other attributes.
Now to me, resilience is probably one of the more important attributes that should back these resistances.
But if we like, we can make our resistances dependent on multiple attributes.
If we want to do that, what I'm going to do is I'm going to collapse all the modifier indices.
We have ten of them total.
And I'm going to add modifiers for our resistances.
Now, if you really wanted to, you could create a new gameplay effect called G resistance attributes
and you could apply it separately to make things simpler.
I'm just going to keep one secondary attributes gameplay effect and treat our resistances as secondary
attributes.
So I'm going to add a new modifier.
This will be index ten and I'm going to choose the attribute.
It's going to be fire resistance.
I'm going to use override.
Just like with our others, modifier magnitude is going to be attribute based and we're going to expand
the backing attribute.
And I'm going to choose resilience as the backing attribute.
Now for fire resistance, I would like each point of fire resistance to ignore 1% of fire damage, which
means fire resistance should be relative low.
I'd like to have about perhaps three for my post-multiply additive value and then for every point of
resilience, I'd like to add about maybe 0.5 to my fire resistance.
And the attribute source is going to be target and I'm not going to snapshot.
Now this is Override, and if we want to base this on multiple attributes, we could, for example,
we could add another modifier and instead of override, we can just choose Add as these modifiers are
applied one after the other.
So let's say I'd like my resistances to be based on resilience, but also one of my other attributes,
let's say for the elements, all the damage types except for physical can have their resistances buffed
up based on intelligence as well.
So I can add another modifier.
For index 11, we can choose fire resistance, for example.
Choose Add instead of override.
And for the modifier magnitude, we can make it attribute based and it can be based on the backing attribute
of intelligence.
And we need to determine how much is added to the intelligence.
For example, for every point of intelligence, fire resistance can go up by 0.1, for example.
So that's another possibility.
I'm going to keep this simple, though, and base these all on resilience only.
So I'm going to go ahead and delete that modifier and consider fire resistance done.
So I'm going to add another modifier and take care of my next resistance.
That's going to be lightning resistance.
It's going to be override.
We're going to choose a modifier magnitude attribute based, expanding our backing attribute.
It's going to be also resilience taken from the target.
And I'd like the same coefficients for all of these attributes.
A three for post-multiply and a coefficient of 0.5, so three and 0.5.
And it's kind of nice to just put them all at the same settings in the beginning.
And then as we play test the game, we can come back and tweak these.
So it doesn't make a whole lot of sense to try to put in values that you think are perfect right at
this point, because we don't know if they're perfect yet.
We haven't tested them.
Okay.
So in addition to lightning resistance, we need another one.
And this one is going to be arcane resistance.
It's going to be override.
We're going to make it attribute based.
The backing attribute is going to be also resilience taken from the target with a post-multiply of three
and a coefficient of 0.5.
And finally, one last.
Resistance attribute.
It's going to be physical resistance.
We'll make it override.
Attribute based.
Backing.
Attribute Resilience.
Captured from target Post-multiply of three Coefficient of 0.5.
So now that we have this taken care of and because we placed it in secondary attributes, we don't need
to go and make another attribute setting gameplay effect.
We don't need to take care of applying that effect.
It's all taken care of for us.
Now all we need to do is implement this in the attribute menu.
Now, just by the way we're implementing these resistances for aura.
We haven't bothered adding these to the enemies gameplay effect for setting the enemy attributes.
If you want, you can add them to the enemies gameplay effect as well.
For now, I'm not going to implement resistances for enemies, but it's just as simple as adding those
to the gameplay effect for the enemy.
Secondary attributes.
I leave that as optional for you.
And I very well may add that later on in the course, but for now it's not important.
I'm moving on to the UI because we need to go to the attribute menu and our attribute menu now needs
attribute rows for our resistances.
Now I'm going to add it to the secondary attributes.
I'm just going to consider it to be one of the secondary attributes.
So we just need four more rows here in our scroll box.
Now we have row armor through row.
Max.
Mara.
I'm going to stick the resistances down at the bottom just to keep things simple.
I'm going to select Row Max Mana.
I'm going to hit control C control V, and we now have another row and I'm going to call this row.
Fire resistance.
I'm going to hit control C, control V and call this one row.
Lightning Resistance.
Control V.
Call this one row.
Arcane.
Resistance Control V.
Rename this one Physical resistance.
So we now have four new rows.
These must have their gameplay tags set, which means we should go into the graph.
Now we have our set attribute tags where we're setting the primaries.
The secondaries will have another sequence here for our resistances.
Even though our resistances are technically secondary attributes, we're just going to separate them
here.
We're going to have another sequence.
And this one will handle our resistance attributes.
I'm going to move these out of the way for now.
And for our resistance attributes, we're going to get our ro fire resistance.
Our row, lightning resistance, our row, arcane resistance and our row physical resistance.
And we're going to set their gameplay tags.
So we're going to say set, attribute tag, going to duplicate it three more times.
And for row fire resistance, I'm going to set it two attributes Resistance.
Fire for row Lightning resistance.
We're going to set it to resistance lightning and hook that up.
And you already know what we'll do for these arcane resistance gets arcane.
Physical resistance gets physical.
We hook these up to the sequence and we're done.
Now, this function looks a little bit unwieldy, right?
It's a little bit out of hand.
And we could just refactor each of these into their own functions.
For example, I could highlight these right click collapse the function and call this set primary attribute
tags.
I can highlight these collapse the function.
Call this set secondary attribute tags and I can highlight these.
Collapse the function.
Set resistance Attribute tags.
Like so.
Okay, So it seems like we're almost done, if not completely done.
Right.
And if you got to this point and you went and tried to playtest and you opened your attribute menu and
scroll down and you said, why did these just say attribute, you're forgetting one important step.
And that's that our attribute menu receives a struct of type or attribute info, and this is data driven
by a data asset, isn't it?
We have to fill in that data asset.
We have to go into blueprints, ability system data and we have to go into attribute info.
Remember, each attribute has the gameplay tag for the attribute, the attribute tag associated with
it.
It has the attribute name and the attribute description.
We're not using that description just yet, but we have the attribute name and that's what we use to
display in our attribute menu what the attribute is.
We're going to need more of these.
We're going to add four more.
So I'm going to click plus that's going to be index 14.
For me, the attribute tag is going to be attributes resistance.
We'll start with our Cain.
The attribute name will be arcane.
And for the description, we'll just say resistance to arcane damage.
Now I can click plus.
For index 15.
I'm going to choose resistance fire.
The attribute name is going to be and actually this should be fire resistance.
And the attribute name for the last one should actually be arcane resistance.
That's what we want to see in our menu.
Now, attribute description will be resistance to fire damage and we can add another one.
I'm going to collapse these as I go.
So adding another one we have, let's see, what did we have?
We had fire and arcane.
We need lightning.
The name will be Lightning Resistance.
The description resistance to lightning damage.
And one more for physical.
We're going to choose the physical tag.
Physical resistance and description resistance to physical damage.
Now that we have this in our attribute info, if we go and press play, go to the attributes and scroll
down.
Look at that.
We have fire resistance through physical resistance and we're seeing the actual number.
Now we're not using that number yet.
We still have to do that, but now we have the attributes.
So that's great.
Now because these are all using basically the same modifier coefficients and parameters all based on
resilience.
Well, they all change when resilience changes and all by the same amount.
And as resilience gets really, really high, these resistances get really high as well.
So that gives us an incentive to increase our resilience, which also increases a lot of our other attributes.
So resilience might be verging on the edge of overpowered, but that's okay.
This is all stuff that we can change the framework and the system is in place and that's what's important.
So now that we have resistance attributes, it was fairly easy to incorporate it into all of the systems
in our game.
Just those boilerplate steps in the attribute set are what's keeping this all tied together, right?
And we didn't have to touch one line of code in our attribute menu widget controller because it's just
coded so well.
So if you want an example of good code, use the attribute menu widget controller as a prime example
of that.
So you can always go back to that class if you need an example of robust code.
So anyway, we have our resistances.
We're not taking them into account when it comes to causing damage.
So that's going to be our next step.
And I'll see you in the next video.
Great job on the challenge.
I'll see you soon.