View Single Post
  #3  
Old 06-05-2025, 03:48 AM
Torven
Sarnak
 
Join Date: Aug 2014
Posts: 76
Default

Partial Damage

PoP and later era EQ has two resist scales: 0-199 and 0-599. All-or-nothing spells use the 0-199 scale and partial damage spells (DDs) use the 0-599 scale. Meaning the spells begin to always full resist after the target's effective resist hits 200 or 600. The average damage on DDs becomes very low well before 600 however. Although if a caster is anywhere from level 30 to 50 and the target is an NPC then the DD scale will vary and be as low as 0-399 due to the partial damage modifiers for level 50 and under casters.

Classic resists have an all-or-nothing scale (0-99) but also the resist caps create a strange region above 99 which is completely flat until the 151 immunity is reached. This allows DD spells to still land even after all-or-nothing spells become immune(ish) for another 50 resist values up until the hard 151 limit. I say this is strange because you would expect a target with 150 resist value to resist more than one with 100 resist value, particularly when resists were more potent back then, but this is not the case.

Here is the partial damage logic from 1999 launch until October 8 2001:

Code:
mitigation_pct = (resist_pct * 100 + roll * -100) / resist_pct;		// this formula is used up until Sept 4 2002

if (IsNPC())
{
	if (level_diff > 0 && defender_level > 16) {	// yellows and reds
		mitigation_pct = mitigation_pct + 5;
	}	
	if (defender_level > 29) {
		mitigation_pct = (mitigation_pct - 25) + defender_level;	// gets quite large on the highest level mobs
	}
	if (defender_level < 15) {
		mitigation_pct = mitigation_pct - 5;		// landing on newbie mobs is easier than on player targets
	}
}
if (mitigation_pct < 0) {
	mitigation_pct = 0;
}
if (mitigation_pct > 100) {
	return 100;
}
return mitigation_pct;
resist_pct is the effective resist value and roll is a random number from 0 to 99. Sony's resist algorithm returns the mitigation percentage, which is the inverse of the damage percentage, so the actual damage would be something like: spell_dmg = max_dmg * (100 - mitigation_pct) / 100. Logs show that Sony's servers rounded up using that math, so I'm not precisely sure how they did the final step.

Damage on players is very simple and is computed by that formula without the extra modifiers applied. The modifiers make NPCs targets resist more or less compared to players depending on the NPC's level.

On player targets and NPCs without qualifying modifiers, the above formula will result in a full resist only if, and always if, the roll is 0. Beyond that 1% chance, players could not fully resist DD spells prior to September 4 2002. The spells could still be heavily mitigated down to very little, but the full resist rate was always one percent. This will probably seem odd if you're used to the new resist system.

The maximum a player (and NPCs under level 30) could mitigate non-lure DD spells to was 50% average damage. It's 50% because at max resist (the player cap is 99 remember) the partial damage formula will mitigate the spell damage by about the amount of the roll; i.e. roll a 10, the spell does 11% damage; roll a 50, the spell does 51% damage; roll a 99, the spell does 100%. EQ math is fairly simple.

There are three modifiers for partial damage spells landing on NPCs. The first adds 5% more mitigation on yellow and red con NPCs which are also above level 16. The second adds a large resist bonus to level 30+ NPCs, growing larger the higher level the NPC is, and stacks with the previous modifier. The third reduces the mitigation by 5% for newbie level NPCs.


Partials After The October 8 2001 Patch

Velious was known to be a very melee-centric expansion with caster DPS falling behind the melee DPS. This was in large part due to the increased max hitpoints of NPCs and melee DPS scaling with gear a lot more, but the original resist algorithm was also punishing when casting on very high level targets. Sony addressed this two months prior to Luclin by significantly reducing DD spell mitigation by removing the partial damage modifiers on yellows+reds and on level 30+ NPCs, but only for level 51+ players. Sony also reduced NPC resist values.

Quote:
Originally Posted by October 8 2001 Patch Note
- The level-based spell resistance bonus inherent in super-high level NPCs has been reduced significantly.
A developer forum post explained it in more detail:

