diff options
Diffstat (limited to 'src/game/Unit.cpp')
-rw-r--r-- | src/game/Unit.cpp | 296 |
1 files changed, 235 insertions, 61 deletions
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 535465d52d2..5a69f29a927 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1741,87 +1741,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) + SpellEntry const* spellProto = (*i)->GetSpellProto(); + + // Max Amount can be absorbed by this aura + int32 currentAbsorb = mod->m_amount; + + // Found empty aura (umpossible but..) + if (currentAbsorb <=0) { - if (((Player*)pVictim)->HasSpellCooldown(31231)) - continue; - if (pVictim->GetHealth() <= RemainingDamage) + existExpired = true; + continue; + } + // Handle custom absorb auras + // TODO: try find better way + switch(spellProto->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: { - int32 chance = (*i)->GetModifier()->m_amount; - if (roll_chance_i(chance)) + // Astral Shift + if (spellProto->SpellIconID == 3066) { - 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; + //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; } - continue; - } - - int32 currentAbsorb; - - // Reflective Shield - if ((pVictim != this) && (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST && (*i)->GetSpellProto()->SpellFamilyFlags == 0x1) - { - if(Unit* caster = (*i)->GetCaster()) + case SPELLFAMILY_DRUID: { - AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_DUMMY); - for(AuraList::const_iterator k = vOverRideCS.begin(); k != vOverRideCS.end(); ++k) + // Primal Tenacity + if (spellProto->SpellIconID == 2253) { - switch((*k)->GetModifier()->m_miscvalue) + //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) + 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, ®en, 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); @@ -5001,6 +5149,13 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu pVictim->CastCustomSpell(pVictim,34919,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); return true; // no hidden cooldown } + // Divine Aegis + if (dummySpell->SpellIconID == 2820) + { + basepoints0 = damage * triggeredByAura->GetModifier()->m_amount/100; + triggered_spell_id = 47753; + break; + } switch(dummySpell->Id) { // Vampiric Embrace @@ -6305,6 +6460,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: { @@ -6341,7 +6506,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB return true; } -bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown) +bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown) { int32 scriptId = triggeredByAura->GetModifier()->m_miscvalue; @@ -6408,6 +6573,16 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAur case 5497: // Improved Mana Gems (Serpent-Coil Braid) triggered_spell_id = 37445; // Mana Surge break; + case 8152: // Serendipity + { + // if heal your target over maximum health + if (pVictim->GetHealth() + damage < pVictim->GetMaxHealth()) + return false; + int32 cost = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100; + int32 basepoints0 = cost * triggeredByAura->GetModifier()->m_amount/100; + CastCustomSpell(this, 47762, &basepoints0, 0, 0, true, 0, triggeredByAura); + return true; + } } // not processed @@ -9973,7 +10148,6 @@ bool InitTriggerAuraData() isTriggerAura[i]=false; isNonTriggerAura[i] = false; } - isTriggerAura[SPELL_AURA_PERIODIC_DAMAGE] = true; isTriggerAura[SPELL_AURA_DUMMY] = true; isTriggerAura[SPELL_AURA_MOD_CONFUSE] = true; isTriggerAura[SPELL_AURA_MOD_THREAT] = true; @@ -10209,7 +10383,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS: { sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); - if (!HandleOverrideClassScriptAuraProc(pTarget, triggeredByAura, procSpell, cooldown)) + if (!HandleOverrideClassScriptAuraProc(pTarget, damage, triggeredByAura, procSpell, cooldown)) continue; break; } |