A More Scalable Approach to Resistances (w/math, spoily)
Moderator: Moderator
-
- Uruivellas
- Posts: 744
- Joined: Thu Nov 18, 2010 6:42 pm
A More Scalable Approach to Resistances (w/math, spoily)
The current resistance system doesn't scale well, since eventually any character can reach almost maximum resistances against each kind of attack. The new 70% fixed cap in beta 15 doesn't solve the problem either since it just limits the player's choices on how to deal with certain fights, especially in the end game, forcing mobs and bosses there to be nerfed to maintain game balance.
PROPOSAL
Replace the current additive resistance calculation, where total resistance is a sum of the restances from each source to a multiplicative one where the final resistance is computed by multiplying the base resistances (break through, actually) together. That is, replace
R% = r1%+r2%+r3%+......
with
R% = 1-[(1-r1%)*(1-r2%)*(1-r3%)*.....] (interchanging percentages and fractions)
Similarly, the effects of a debuff like curse of vulnerability would be computed as:
R%=R%*(1-debuff%)
Where for example a debuff of 60% would reduce total resistance to 40% of it's normal value.
Consider 3 pieces of gear with 30% resistance each:
Current calculation:
R% = 30%+30%+30% = 90%
Making the character nearly immune to the damge type.
New calculation:
R% = 1-(1-0.3)*(1-0.3)*(1-0.3) = 0.657 = 65.7%
The character is only highly resistant to the damage, and can never become completely immune with normal equipment since diminishing returns are built into the computation.
To make the system complete (and allow for complete immunity to small attacks) a shielding component is needed:
S = s1+s2+s3+.....
This is just a (relatively small) fixed number that is subtracted from the damage after it is reduced by the resistances, much like a kind of magical armor. So the final damage calculation is then:
Dfinal = Dbase*R% - S
This simple formula has the virtues of inherent dimishing returns built in and the ability to achieve immunity against small attacks, or all attacks if one of the base resistances is 100%. So long as a character doesn't have a single piece of gear granting 100% resistance, however, any sufficiently large attack will still penetrate, making this approach scalable to any level of content that may come up in the future.
These results are plotted in the first graph below from game start up to current end game content and beyond, where it is assumed that the character has 3 equal pieces of gear contributing to reistance, and the shielding component is set equal to the resistance % times 0.2. This means that at the point in the game where 20% resistance is typical, a shield of 6 would also be typical (and valued appropriately when generating random items). A single piece of gear with both of these values versus fire would list its resistance as Fire 20%+4, for example. Three pieces of this gear would then provide:
R% = 1-(1-0.2)*(1-0.2)*(1-0.2) = 48.8%
S = 2+2+2 =6
For character sheet resistance of 48.8%+6.
For comparison, the effect on break through damage with shielding ratios of 0.1 and 0.5 is also plotted below.
PROPOSAL
Replace the current additive resistance calculation, where total resistance is a sum of the restances from each source to a multiplicative one where the final resistance is computed by multiplying the base resistances (break through, actually) together. That is, replace
R% = r1%+r2%+r3%+......
with
R% = 1-[(1-r1%)*(1-r2%)*(1-r3%)*.....] (interchanging percentages and fractions)
Similarly, the effects of a debuff like curse of vulnerability would be computed as:
R%=R%*(1-debuff%)
Where for example a debuff of 60% would reduce total resistance to 40% of it's normal value.
Consider 3 pieces of gear with 30% resistance each:
Current calculation:
R% = 30%+30%+30% = 90%
Making the character nearly immune to the damge type.
New calculation:
R% = 1-(1-0.3)*(1-0.3)*(1-0.3) = 0.657 = 65.7%
The character is only highly resistant to the damage, and can never become completely immune with normal equipment since diminishing returns are built into the computation.
To make the system complete (and allow for complete immunity to small attacks) a shielding component is needed:
S = s1+s2+s3+.....
This is just a (relatively small) fixed number that is subtracted from the damage after it is reduced by the resistances, much like a kind of magical armor. So the final damage calculation is then:
Dfinal = Dbase*R% - S
This simple formula has the virtues of inherent dimishing returns built in and the ability to achieve immunity against small attacks, or all attacks if one of the base resistances is 100%. So long as a character doesn't have a single piece of gear granting 100% resistance, however, any sufficiently large attack will still penetrate, making this approach scalable to any level of content that may come up in the future.
These results are plotted in the first graph below from game start up to current end game content and beyond, where it is assumed that the character has 3 equal pieces of gear contributing to reistance, and the shielding component is set equal to the resistance % times 0.2. This means that at the point in the game where 20% resistance is typical, a shield of 6 would also be typical (and valued appropriately when generating random items). A single piece of gear with both of these values versus fire would list its resistance as Fire 20%+4, for example. Three pieces of this gear would then provide:
R% = 1-(1-0.2)*(1-0.2)*(1-0.2) = 48.8%
S = 2+2+2 =6
For character sheet resistance of 48.8%+6.
For comparison, the effect on break through damage with shielding ratios of 0.1 and 0.5 is also plotted below.
- Attachments
-
- Resistance Model0.2.gif (10.98 KiB) Viewed 2160 times
-
- Resistance Model0.1.gif (10.93 KiB) Viewed 2160 times
-
- Resistance Model0.5.gif (11.04 KiB) Viewed 2160 times
Re: A More Scalable Approach to Resistances (w/math, spoily)
My initial impression is positive, particularly the consistency between the resistance + shielding in both the melee and elemental damages. It appears to scale pretty well, too.
<DarkGod> lets say it's intended
Re: A More Scalable Approach to Resistances (w/math, spoily)
I also like it...
but caps have the advantage of being easy to explain to the player, multiplicative resists do not (especially when you add on an extra component.)
but caps have the advantage of being easy to explain to the player, multiplicative resists do not (especially when you add on an extra component.)
-
- Uruivellas
- Posts: 744
- Joined: Thu Nov 18, 2010 6:42 pm
Re: A More Scalable Approach to Resistances (w/math, spoily)
There is also the virtue of more always being better with this system, which is easy for anyone to understand. With caps, it's easy, especially for new players, to make mistakes that waste resources going over cap.
Re: A More Scalable Approach to Resistances (w/math, spoily)
The current cap system is pretty straightforward to anyone who pushed the 'C' button - especially after things like diablo II. Seems to have solved the issue pretty well, really.
Re: A More Scalable Approach to Resistances (w/math, spoily)
That would be a bit difficult to implement in my view of the subject. I think the current system should be changed but this is how I'd do it:
Using the base concept of Resist%=1-0.99^Resist. This is an abstraction of multiplicative effect combination on the opening post that feels logic to all of us:
A Resist of 36 gives us 30.36% resistance. (1-0.99^36=0,3036)
Three times that, 108 would give us 66.22% (1-0.99^108=0.6622)
You can test this and see the numbers add up correctly.
This allows us to set up the diminishing returns without having to completely overhaul the system: Items, spells or talents would just take their current resist values and you'd just have to update the tooltips (for player friendliness) and the damage calculation formulas.
About the shielding concept, I'm a bit indifferent to it but I think it could be easily introduced as a new stat on Talents and Items, kind of like Antimagic Shield.
Edit: Checking code... this might be easier than I thought.
Here we go gentlemen:
Actor Tooltip: Class/Actor line 566 should read:
Item Description: Class/Object line 303 should read:
Class/Player line 70 (so the game doesn't explode
need to be removed later - will cap your resists around 50% if you don't change this at player creation)
Damage Calculation: Data/damage_types line 65
I haven't done the Character Sheet and dump but this is perfectly enough... Enjoy.
Talent and Effect tooltips would have to be updated individually too I'm afraid.
This lowers the average overall value of resists by a little bit 10%, but this can be tuned in the itemization I guess.
Using the base concept of Resist%=1-0.99^Resist. This is an abstraction of multiplicative effect combination on the opening post that feels logic to all of us:
For clarification purposes if you don't follow, in the previous example we had 3 x 30% resists stacking to 65.7%.New calculation:
R% = 1-(1-0.3)*(1-0.3)*(1-0.3) = 0.657 = 65.7%
The character is only highly resistant to the damage, and can never become completely immune with normal equipment since diminishing returns are built into the computation.
A Resist of 36 gives us 30.36% resistance. (1-0.99^36=0,3036)
Three times that, 108 would give us 66.22% (1-0.99^108=0.6622)
You can test this and see the numbers add up correctly.
This allows us to set up the diminishing returns without having to completely overhaul the system: Items, spells or talents would just take their current resist values and you'd just have to update the tooltips (for player friendliness) and the damage calculation formulas.
About the shielding concept, I'm a bit indifferent to it but I think it could be easily introduced as a new stat on Talents and Items, kind of like Antimagic Shield.
Edit: Checking code... this might be easier than I thought.
Here we go gentlemen:
Actor Tooltip: Class/Actor line 566 should read:
Code: Select all
resists[#resists+1] = string.format("%d%% %s", (1-0.99^v)*100, t == "all" and "all" or DamageType:get(t).name)
Code: Select all
rs[#rs+1] = ("%d%% %s"):format((1-0.99^i)*100, res == "all" and "all" or DamageType.dam_def[res].name)

Code: Select all
t.resists_cap.all = t.resists_cap.all or 700
Code: Select all
res = (1-0.99^res) * (100 - pen)
Talent and Effect tooltips would have to be updated individually too I'm afraid.
This lowers the average overall value of resists by a little bit 10%, but this can be tuned in the itemization I guess.
Last edited by Dervis on Sat Dec 04, 2010 12:01 am, edited 6 times in total.
Re: A More Scalable Approach to Resistances (w/math, spoily)
I thought of another way to handle resistance.
It makes 100% resistance basically impossible to get(we could have a special flag for that), and does offer diminishing returns of a sort...
Of course, the resistance offered by items(and natural monster resistances)should be rebalanced, but I think it's doable..
Some examples...
Resistance 100(which should be easier to get than resistance 100%, duh) means you take half damage.
Resistance 200, one third.
Resistance 300, one fourth.
Resistance 900 makes you take 1/10, and so on.
Basically, as resistance approaches infinity, damage taken approaches zero.
The player could simply be shown the 'damage divisor', so it wouldn't be too hard to understand.
One problem is balancing vulnerabilities, and avoiding 'divide by zero'errors, or even ridicolously low damage divisors that result in near infinite damage.
It makes 100% resistance basically impossible to get(we could have a special flag for that), and does offer diminishing returns of a sort...
Code: Select all
damage taken = base damage * 100 / (100+resistance)
Some examples...
Resistance 100(which should be easier to get than resistance 100%, duh) means you take half damage.
Resistance 200, one third.
Resistance 300, one fourth.
Resistance 900 makes you take 1/10, and so on.
Basically, as resistance approaches infinity, damage taken approaches zero.
The player could simply be shown the 'damage divisor', so it wouldn't be too hard to understand.
One problem is balancing vulnerabilities, and avoiding 'divide by zero'errors, or even ridicolously low damage divisors that result in near infinite damage.
ToME online profile: http://te4.org/users/zonk
Addons (most likely obsolete): Wights, Trolls, Starting prodigy, Alternate save/resistance system
Addons (most likely obsolete): Wights, Trolls, Starting prodigy, Alternate save/resistance system
-
- Uruivellas
- Posts: 744
- Joined: Thu Nov 18, 2010 6:42 pm
Re: A More Scalable Approach to Resistances (w/math, spoily)
There are a number of ways to do the scaling so that diminishing returns are incorporated. Dervis's approach is perfectly valid, and the choice of formula largely depends on what kind of curve you want. I chose the formula I proposed because it is more transparent to players -- if you pick up a new piece of gear with 15% resistance on it and equip it, it will reduce the damage you take by around 15% (for the most important case of a reasonably large attack) no matter what resistance you started with.
I started thinking about how the system could be adjusted while playing a sun paladin in the end game, where I could hit the 70% cap on most of the resistances by the end game fight. Thinking ahead, I was wondering what I would do with that character if there was more game to play -- I'd soon be finished with getting enough resistances no matter how much farther I went. As better gear is introduced, we could eventually see everyone running around with uniformly capped 70% resistance to just about everything, which wouldn't be very interesting or balanced in the long run.
As far as implementing the new changes, I don't think the coding is likely to be difficult (though I am not a LUA programmer and am not familiar with the game code), and the shielding component can default to 0 for all current items and be introduced incrementally. The more tedious part would be adjusting existing items, but that, too, shouldn't be too bad if we pick a balancing point with the current system. Rearranging the resistance equation for 2 equal pieces of gear gives:
r%=1-(1-R%)^0.5
For example, if we want 50% resistance in the current system to translate into 50% in my proposed system, we can uniformly adjust up the resistances on current items. Plugging in numbers gives:
1-(1-50%)^0.5=29.3%
So scaling up the resistance on current items by 1.17 (29.3/25) should provide equivalent resistance under the new system at the point we've chosen. Since everything is still being tweaked in beta, we don't reallly need to be exact here, though, so we could just let shields scale up to 35% and body armor scale up to 50% and call it close enough.
I started thinking about how the system could be adjusted while playing a sun paladin in the end game, where I could hit the 70% cap on most of the resistances by the end game fight. Thinking ahead, I was wondering what I would do with that character if there was more game to play -- I'd soon be finished with getting enough resistances no matter how much farther I went. As better gear is introduced, we could eventually see everyone running around with uniformly capped 70% resistance to just about everything, which wouldn't be very interesting or balanced in the long run.
As far as implementing the new changes, I don't think the coding is likely to be difficult (though I am not a LUA programmer and am not familiar with the game code), and the shielding component can default to 0 for all current items and be introduced incrementally. The more tedious part would be adjusting existing items, but that, too, shouldn't be too bad if we pick a balancing point with the current system. Rearranging the resistance equation for 2 equal pieces of gear gives:
r%=1-(1-R%)^0.5
For example, if we want 50% resistance in the current system to translate into 50% in my proposed system, we can uniformly adjust up the resistances on current items. Plugging in numbers gives:
1-(1-50%)^0.5=29.3%
So scaling up the resistance on current items by 1.17 (29.3/25) should provide equivalent resistance under the new system at the point we've chosen. Since everything is still being tweaked in beta, we don't reallly need to be exact here, though, so we could just let shields scale up to 35% and body armor scale up to 50% and call it close enough.
Re: A More Scalable Approach to Resistances (w/math, spoily)
I don't think better resist gear should be introduced to be honest. More variety of yes, but not necessarily better.Hachem_Muche wrote:
As better gear is introduced, we could eventually see everyone running around with uniformly capped 70% resistance to just about everything, which wouldn't be very interesting or balanced in the long run.
Also, your perspective is that of someone who just got done playing a class with a nice buff to resists from a talent. Hitting the 70% cap isn't going to be as easy for other classes.
Finally I'd like to mention that the resist cap was put in as a rule with an exception. You could have gone over the cap to several resists with artifacts that got added to the game to do just that.
Not to come off as harsh but this is the second thread on this subject in a relatively short period of time and while both are well thought out and interesting suggestions the first thread was considered and led directly to the resist cap being implemented along with the inclusion of a few artifacts to break the cap.
I'd like to see more brainstorming of interesting ways to break the cap rather then brainstorming ways to overhaul the system. For instance, how about an artifact that gives you a nice boost to fire resist and the fire resist cap but lowers your cold resist and cold resist cap?
Again, I like multiplicative diminishing returns and several diminishing resist ideas got tossed around the other thread as well as IRC but ultimately a hard cap was what DG felt was best for the game and at least one of his reasons was that it's easy for people to understand.