The Bard Proc Exploit
I don't know when this was discovered, but in 2002 it was publicly known that bards could stack tash debuffs with enchanters by using proc weapons. A couple of Safehouse threads described it:
Quote:
Originally Posted by Safehouse Thread April 2002
If a bard casts a spell that is already on something, it stacks anyway. So, if an enchanter casts Tash on a mob, then a bard procs Tash from a weapon, it stacks. If any other class tries to proc tash over an enchanter cast tash they get "Your spell did not take hold". I don't know why, but bard songs/spells always stack if they are cast last.
If the bard procs Tash before the enchanter casts Tash, then the enchanter one will overwrite it I'm pretty sure, and the bard will need to proc again to make them stack. This is the same idea with bard dmg shield stacking (which I hear is supposedly being fixed again next patch, let's see how badly this breaks bards). Bards can sing at least 2 dmg shield songs and also cast a dmg shield from a SS bracer, and then also cast a dmg shield from a summoned Lava Diamond (from magician VP staff off Druusshk). This is a big key in making monster 130+ pt dmg shields for MTing things like Avatar of War.
|
https://web.archive.org/web/20020514....topic&index=4
Quote:
Originally Posted by Safehouse Thread May 2002
A bard can stack a tash spell on top of an enchanter's tash spell, as long as they aren't the same exact identical version of tash (there are 4 versions). No other class is able to do this.
|
Quote:
Originally Posted by Safehouse Thread May 2002
I did indeed confirm for myself last night that bard item tash stacks after enchanter tash is applied, and does get overwritten if the bard does it first.
|
https://web.archive.org/web/20020601...ID=11187.topic
I don't think this was abused much during Velious. If it were public knowledge in 2001 then Sony would have likely fixed it sooner. Sony was much less tolerant of this kind of thing back then. It obviously makes slowing much easier and would allow ST warders to become slowable when they otherwise would not be, assuming they had ~155 MR.
This exploit seems to have been patched out on September 26 2002:
Quote:
Originally Posted by eqdiva.com front page by Espio
A major patch today for bards, if mostly a stealth major patch. Dont let the offical text below fool you - they made some serious changes to bard stacking without letting us know. It appears that most 'special' bard stacking (such as tash orb/stick, DS'es, and illusions) no longer function (anyone wanna buy my orb?...). In addition, McVaxius' Rousing Rondo no longer stacks with the epic or primal proc. Oh, and the procs from the Epic and Sirensong now interrupt your twisting.
|
My Guesses at Sony's September 4 2002 Individual NPC Resist Increases
Unchanged NPCs:
- The standard resist was not changed. It was 25/35 before and after. (this is factual, not a guess)
- Any mobs under 100 resist likely didn't change. I have a hard time thinking they went through the trouble to add small amounts to more trivial mobs.
- I think older era (i.e. pre-Velious) mobs were less likely to have changed. (other than the 435 thing) Sony was probably content to allow them to resist less rather than spend the time to adjust them. Kunark era mobs also tended to be resisty anyway, so I doubt they minded if they became easier to hit.
- The common Fearplane mobs look as though they were not changed. Log data from 2001 shows Amygdalans having the same resists.
- West ToV dragons, Eashen and Ikatiar look unchanged for all resists.
- Tormax, Vindicator, Dain, Tunare, Yelinak and Velketor also look unchanged to me.
- Suits of sentient armor in WL have about 105 FR and CR on Live, which I think was unchanged. The tipa logs and old comments agree they were resistant.
- I parsed the resists of "a geonid" in WL which had 335 CR and ~115 FR. Old comments remark on their high resistance and suggest this was unchanged.
Luclin raid bosses seem to have not been changed, or if they changed some I can't tell. They all pretty much have low to moderate resists on Live servers and the few that are resisty were known to be resisty. (e.g. Aten) Aten would have still been easily slowable with the same MR. This is a little weird because many Velious NPCs seem to have gained resists but Luclin looks unmodified. Perhaps because they had so much HP and Sony was nerfing sustained CH rotations at the time that they just decided to let nukes hit easier.
I did find one exception (well, two) for Luclin however: after the September 4 patch, Seru and Emperor both became magic slowable, and Sony had to disable the spawns temporarily to prevent guilds from killing them easily. This bolsters the theory that they didn't adjust Luclin NPC resists. If they didn't bother to change those two mobs then it seems less likely they changed others.
https://dbsanfte.github.io/eq-archiv...msg-148342.txt
"old ahr used to have super resists and apparently at some point mob resists all got lowered by a *lot* in luclin!" (4/19/03)
https://web.archive.org/web/20030521...topic&index=68
Changed NPCs:
- All NToV dragons (minus Kreizenn) look like they had their MR raised by 50.
- ToV trash mobs with 185 MR likely gained 50 MR. It looks as if every NPC in the zone that had over 100 MR gained 50 MR.
- Aaryonar, Feshlak, Mirenilla and Koi`Doken have high all resists so these mobs may have been given +50 to all but I'm far from certain.
- The back five dragons in NToV have lower resists so these may not have gained +50 to FR CR PR DR, but their MR looks elevated.
- Dozekar looks like his MR was raised but not the other resists.
- Three ST Warders (not Hraashna) seem to have gained 100 MR.
- Sont, Kland and Dagarn got 100 MR. Other resists may have been raised too but it's hard to say. (more likely than not)
- Statue and Idol gained 100 MR. Non-MR raised at least 50, maybe 100.
- Avatar of War gained MR, otherwise cripple wouldn't land. Probably 100 although 50 would allow cripple to land with Occlusion.
- Mobs with 435 may have had their resists increased from 335. Mobs with 335 probably were 335 before.
- Old comments under dracoliche say fire hit easily but the FR I parsed was 175. Sounds like FR got 100, maybe less. MR as well.
- Kyenka and Yetarr look like they may have had MR increases.
- Wuoshi had to of gained 100 MR to be slowable. CR and FR raised by 50-100.
- A 2001 comment under Tantor says he was slowed by a mage and enchanter. This probably means Tantor's resists were increased because he parsed at 185 MR.
- Many WW dragons, Mraaka and Tantor have 185 MR and they also have high secondary resists. It's very plausible to me that these had something like +50 applied to all resists. If Tantor was given resists then likely most or all of these did.
Post-Planes of Power Resist Modifications
I am also aware of Sony reducing resists on NPCs in 2006. Rashere (a Sony developer) at the time was planning on doing another resist system revamp, and part of this revamp included a reduction in resists on many NPCs to compensate for the algorithm changes. Rashere ended up not going through with the logic changes but apparently the resist reductions stayed in, unfortunately. I have only noticed the reductions on PoP era NPCs but this is only possible to measure on a tiny handful of NPCs from old logs due to needing hundreds of spell casts to notice small adjustments so it could have been applied to an unknown number of NPCs from any era. See this post for more details:
https://www.eqemulator.org/forums/sh...6&postcount=19
I'll snip the most relevant portion of that post for convenience:
Quote:
Originally Posted by Torven
I also want to mention that I found considerable differences in the resist rates on Planes of Power NPCs on Live vs. what I see in AK logs. I can calculate a resist estimate using logs where AoE spells were employed (PBAoEs or wizards quadding) which provide a reasonable sample size. Mobs that have 50 resist on Live seemed to have about 65 resist on AK. I also found mobs that have 65 MR on Live having about 80-85 on AK. (e.g. PoFire flameheads) BoT minibosses (the level 65 ones) also resisted slow A LOT on AK, and their current 155 MR on Live is just too low to match AK logs. I had also done some crude MR tests on Diaku ogres on AK to find the best charm pet, and the results indicated higher MR on AK. (except for one which was oddly lower) Just about every mob I could check from AK logs showed higher resists on PoP NPCs, but I can only check a handful of NPCs because large samples are required.
|
I also found a few cases of Live server NPC resists being wildly different than what AK logs showed. On Live servers now, and was the case in 2014 when I parsed the NPC, Azaracks in Sky are highly resistant to fire but AK logs show fire hitting them well. Sony at some point after AK's time raised their fire resist by a significant amount. The same is the case for Rhag`Zhezum, Arch Lich Rhag`Zadune and Rhag`Mozdezh which are all fire immune on Live servers but AK logs showed fire landing easily. Emporer Ssraeshza is disease immune on Live but old websites all said he was disease slowable. There are likely more cases like these but they are hard to find.
My NPC statistics spreadsheet, which has my parsed Live NPC resist values and is the source for TAKP's data, can be found here:
https://docs.google.com/spreadsheets...gid=1108344399
The Level Difference Modifier
An ex-Sony/Daybreak developer by the name of Prathun wrote a post in 2010 which outlined how the resist algorithm worked at the time. It was an extremely illuminating post and invaluable to the emulation community for obvious reasons.
The resist value of the target, while resisting a spell, is increased or decreased prior to the roll by an amount that increases exponentially as the level gap between the caster and the target increases. This is why higher level casters land spells easier on lower level targets and lower level casters have a harder time landing spells.
Prathun's 2010 resist pseudocode post mentions the level difference modifier being this:
Code:
Adjust resist chance for level difference between caster and target.
Set temp level difference to (target level - caster level).
If target is at least level 67 and target is an NPC, temp level difference is set to (66 - caster level) or 0, whichever is greater.
If target is a PC, and caster level is at least 21, and temp level difference is greater than 15, set temp level difference to 15.
If target is an NPC, and temp level difference is less than -9, set temp level difference to -9.
Set level modifier to (temp level difference * temp level difference / 2)
If temp level difference is negative, make level modifier negative.
If target is an NPC and caster is far below target's level, set level modifier to 1000.
That is very similar to the older logic. All of the older clients (including the February 1999 client) do this:
Code:
level_diff = defender_level - attacker_level;
if (!IsNPC()) {
if (level > 20 && level_diff > 10) { // green/low cons casting on clients; cap resist advantage player gets to 50
level_diff = 10;
}
}
else if (IsNPC() && level_diff < -9) { // caps the level advantage when casting on green/low NPCs to -40 resist; same as modern EQ
level_diff = -9;
}
level_mod = (level_diff * level_diff) / 2; // modern EQ still does it this way
if (level_diff < 0) {
level_mod = -level_mod;
}
So the two main differences between old EQ and modern EQ are that players get a lot more benefit from level difference when saving against green NPCs in modern EQ and the penalty from level difference when attacking very high level NPCs is capped at defender_level = 66. Also starting in Omens of War when players go over level 66, the level difference mod starts to vanish even from NPCs below the player's level.
The level 67+ thing would have made level 70 bosses resist less while the player cap was still 60. It's possible this was put in during Velious in the October 8 patch. It's also possible it was put in with the September 4 2002 patch. It's also possible it was put in for Omens of War or some other time. We can't know without some kind of Darkpaw leak. The need for such a thing increased with PoP where boss levels went from +10 to +15. (bosses could be level 80 in PoP although I suppose Sony didn't have to make them that high) I really doubt it went in during Velious because it would have made raid bosses much easier to land slows on and I've found nothing mentioning this. Furthermore Luclin bosses are all level 66. If I were forced to pick one, I'd say Sept 4 '02.
The old clients do not have that 1000 modifier in them. We could not find anything relating to the "six level limit" (I explain what that is later) in the old clients or any sort of resist wall when fighting against NPCs that are much higher level than the caster. It seems to have been outside the functions we have decompiled and likely in a function the clients didn't have. The diff*diff/2 modifier would have prevented spells from landing on very deep reds though, and anything 16 or more levels above the player would have resisted even lifetaps in classic unless it was magic debuffed if this six level limit didn't exist, as it's not capped in that direction on NPC targets.
Resist Roll Details
Prathun's 2010 resist pseudocode post describes modern EQ's resist roll this way:
Code:
Roll a random number between 0 and 200.
If the roll is greater than the resist chance, spell lands.
However by doing tests on Live servers in 2021 I have determined that the roll is actually 1-200 there. I don't think Prathun was very concerned about being precise and unambiguous here when he wrote that, but we can't be sure when the roll changed from 0 to 1. Sony's random number function, in the code, is called like this: RollNum(X, Y) and the possible outcomes end up being X to (Y-1). So when Prathun said "0 to 200" he may have meant 0-199 inclusive there. I speculated in another thread that Rashere (a Sony dev) may have done it in 2006 but I really can't know when it was, and it may just have been some time between 2010 and 2021 as Prathun's post suggests.
Classic eras (pre Sept 4 2002) for certain rolled 0-99 (inclusive) as the decompiles show. I'm somewhat sure (although I wouldn't say 100% sure) that after the September 4 2002 patch the roll still started at zero instead of one. It was either 0-199 or 0-200. I have no way to determine if the top roll is 199 or 200 without a running Sony PoP server to parse on, which don't exist anymore (RIP AK), but I was able to find out via old logs that the lowest roll is very likely 0 post Sept 4 revamp. See this post for details:
https://www.eqemulator.org/forums/sh...6&postcount=19
In all eras that I'm aware of, when the roll is equal to the effective resist value then the spell will resist. This is the case in the decompiles, Live circa 2021, and Prathun's pseudocode also says > instead of >=. My AK log data cannot rule out >= as it's not enough to, but the data does suggest that it was also > in PoP.
There are two consequences to the roll starting at zero and checking it using a > instead of a >=.
The first is that the effective resist rate in classic (which does a 0-99 roll) ends up being resist value + 1. For example if the resist value is 5 then the possible roll outcomes which result in a resist are 0, 1, 2, 3, 4, 5. That is six values out of 100 possible rolls so a 6% resist rate. After Sept 4 the resist rate ends up being 3%. (or 2.985% if a 0-200 roll) If the roll starts at 1, then the resist rate becomes 2.5% using a 1-200 roll. This has large implications for tick saves.
The second is that it becomes possible to resist a spell even at zero resist value by rolling a zero if not accounted for. Classic eras had floors to prevent the resist value from being zero, but after Sept 4 2002 it became possible to guarantee that a spell will land for full on a target. (either by debuffs, level difference or spell resist modifier) The partial damage math breaks if the resist value is zero, so it seems that Sony had a "if resist == 0 then spell lands full" check in place before they switched to 1-200.
The classic clients also did this:
Code:
if (roll > 98 || roll > resist) {
// land spell
} else {
// resist spell
}
They explicitly allowed for a one percent chance of landing a spell regardless of the target's resist value. The roll is skipped if the 151 threshold is met earlier in the logic however, so basically if the target was lifetappable, then there was at least a 1% chance to land any (MR) spell on it. Theoretically this would have allowed slow spells to land on some otherwise unslowable targets, although the gap between 99 and 151 isn't very large and most unslowable mobs would have been above that 151 threshold. It also makes the difference between the 99 PC cap and 100 NPC cap mostly pointless because a 99 roll will simply land the spell although NPCs would partially resist a tiny bit more.
I did find log evidence of this. I have 2001-2002 logs of my warrior getting hit by spells very very infrequently when I know that my resist was > 100 at the time. (seen in screenshots and logged buffs) I was pulling mushrooms in Fungus Grove for AoE groups, which cast several hundred spells on me. The hit rate was about 1% as expected. I also had Thunder Blast land once in 61 casts in a log.