KhymChanur: I see that, for the ToME module (defined in game/tome/module.lua), resistances are supposed to "add" by taking the greater of the two resistances, so if, for example, the player has many equiped items which give different levels of fire resistance, then the one with the largest resistance will be used. However, this doesn't quite work if vulnerabilities (negative resistances) are thrown in. For instance, if one item gave a resist of +50% to fire, and another item gave -100% to fire (doubling the damage from fire), then they should completely cancel out.
So, how to deal with this? One way would be to give the adding function an array of resistances, and the function would pick the bigest positive resist and the bigest negative resist, and then see how much they cancel each other out. However, since I can't the resist_add() function being used anywhere, I don't know if this would be possible. Another way might be to have a vulnerability_add() in addition to resist_add(), but that seems kind of klunky.
JohnGilmore: I would think that the "proper" way to do this would be to modify resists so that they are a bit lower (average 25% rather that 50% damage reduction) and then apply resists from least to greatest, thusly:
I have four "fire resistance" objects: a -100%, a 25%, and two 50% and take a 100 damage "fire" hit. The first would be applied, increasing it to 200 damage, then the second, decreasing to to 150, then the two 50%'s, reducing the damage further to 75 and 37 respectively. So I'd take 37 damage.
An alternative, which would reduce the usefullness of additional resists, would be to reduce the effectiveness of additional resists at the same time as you reduce the damage, unless the resist is negative. Thus:
-100% doubles damage to 200. 25% reduces it to 150 damage, and reduces the two 50%'s to 38%. the first 38% reduces the damage to 93 and the last resist to 23.5, and the last resist would reduce the damage to 71.
Or you could work it the other way, 50% reduces it to 50, and the rest of the resists to 25%, 12.5%, and -50%. 25% reduces it to 37.5 and the rest of the resists to 9.37% and -37.5%. the 9.37 reduces it to 33.82, and the final resist to -33.82%. The final resist (vulnerability) changes the damage to either 67.64 if you choose not to "reduce" negative resists, or 45.25 if you do.
So, three HP per hundred difference between the last two methods, which is to say almost no difference at all. Note that with either technique, wearing two "vulnerability to fire" items would be a BAD idea. It would double the damage, and double the second vulnerability, for SIX times normal damage, rather than the expected four.
What other methods could reasonably be used to compute damages?
NOTE: I'm sure that with a little algebra we could figure out how to pre-compute all these during "calc bonuses" so that all the fancy math isn't needed every time you get hit.
Orvin: It would be nice if items with "stronger magic" had precedence over items with "weaker magic" when their magical effects conflicted. How about associating a "precedence value" with items...so, if you wear an item that grants fire resistance of -100% and has a precedence of 10, and all of your items that grant positive fire resistance are of precedence less than 10, you talke double damage from fire. You could even assign precedence values to racial modifiers, so an Ent might have to find a powerful item that gives fire resistance, rather than any item that does...
AerdanRunestar: How about modifying by addition rather than multiplication? Thusly, a weakness to fire at -100% and a resistance to fire at 50% would cancel out to be -50%. It'd be simpler than using algebra, at any rate.
LukeHaub: The last time I looked at resists which i'll admit was a couple of alpha's ago i thought they were just being applied one after the other like JohnGilmore's previous example
I have four "fire resistance" objects: a -100%, a 25%, and two 50% and take a 100 damage "fire" hit. The first would be applied, increasing it to 200 damage, then the second, decreasing to to 150, then the two 50%'s, reducing the damage further to 75 and 37 respectively. So I'd take 37 damage.
which means that it doesn't matter which order you apply them in, you'll always get the same final resist.
i'm fairly certain the code for the resist stacing funciton looked something like this
multiplier = 1 for i = 1 to number_of_resists multiplier = multiplier * (100 - resists[i]) / 100 end
and then you'd just multiply the damage by multiplier.
Personally i prefer simply stacking them like AerdanRunestar said rather than multiplying them but i definitely disagree with the idea of giving each resist a precedence Orvin
ShrikeDeCil I'm with Luke. A difficulty with the multiplication scheme is that the 'pluses' and the 'minuses' aren't symmetric around zero. That is, picture a +100 & a -100 item. The +100 is immunity, the -100 is just double damage. You'd need -600 or so to get to where 'susceptibility' under the old system was, yes? So, like T2, you look for your item of immunity and ignore the bonuses and deficits of your other gear with regards to that attack.
If you turn it around and say 'add the resistances/susceptibilities all up' (and even if you just take the largest ones, whatever), then you have 100%(base damage) +100%-100%=100% -> normal damage. So all the little '+5s' do end up being relevant if you like. And conceptually easier to deal with on the fly by the user. Having to decide between the gear based on some of the proposals above would be excruciating. (Ok, this cloak isn't my _main_ fire resistance, but it does provide some and I can expect half of that bonus to apply as long as I'm not wearing those gloves, which would make this the third highest fire resistance...)
Expressing this in code:
resist_modifier = 100 -- With no resists, we expect to take 100% damage.
for i = 1 to number_of_resists -- where susceptibilities are just negative resists.
resist_modifier = resist_modifier - resists[i]
end
resist_modifier = resist modifier/100
damage = damage * resist_modifier
if damage < 0 then damage = 0 -- (Unless one wants PCs being healed by flames :D)
NeilStevens: How about we do it like in ToME 2: Resistance supersedes vulnerability?
Engine-wise I would like to see a more clear interface for doing resistance addition. Perhaps the function should take two tables, one listing all the permanent resists, and the other listing all the temp resists. Then we can do this (in pseudocode):
if max(temp) or max(perm) is 100
return 100
if max(temp) and max(perm) is 66
return 88
if max(temp) or max(perm) is 66
return 66
if max(temp) and max(perm) >= 0 -- Inequality to deal with non-elemental resists
return 0
else
return min(temp, perm)
end
LukeHaub: I thought we were trying to move away from the breakpoint thing so your resistance could be any value, not just 2/3 or 8/9
NeilStevens: The engine is, the game isn't. At least, as far as I know. And well, since I'm writing the ego items.... heh.
LukeHaub: If you're going to have monsters with resistances such as 50 and 95% you might as well do that for items too. But I suppose if i don't like it i can always change it in a module
LukeHaub: Just thoought i'd point out one potential problem with the multiplication way. If someone has a resistance of >100% then resistances <0 would actually be a benefit not a hinderance because they'd increase the amount of damage you'd be healed
e.g. 125% and -100% resistance
mult = 1 mult = mult * (100-125)/100 = -0.25 mult = mult * (100+100)/100 = -0.5
so having that -100 would double the amount you'd be healed by a resist >100%
on top of this, having 2 resists >100% e.g. 150% and 150% then the two negatives would cancel out
mult = 1 mult = mult * (100-150)/100 = -0.5 mult = mult * (100-150)/100 = 0.25
ToME Wiki