[7063] Absorb auras fixes (add custom handle for some auras)

Fix Shaman 51474 and ranks
Fix Rogue 31130 and ranks
Fix Druid 33851 and ranks
Fix DK 49145 and ranks, 49157 (TODO: need use only on transform), 50462, 53766, 51052,
Fix 41475 - boss cast
Fix 39228, 60218 (item 27770/37220 spells)
Hidden cooldown for 53601.

Signed-off-by: DiSlord <dislord@nomail.com>
This commit is contained in:
DiSlord 2009-01-10 19:07:24 +03:00
parent 4051db9767
commit 48bebc4056
6 changed files with 245 additions and 64 deletions

View file

@ -1621,87 +1621,235 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
int32 RemainingDamage = damage - *resist;
// Get unit state (need for some absorb check)
uint32 unitflag = pVictim->GetUInt32Value(UNIT_FIELD_FLAGS);
// Need remove expired auras after
bool existExpired = false;
// absorb without mana cost
int32 reflectDamage = 0;
Aura* reflectAura = NULL;
AuraList const& vSchoolAbsorb = pVictim->GetAurasByType(SPELL_AURA_SCHOOL_ABSORB);
for(AuraList::const_iterator i = vSchoolAbsorb.begin(), next; i != vSchoolAbsorb.end() && RemainingDamage > 0; i = next)
for(AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end() && RemainingDamage > 0; ++i)
{
next = i; ++next;
if (((*i)->GetModifier()->m_miscvalue & schoolMask)==0)
Modifier* mod = (*i)->GetModifier();
if (!(mod->m_miscvalue & schoolMask))
continue;
// Cheat Death
if((*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && (*i)->GetSpellProto()->SpellIconID == 2109)
{
if (((Player*)pVictim)->HasSpellCooldown(31231))
continue;
if (pVictim->GetHealth() <= RemainingDamage)
{
int32 chance = (*i)->GetModifier()->m_amount;
if (roll_chance_i(chance))
{
pVictim->CastSpell(pVictim,31231,true);
((Player*)pVictim)->AddSpellCooldown(31231,0,time(NULL)+60);
SpellEntry const* spellProto = (*i)->GetSpellProto();
// with health > 10% lost health until health==10%, in other case no losses
uint32 health10 = pVictim->GetMaxHealth()/10;
RemainingDamage = pVictim->GetHealth() > health10 ? pVictim->GetHealth() - health10 : 0;
}
}
// Max Amount can be absorbed by this aura
int32 currentAbsorb = mod->m_amount;
// Found empty aura (umpossible but..)
if (currentAbsorb <=0)
{
existExpired = true;
continue;
}
int32 currentAbsorb;
// Reflective Shield
if ((pVictim != this) && (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST && (*i)->GetSpellProto()->SpellFamilyFlags == 0x1)
// Handle custom absorb auras
// TODO: try find better way
switch(spellProto->SpellFamilyName)
{
if(Unit* caster = (*i)->GetCaster())
case SPELLFAMILY_GENERIC:
{
AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_DUMMY);
for(AuraList::const_iterator k = vOverRideCS.begin(); k != vOverRideCS.end(); ++k)
// Astral Shift
if (spellProto->SpellIconID == 3066)
{
switch((*k)->GetModifier()->m_miscvalue)
//reduces all damage taken while stun, fear or silence
if (unitflag & (UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED))
RemainingDamage -= RemainingDamage * currentAbsorb / 100;
continue;
}
// Nerves of Steel
if (spellProto->SpellIconID == 2115)
{
// while affected by Stun and Fear
if (unitflag&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING))
RemainingDamage -= RemainingDamage * currentAbsorb / 100;
continue;
}
// Spell Deflection
if (spellProto->SpellIconID == 3006)
{
// You have a chance equal to your Parry chance
if (damagetype == DIRECT_DAMAGE && // Only for direct damage
roll_chance_f(pVictim->GetUnitParryChance())) // Roll chance
RemainingDamage -= RemainingDamage * currentAbsorb / 100;
continue;
}
// Reflective Shield (Lady Malande boss)
if (spellProto->Id == 41475)
{
int32 reflectDamage = 0;
if(RemainingDamage < currentAbsorb)
reflectDamage = RemainingDamage / 2;
else
reflectDamage = currentAbsorb / 2;
pVictim->CastCustomSpell(this, 33619, &reflectDamage, NULL, NULL, true, NULL, *i);
break;
}
if (spellProto->Id == 39228 || // Argussian Compass
spellProto->Id == 60218) // Essence of Gossamer
{
// Max absorb stored in 1 dummy effect
if (spellProto->EffectBasePoints[1] < currentAbsorb)
currentAbsorb = spellProto->EffectBasePoints[1];
break;
}
break;
}
case SPELLFAMILY_DRUID:
{
// Primal Tenacity
if (spellProto->SpellIconID == 2253)
{
//reduces all damage taken while Stunned
if (unitflag & UNIT_FLAG_STUNNED)
RemainingDamage -= RemainingDamage * currentAbsorb / 100;
continue;
}
break;
}
case SPELLFAMILY_ROGUE:
{
// Cheat Death
if(spellProto->SpellIconID == 2109)
{
if (pVictim->GetTypeId()==TYPEID_PLAYER && // Only players
pVictim->GetHealth() <= RemainingDamage && // Only if damage kill
!((Player*)pVictim)->HasSpellCooldown(31231) && // Only if no cooldown
roll_chance_i(currentAbsorb)) // Only if roll
{
case 5065: // Rank 1
case 5064: // Rank 2
case 5063: // Rank 3
{
if(RemainingDamage >= (*i)->GetModifier()->m_amount)
reflectDamage = (*i)->GetModifier()->m_amount * (*k)->GetModifier()->m_amount/100;
else
reflectDamage = (*k)->GetModifier()->m_amount * RemainingDamage/100;
reflectAura = *i;
} break;
default: break;
pVictim->CastSpell(pVictim,31231,true);
((Player*)pVictim)->AddSpellCooldown(31231,0,time(NULL)+60);
// with health > 10% lost health until health==10%, in other case no losses
uint32 health10 = pVictim->GetMaxHealth()/10;
RemainingDamage = pVictim->GetHealth() > health10 ? pVictim->GetHealth() - health10 : 0;
}
if(reflectDamage)
break;
continue;
}
break;
}
case SPELLFAMILY_PRIEST:
{
// Reflective Shield
if (spellProto->SpellFamilyFlags == 0x1)
{
if (pVictim == this)
break;
Unit* caster = (*i)->GetCaster();
if (!caster)
break;
int32 reflectDamage = 0;
AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_DUMMY);
for(AuraList::const_iterator k = vOverRideCS.begin(); k != vOverRideCS.end(); ++k)
{
switch((*k)->GetModifier()->m_miscvalue)
{
case 5065: // Rank 1
case 5064: // Rank 2
case 5063: // Rank 3
{
if(RemainingDamage >= currentAbsorb)
reflectDamage = (*k)->GetModifier()->m_amount * currentAbsorb/100;
else
reflectDamage = (*k)->GetModifier()->m_amount * RemainingDamage/100;
} break;
default: break;
}
if (reflectDamage)
{
pVictim->CastCustomSpell(this, 33619, &reflectDamage, NULL, NULL, true, NULL, *i);
break;
}
}
break;
}
break;
}
case SPELLFAMILY_SHAMAN:
{
// Astral Shift
if (spellProto->SpellIconID == 3066)
{
//reduces all damage taken while stun, fear or silence
if (unitflag & (UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED))
RemainingDamage -= RemainingDamage * currentAbsorb / 100;
continue;
}
break;
}
case SPELLFAMILY_DEATHKNIGHT:
{
// Shadow of Death
if (spellProto->SpellIconID == 1958)
{
// TODO: absorb only while transform
continue;
}
// Anti-Magic Shell (on self)
if (spellProto->Id == 48707)
{
// damage absorbed by Anti-Magic Shell energizes the DK with additional runic power.
// This, if I'm not mistaken, shows that we get back ~2% of the absorbed damage as runic power.
int32 absorbed = RemainingDamage * currentAbsorb / 100;
int32 regen = absorbed * 2 / 10;
pVictim->CastCustomSpell(pVictim, 49088, &regen, 0, 0, true, 0, *i);
RemainingDamage -= absorbed;
continue;
}
// Anti-Magic Shell (on single party/raid member)
if (spellProto->Id == 50462)
{
RemainingDamage -= RemainingDamage * currentAbsorb / 100;
continue;
}
// Anti-Magic Zone
if (spellProto->Id == 50461)
{
Unit* caster = (*i)->GetCaster();
if (!caster)
continue;
int32 absorbed = RemainingDamage * currentAbsorb / 100;
int32 canabsorb = caster->GetHealth();
if (canabsorb < absorbed)
absorbed = canabsorb;
DealDamage(caster, absorbed, NULL, damagetype, schoolMask, 0, false);
RemainingDamage -= absorbed;
continue;
}
break;
}
default:
break;
}
if (RemainingDamage >= (*i)->GetModifier()->m_amount)
{
currentAbsorb = (*i)->GetModifier()->m_amount;
pVictim->RemoveAurasDueToSpell((*i)->GetId());
next = vSchoolAbsorb.begin();
}
else
{
// currentAbsorb - damage can be absorbed by shield
// If need absorb less damage
if (RemainingDamage < currentAbsorb)
currentAbsorb = RemainingDamage;
(*i)->GetModifier()->m_amount -= RemainingDamage;
}
RemainingDamage -= currentAbsorb;
// Reduce shield amount
mod->m_amount-=currentAbsorb;
// Need remove it later
if (mod->m_amount<=0)
existExpired = true;
}
// Remove all expired absorb auras
if (existExpired)
{
for(AuraList::const_iterator i = vSchoolAbsorb.begin(), next; i != vSchoolAbsorb.end();)
{
if ((*i)->GetModifier()->m_amount<=0)
{
pVictim->RemoveAurasDueToSpell((*i)->GetId());
i = vSchoolAbsorb.begin();
}
else
++i;
}
}
// do not cast spells while looping auras; auras can get invalid otherwise
if (reflectDamage)
pVictim->CastCustomSpell(this, 33619, &reflectDamage, NULL, NULL, true, NULL, reflectAura);
// absorb by mana cost
AuraList const& vManaShield = pVictim->GetAurasByType(SPELL_AURA_MANA_SHIELD);
@ -6147,6 +6295,16 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
}
break;
}
// Astral Shift
case 52179:
{
if(!procSpell)
return false;
// Need stun, fear or silence mechanic
if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_SILENCE)|(1<<MECHANIC_STUN)|(1<<MECHANIC_FEAR))))
return false;
break;
}
// Burning Determination
case 54748:
{