Welcome back.
Now we have our exec calc damage.
And here we're actually calculating how much damage we should do.
Now, this is just generic damage.
We don't really have any concept of damage types, but if we did, we could respond to each damage type
differently by having some kind of resistance to that damage type, for example.
So damage types are implemented in lots of RPG games.
So we're going to explore a way to implement damage types in this project.
Now I'd like to identify damage types by gameplay tag.
Yes, Unreal Engine does have a built in damage type based on the Ew damage type class.
And it's okay.
It's good for adding static functions to a damage type and checking to see if you're using that damage
type and accessing static functions on it.
They're not supposed to be instantiated or anything, and that's an okay way to implement damage types.
But I like the idea of using gameplay tags to identify damage types as they're more lightweight, don't
require you to cast, and they're very easily passed around throughout the gas system.
So I'd like to use gameplay tags for damage types.
Now I'd like to add a gameplay tag for our first damage type that we'll implement.
And what makes the most sense right now would be fire because we have a firebolt ability.
So our first step for implementing damage types is to define the gameplay tag for the fire damage type
and that's going to be an aura Gameplay tags.
So we can open aura gameplay tags and we do have a gameplay tag called Damage.
I'd like to have a gameplay tag for the fire type, so I'm going to make an gameplay tag called Damage
Underscore Fire.
So this will be the first damage type that we have now I can go into the CPP file and define this gameplay
tag, so I'll put it just under damage and copying and pasting damage.
I'm going to change this to damage underscore fire.
We're going to add a native gameplay tag called Damage Dot Fire and the F string comment will say fire
damage type.
So now damage dot fire is a gameplay tag.
Now how are we going to implement damage types?
Well, we could have the concept of a damage type for our gameplay ability.
We know that our gameplay ability or a gameplay ability, which is our base ability class has a scalable
float for damage.
So if we go to aura gameplay ability, here it is f scalable float.
Now we could have a simple gameplay tag called damage type on our ability if we wanted to just be able
to apply damage of a single type for a gameplay ability.
We could also have our ability be capable of applying multiple damage types.
In that case, it might be nice to have a map from gameplay tag to scalable float for the different
damage types.
Either way, we're going to want to have the damage type information in our ability now at this point
because we're adding more things to our gameplay ability class that may not be used by all gameplay
abilities.
I'd like to subclass or a gameplay ability into a specialized class that's capable of causing damage,
something like aura damage ability, for example.
So for that reason I'd like to start the editor and create a new gameplay ability class based on our
Aura gameplay ability base class, and I'd like that to be a special aura gameplay ability that's capable
of causing damage.
So I'm going to go ahead and just go straight to my C plus plus classes or public ability system abilities
folder and make a new class based on aura gameplay ability.
So I'm going to right click, make a new C plus plus class based on this ability and I'm going to call
this aura damage gameplay ability.
So let's go ahead and create that class.
I'm going to close the editor down and now we should have an aura damage gameplay ability and we'll
put any damage capabilities in that class.
Now Aura projectile spell is just based on aura gameplay ability.
So if we want to reparent it, we have to do that ourselves.
So I'm going to go to the public folder ability system abilities and open aura projectile spell and
expand the include so I can see them and I'm going to change its parent from aura gameplay ability to
aura damage gameplay ability.
For that reason I have to include aura damage gameplay ability instead.
And now our gameplay ability or a projectile spell is based on aura damage gameplay ability.
Now for that reason we have this damage gameplay effect class on aura projectile spell that should be
moved over to aura damage gameplay ability and that should be protected.
So I'm going to use control X to cut that and go over to aura damage gameplay ability, add a protected
section and paste in the damage gameplay effect class.
So only aura gameplay abilities derived from aura damage gameplay ability should need this.
Now.
I'm also going to go to aura gameplay ability and I have this scalable float called damage that's not
needed in the base class.
So I'm going to control X to cut that and head on over to aura damage gameplay ability and paste it
in.
Now the thing is we should have a damage type and if we want to be able to have multiple damage types
and values for the damage, for a damage gameplay ability, we should do something like have a team
map as this can map an gameplay tag.
Two f scalable float and we can call this damage types.
Now we can make this new property with edit defaults only and we can place it in category combat.
Actually, I'd like it to be in category damage.
And with that we don't really need the damage scalable float, but we're using it elsewhere in our code.
So we're going to need to fix that if we remove damage.
Now, where are we using this scalable float?
We're using it in aura projectile spell.
So if we go to aura projectile spell dot CP and find where we're using the damage scalable float, we'll
see that we're calling get value at level here and we're just kind of passing in ten.
We're kind of cheating here so we get damage at level ten for this ability.
But if we get rid of damage, that means we're going to have a team map and we should really get the
value in the team map for each gameplay ability.
And then we should assign tag set by color magnitudes for each damage type.
So that means we're going to need to loop over that team map and do this for each damage type.
So what I can do here is place A for loop.
I'm going to say auto reference pair in damage types.
And here in damage types, we're going to take this const float scale damage.
I'm just going to copy it into here and it's going to be pair dot value, dot get value at level and
I'm going to go ahead and pass in get ability level here.
So we got the scaled damage for each damage type and damage types and then we can assign the tag set
by color magnitude.
So I'm going to copy that line into here.
We pass in the spec handle.
And instead of gameplay tags damage, we're looping through this pair where the key is the gameplay
tag for damage.
So we're going to use pair dot key for the damage type and scale damage will be retrieved from that
pair as well as we're getting it from pair dot value get value at level.
So now with this for loop, we can have multiple damage types and we don't need this scaled damage here
and we don't need this assign tag set by color magnitude so we can remove those.
Now that's not the only place where we're checking for the damage tag, is it?
We need to take a look at exec calc damage and we can search for set by color.
And we can see here that we're getting the set by color magnitude straight up using the damage gameplay
tag.
But now we need to do this for all damage types.
So it'd be nice if we just knew what all the damage types are.
Well, we could keep them all together in some kind of array or collection somewhere.
For example, we can go to aura gameplay tags and we can have a t array of gameplay tags for the damage
types.
So t array f gameplay tag.
And we can call this damage types and we can add the damage types to this array.
We can do that in the CPP file.
So right here under damage fire after this gameplay tag has been created, we can take gameplay tags,
dot damage types.
And call.
Add and add gameplay.
Tags, dot damage fire.
And then we can just make sure that each of the damage types is added to this array.
And then we can always get the t array if we want to know how many damage types there are.
So back to our exec calc.
We can loop over that t array.
We can say for f gameplay tag damage type tag in f or a gameplay tags get.
Dot damage types.
So we're looping through the damage types.
Then we can get the set by color magnitude.
So I'm going to make a const float here called damage type value equals.
And we're going to call spec dot, get set by caller magnitude here, passing in the damage type tag.
So since we're looping through all the different damage types, we can now add all of those damage type
values to damage.
So here I'm just going to set damage to zero as we create it.
So float damage equals zero F.
And then I'm going to add damage.
Type value to damage for each damage type, but only if we find it.
And remember, get set by caller magnitude has a optional float default.
If not found, it's set to zero by default.
So if it's not found, then damage type value will just be zero.
So for that reason it's safe to say damage plus equals damage type value.
So now if we have multiple damage types, we'll add the values set in our set by caller magnitude here.
And we know that our projectile spell loops through all of the damage types and gets their value.
So we're going to have to make sure that we set that damage type F scalable float pair for the fire
damage type.
So that takes care of exec calc damage.
And later, if we decide to add resistance attributes for each damage type, we can check those and
we can lower the damage for that given damage type based on that resistance.
So the last thing to do is to take our aura gameplay ability.
Actually, it's going to be our aura damage gameplay ability and remove damage altogether as we don't
really need it anymore.
And if we're still using it anywhere, a quick compile is going to give us a handy compiler error showing
us, but I don't think we're using it anymore.
So with a successful compile, we can go ahead and launch the editor.
And with that, I'm going to go ahead and open up my firebolt gameplay ability.
So that's an ability system.
Gameplay abilities Fire Firebolt, gar Firebolt and under damage.
We now have damage types instead of a scalable float.
Now I can click plus to add one and now I have a key value pair.
The key is the gameplay tag that's going to be damage fire and the value is going to be my CT damage
curve table Selecting the curve Abilities Dot Firebolt.
So now damage is handled a bit differently.
And the cool thing about this is we could add multiple key value pairs to this map.
Now at this point I only have the fire gameplay tag and I can't add a duplicate key to a map, so I
really don't have any options here.
I can only have one element here, so I'm going to have to delete that one.
But once we add new damage types, we can have multiple and they'll all be applied if we want to do
that.
So now the only thing left is to see if our ability still causes damage.
And it looks like we do.
Now the numbers are lower because we're no longer cheating and passing in a ten for the ability level.
We're just passing in the actual abilities level, which is one.
So we're really only doing a little bit of damage.
As we see that normally we're getting three damage.
When it's a block, we get one damage.
A critical hit is 51.
So that's actually way too high.
And if I go to look at my critical hit damage attribute, I see that it's 45.
Now, that's way out of balance compared to my others.
Critical hit chance is okay, but critical hit damage should not be 45.
So before we wrap up, I'm going to just tweak that and we'll be tweaking these parameters for our attributes
as we go.
I'm going to go into ability system gameplay effects, default attributes, Aura, GE, secondary attributes,
and I'm going to find my critical hit damage attribute.
Here it is.
And I'm going to take a look at my parameters.
I'm going to expand modifier magnitude, attribute based magnitude, and it looks like I have my attribute
based on.
Armor penetration.
So its base value is five.
And for every armor penetration point we get 1.5 added, which must mean armor penetration is too high.
So let's take a look at armor penetration.
Here it is.
We see that it's backed by resilience and it has a post-multiply additive value of 25.
So if we lower this value, we'll lower our critical hit damage value.
That's one option.
So I'm going to go ahead and lower it to about 11 for the post-multiply additive.
And this attribute is backed by resilience and we get 0.15 points added for every resilience point.
And if we want critical hit damage to increase by a smaller amount for every armored penetration point,
what we can do is we can go back down to our critical hit damage and lower our coefficient.
So if we set this to about 0.05, for example, or 0.08, then we should see a smaller value for critical
hit damage.
Taking a look now, I see my critical hit damage is six, which is actually maybe a little bit on the
lower side.
So the coefficient could probably be.
0.25.
Let's see what we get now.
Now we see a critical hit, damage of eight.
And armor penetration is 12 I think critical hit damage of eight when armor penetration is 12 looks
pretty good.
And I'll go ahead and let my armor penetration be just a slight tad bit higher.
I'll go ahead and get that post multiply additive value and increase it to about 16.
And now we should see.
Armor penetration is 17.
Critical hit damage is nine.
Let's go ahead and see how much we get.
That's a block.
Critical hit was 15.
So a block is one.
A blocked critical hit was 12.
A normal hit was three.
So I think a normal hit could be a little bit bigger.
And that's all going to have to do with my scalable float, right?
Because a firebolt has CT damage.
If we open that and look at Firebolt, our scalable float starts off at a value of five at level one.
So I think what I'd like to do is kind of bring this curve up just slightly.
We'll have it start off at a value of ten.
So we'll have it look a little bit more like this.
I think that looks good.
Saving that.
Now, the whole damage just went up.
So a regular hit that was five.
A blocked hit is three regular hit.
Five five blocked.
Critical hit was 15.
Let's see if we can get a critical.
Critical hit.
20.
Okay, so that's looking better.
I'm liking those values.
I think that's looking good.
And our enemies seem to start off with too much health.
So at some point I think I'd like to tweak those settings so the level one enemies don't start off with
so much health and their block chance is a little high.
It looks like they're blocking too much.
But again, that's because they're using the test ability.
So in blueprints, ability system, gameplay effects, default attributes and then secondary attributes
test we have that block chance just hardcoded here.
So looks like it is 50%.
Realistically, I'd like it to be closer to something like 15 so we won't see so many blocks.
And most of the damage will be just regular.
But that was a critical hit.
Looks like our critical hit Chance is a little high.
18.
So that's we'll just keep in mind that that's a bit high and then we can.
Tweak it later as we see fit.
Okay.
Excellent.
So we now have damage types.
The next step is to implement damage resistances to those damage types.
Great job and I'll see you soon.