Quote:
Originally Posted by Abashi on Oct 5 2001
Through our testing we found that many higher level creatures, and especially those creatures that are above 60th level, were typically resisting magical damage to an extent far greater than they should have been. This lead to a couple of classes having their usefulness in these situations either negated or reduced to a pure utility role. As such we’ve made the following changes:

NPCs now have less of a chance to resist any direct damage spell caused by casters above level 50. Super-high level NPCs have received a large reduction in the level-difference bonus they receive to their resists based upon the level of the attacking player character. We’ve increased the effectiveness of resist debuffs against a large number of higher level NPCs in regard to damage spells being cast upon them. We’ve also reduced the resistances on a wide range of NPCs, especially for NPCs in Velious.
I don't know what "increased the effectiveness of resist debuffs against a large number of higher level NPCs" is referring to. Resist debuffs always reduced by the same amounts as far as I'm aware. (PvP aside)

Prathun's 2010 spell resist pseudocode shows the modifiers being limited to levels 50 and under:

Code:
Partial resist modifier is set to ((150 * (resist chance - roll)) / resist chance). 
If target is a non-mercenary NPC...
	If target is higher level than caster, and target is at least level 17, and caster is level 50 or below, add 5 to partial resist modifier.
	If target is at least level 30 and caster is level 50 or below, add (casterlevel - 25) to partial resist modifier.
	If target's level is less than 15, subtract 5 from partial resist modifier.
My old logs confirm that the modifiers were gone after that patch for my level 60 wizard which I just happened to have logs of from Oct 2001.

That patch did not remove the DD yellows and reds +resist modifier however. Prathun's pseudocode still has it:

Code:
If effect is damage and target is a non-mercenary NPC...
     If target is at least level 67, level difference is set to (66 - caster level) or 0, whichever is greater.
     If target is at least level 17 and level difference is greater than 0, add (2 * level difference) to resist chance.
They might have added that level 67 cap at the time but I have no way to know. There were other points in time where it made sense to add that, and I think Sept 2002 makes more sense because it made raid bosses much easier to land debuffs on and the intent at the time was seemingly to allow damage spells to land easier, not slows.

Removing those two partial damage modifiers for level 51+ casters meant that the damage 51+ players did to NPCs ended up the same as damage done to players, meaning that NPCs could not fully resist DD spells beyond the 1% chance unless it was entirely immune and the average damage players did to even highly resistant NPCs ended up about 50% average damage so it was a significant buff to casters. Before the patch, the most resistant non-immune NPCs would only take about 13% average damage.

I did find a discrepancy with Prathun's pseudocode and the classic logic in regards to the partial damage modifiers. Prathun mentions this: "add (casterlevel - 25) to partial resist modifier". Notice he says the caster's level there instead of the target's level. All of the old clients use target's level there. I strongly suspect that Prathun made an error in his post, because using the caster's level instead of target's level doesn't make much sense as the penalty would get worse as the caster went up in level even while casting on the same level NPCs.




Estimating NPC Resist Values From Spell Damage

Knowing how partial damage is calculated allows us to figure out the target's resist value if enough hits are in the log. Unfortunately I have very few logs from before PoP era so I can only calculate resists for a few NPCs, but if somebody finds old logs at some point they can get a resist estimate by following the instructions I will outline.

First you must understand that there are a limited number of possible partial damage values for a given spell. For any given resist value, only a subset of these values is possible. With enough partial damage hit values, it is possible to determine the target's resist value. I have made a table in a spreadsheet which will calculate every possible partial hit damage for a given spell. With that it is possible to find the resist value that best matches the partial damage numbers seen in an old log file.

