Quote:
Originally Posted by Homesteaded
[You must be logged in to view images. Log in or Register.]
They posted today that NPC bash rate is 100%, will be fixed.
|
Not 100%. It's not a bug.
Here's the formula. It matches logs Torven has (and actually, Torven was the one who wrote this formula)
Code:
// this is precise for the vast majority of NPCs
// at some point around level 61, base stun chance goes from 45 to 40. not sure why
int stun_chance = 45;
int defenderLevel = defender->GetLevel();
int levelDiff = GetLevel() - defenderLevel;
if (GetLevel() > 60)
stun_chance = 40;
if (levelDiff < 0)
{
stun_chance -= levelDiff * levelDiff / 2;
}
else
{
stun_chance += levelDiff * levelDiff / 2;
}
if (stun_chance < 2)
stun_chance = 2;
if (defender->IsNPC() && defenderLevel > RuleI(Spells, BaseImmunityLevel))
stun_chance = 0;
if (stun_chance && zone->random.Roll(stun_chance))
{
Log(Logs::Detail, Logs::Combat, "Stun passed, checking resists. Was %d chance.", stun_chance);
int stun_resist = 0;
if (defender->IsClient())
{
stun_resist = defender->aabonuses.StunResist; // Stalwart Endurance AA
}
if (defender->GetBaseRace() == OGRE && !BehindMob(defender, GetX(), GetY())) // should this work if the ogre is illusioned?
{
Log(Logs::Detail, Logs::Combat, "Frontal stun resisted because, Ogre.");
}
else
{
if (stun_resist && zone->random.Roll(stun_resist))
{
defender->Message_StringID(MT_DefaultText, AVOID_STUN);
Log(Logs::Detail, Logs::Combat, "Stun Resisted. %d chance.", stun_resist);
}
else
{
Log(Logs::Detail, Logs::Combat, "Stunned. %d resist chance.", stun_resist);
defender->Stun(2000, this); // bash/kick stun is always 2 seconds
}
}
}
else
{
Log(Logs::Detail, Logs::Combat, "Stun failed. %d chance.", stun_chance);
// This is a crude approximation of interrupt chance based on old EQ log parses
int interruptChance = 100;
if (IsNPC() && !IsPet())
{
if (GetLevel() < defenderLevel)
interruptChance = 80; // Daybreak recently confirmed this 80% chance
}
else if (defender->IsNPC())
{
int levelDiff = GetLevel() - defenderLevel;
interruptChance += levelDiff * 10;
if (defenderLevel > 65 && interruptChance > 0)
interruptChance = 2;
else if (defenderLevel > 55)
interruptChance /= 2;
else if (defenderLevel > 50)
interruptChance = 3 * interruptChance / 4;
}
Log(Logs::Detail, Logs::Combat, "Non-stunning bash/kick interrupt roll: chance = %i", interruptChance);
if (zone->random.Roll(interruptChance))
{
if (IsValidSpell(defender->casting_spell_id) && !spells[defender->casting_spell_id].uninterruptable)
{
Log(Logs::Detail, Logs::Combat, "Non-stunning bash/kick successfully interrupted spell");
defender->InterruptSpell(SPELL_UNKNOWN, true);
}
}
}
And here's the flee stun code. This was taken again from various logs, and additionally happens on Live:
Code:
// 3 second flee stun check. NPCs can stun players who are running away from them. 10% chance on hit
if (spell_id == SPELL_UNKNOWN && damage > 0 && other && other->IsNPC() && !other->IsPet() && other->GetLevel() > 4 && EQ::skills::IsMeleeWeaponSkill(attack_skill))
{
if (animation > 0 && zone->random.Roll(10) && other->BehindMob(this, other->GetX(), other->GetY()))
{
int stun_resist = aabonuses.StunResist;
if (!stun_resist || zone->random.Roll(100 - stun_resist))
{
if (CombatRange(other, 0.0f, false, true)) {
Log(Logs::Detail, Logs::Combat, "3 second flee stun sucessful");
Stun(3000, other);
}
}
else
{
Log(Logs::Detail, Logs::Combat, "Stun Resisted. %d chance.", stun_resist);
Message_StringID(MT_DefaultText, AVOID_STUN);
}
}
}