Even a single partial hit can tell you that the resist value is over a certain number. For example, if Sunstrike hit for 33 damage, that means the effective resist value is 50 or higher, because 33 is not possible for lower resist values. Note that this is only true for logs from Oct 8 2001 until Sept 3 2002. Also note that you must account for the level difference of the caster and NPC, debuffs, spell resist adjusts (wizards' -10 for example), etc. and reverse apply these to get the NPC's real value.

Using a cell formula of =CEILING.MATH((MIN(MAX(INT((C$3*100+$B4*-100)/C$3), 0), 100)-100)*-1*$F$1/100) where column B is the random roll number and row 3 is the resist value and F1 is the max spell damage, you will get a table of partial damage hits for spells from Oct 8 2001 until Sept 3 2002. In Excel you are able to highlight cells with a specific value using conditional formatting and this makes it easier to find the best resist match. It's more complicated to make a table for damage prior to Oct 8 2001 due to the modifiers and I don't have enough logs of raid content from before that time to get any useful data from.



My October 28 2001 log has AoE damage on Fearplane mobs in it. I had parsed these NPCs on Live years ago, but I can use this log to verify my findings. The expected resist values for a level 60 wizard casting Jyll's Wave of Heat on most of these NPCs should be 10 or 5, which are the floors I mentioned previously, as level difference should give a me -40 and the spell itself another -10, and most of the NPCs in the zone parsed to the typical fire resist of 35 on Live servers. The random level range of these NPCs is 48-52, so 3 out of 5 of these NPCs will have an effective resist of 10 and the other 2 of out 5 will have an effective resist of 5 due to the resist floors.

[Sun Oct 28 17:59:28 2001] a glare lord was hit by non-melee for 65 points of damage.
[Sun Oct 28 17:59:28 2001] A glare lord is incinerated by an intense wave of heat.
[Sun Oct 28 17:59:29 2001] phoboplasm was hit by non-melee for 195 points of damage.
[Sun Oct 28 17:59:29 2001] Phoboplasm is incinerated by an intense wave of heat.
[Sun Oct 28 17:59:39 2001] a glare lord was hit by non-melee for 519 points of damage.
[Sun Oct 28 17:59:39 2001] A glare lord is incinerated by an intense wave of heat.
[Sun Oct 28 17:59:50 2001] a glare lord was hit by non-melee for 65 points of damage.
[Sun Oct 28 17:59:51 2001] A glare lord is incinerated by an intense wave of heat.

The log shows these partial damage hits. 519 is only possible for a resist value of 5, 10, 15, 20, 24 and gets more common above 24. 65 partial damage is only possible for resists 10, 11, 20 or higher. 195 is possible at 10 resist, 17 resist, 20, 24 and higher. So only having these few partial damage hits, we are able to verify that 10 effective resist (effective meaning after all modifiers are applied) value is likely the correct answer for these casts, and the NPCs' resists are 35 because that's the standard resist value. (more on standard resist values later) The next possibilities would be 60 or 70. If you had another log of a player round level 50 you could determine if the resist rate was 35 or 60 just from eyeballing it. (incidentally I did parse them at 35 when I parsed Live server NPCs)

Amygdalans have a higher MR, FR and CR. I parsed them at 95 on Live servers. For these mobs the level difference modifier is either -40 or -32 since my caster was level 60. Fear mobs have a level range of 48-52, so the level 52 ones would end up with a level modifier of -32.

Jyll's Wave of Heat partial damages on Amygdalan warrior: 52, 150, 279, 318, 389, 558
Jyll's Wave of Heat partial damages on Amygdalan knight: 428, 597
Jyll's Zephyr of Ice partial damages on Amygdalan warrior: 292, 565, 571
Jyll's Zephyr of Ice partial damages on Amygdalan knight: 72, 494

The lowest effective resist value that may produce a partial hit of 318 damage using Wave of Heat is 27. The same is true for 292 and Zephyr of Ice. So we can know that Amygdalans had at or above 69 absolute resist value just from those hits. (27+32+10) 95 absolute resist value would translate to either 45 or 53 effective resist value for these spells, and the data matches this for all hits except 428 and 558. I can't explain why those wouldn't match except if a level 52 one with temperate flux staff debuffed, then it would fit. There were a few other wizards there. 95 still fits the best for the data. The next best fit is 85, but if Sony had modified resists I would think they would have raised it by more than 10 on Sept 4 2002. This is fairly strong evidence that common Fearplane NPCs did not have their resists changed since 2001. (probably never)

[Sat Oct 13 23:23:14 2001] Ymmeln was hit by non-melee for 198 points of damage.
[Sat Oct 13 23:23:14 2001] Ymmeln is caught in a torrent of jagged ice.
[Sat Oct 13 23:23:00 2001] Ymmeln was hit by non-melee for 249 points of damage.
[Sat Oct 13 23:23:00 2001] Ymmeln is caught in a torrent of jagged ice.
[Sat Oct 13 23:23:08 2001] Ymmeln was hit by non-melee for 408 points of damage.
[Sat Oct 13 23:23:08 2001] Ymmeln is struck down by Solists spear of ice.
[Sat Oct 13 23:22:01 2001] Ymmeln was hit by non-melee for 960 points of damage.
[Sat Oct 13 23:22:01 2001] Ymmeln is struck down by Solists spear of ice.

I parsed two of these named HoT drakes on Live, although not this particular one, and they also parsed to about 85 cold resist. This 2001 log shows it was maloed, so that means -45 or -60. Reduce by another -10 because of wizard nukes. The NPC is level 60, so there is no level difference modifier. 15 and 30 effective resist value fits for this and not much else. We would expect the resist to be a multiple of 5 which eliminates everything else under 45. The log also shows 11 full damage casts on it, which is a full damage cast rate of 73%, which more closely matches -45 malo. This log data matches Live's value and indicates that the resist value has not changed since 2001 with relatively high confidence.

I have precious few logs of spells landing on raid content prior to September 2002 otherwise I'd give better examples. But this illustrates how it can be done.

A simple way to get an estimate for a resist is by getting the resist rate of full damage DDs or landed all-or-nothing spells on a mob from a log. Since resist rate = effective resist value in this era, it's straightforward to come up with an MR estimate once you account for level difference and other modifiers. This works on Live servers too but you have to multiply the resist rate by two since the scale is 1-200 instead of 0-99 and this is one way I get resist estimates from Live NPCs. On Live servers you can cast hundreds or even thousands of times in carefully prepared logs, but in older in-era logs your estimates will have a much higher margin of error for obvious reasons.

As an example, I have a 2001 log of my warrior attacking Vulak with a Sceptre of Destruction. I can use the proc resist rate to estimate Vulak's magic resist.

In this log, 24 anarchy procs landed on Vulak. 4 resisted. This is a resist rate of ~14%, which would make the effective MR estimate 14. Now we reverse apply every modifier: -40 for tash, -60 for malosini, +50 for level difference modifier and +20 for damage spell penalty on yellows/reds. This makes the modifier -30, so we add 30 to the 14 = 44 estimated MR. That's the procedure, however bards also kept Occlusion on this Vulak for at least some of the fight which throws the numbers off. The resist floor would keep the resist rate at least 10%, so that floor could have been hit here. These factors make for a bad example but I have so few logs to use. I'd expect Vulak's MR to be somewhere around 35-60 looking at this.

I also happen to have five logs of Lady Vox raids of my wizard from before Kunark. In total there are 29 hits and 16 full resists of the Conflagration spell. 12 were full damage. I parsed Lady Vox's fire resist at 60 points on Live servers a decade ago. I also wrote a script to simulate spell casts, so we can test to see if it matches the old logs. Simulating 60 resist value (wizard DDs get -10 but the yellow+red penalty cancels it out) in this scenario results in a full hit rate of about 17% and a full resist rate of 29%. That is somewhat close to the log results of 27% and 35%, particularly when small differences in resist value change the results quite a bit. The margin of error is large with a sample size of 45. One of the logs was from before wizards got the -10 modifier however and the damage was noticeably worse in that, including 3 of the 16 full resists. Also the resist value might be off by 5 as the parse has a margin of error as well. The results at least do not conflict with the classic era resist logic.
Reply With Quote