diff options
author | ariel- <ariel-@users.noreply.github.com> | 2017-12-21 02:25:04 -0300 |
---|---|---|
committer | ariel- <ariel-@users.noreply.github.com> | 2017-12-21 02:25:04 -0300 |
commit | 5e2c5a52cd8a4ce12e189034df66b42d0d0b2c01 (patch) | |
tree | a0813c95b83f4820c9310a3c7f37962ca32f1b76 /src | |
parent | bd12f481d5d2a5fd12f875aef510ec9f577d597d (diff) |
Core/Spell: implement SPELL_FAILED_AURA_BOUNCED on DR spells
Closes #13695
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 61 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 5 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 50 |
4 files changed, 73 insertions, 44 deletions
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 3d4d7191bf1..e39e1e13311 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -96,6 +96,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma bool CanSwim() const override { return (GetCreatureTemplate()->InhabitType & INHABIT_WATER) != 0 || IsPet(); } bool CanFly() const override { return (GetCreatureTemplate()->InhabitType & INHABIT_AIR) != 0; } bool IsDungeonBoss() const { return (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_DUNGEON_BOSS) != 0; } + bool IsAffectedByDiminishingReturns() const override { return Unit::IsAffectedByDiminishingReturns() || (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_ALL_DIMINISH) != 0; } void SetReactState(ReactStates st) { m_reactState = st; } ReactStates GetReactState() const { return m_reactState; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 995714ae2e7..1f0b9d04368 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -4737,17 +4737,6 @@ bool Unit::HasNegativeAuraWithInterruptFlag(uint32 flag, ObjectGuid guid) const return false; } -bool Unit::HasNegativeAuraWithAttribute(uint32 flag, ObjectGuid guid) const -{ - for (AuraApplicationMap::const_iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end(); ++iter) - { - Aura const* aura = iter->second->GetBase(); - if (!iter->second->IsPositive() && aura->GetSpellInfo()->Attributes & flag && (!guid || aura->GetCasterGUID() == guid)) - return true; - } - return false; -} - bool Unit::HasAuraWithMechanic(uint32 mechanicMask) const { for (AuraApplicationMap::const_iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end(); ++iter) @@ -4765,6 +4754,26 @@ bool Unit::HasAuraWithMechanic(uint32 mechanicMask) const return false; } +bool Unit::HasStrongerAuraWithDR(SpellInfo const* auraSpellInfo, Unit* caster, bool triggered) const +{ + DiminishingGroup diminishGroup = auraSpellInfo->GetDiminishingReturnsGroupForSpell(triggered); + DiminishingLevels level = GetDiminishing(diminishGroup); + for (auto itr = m_appliedAuras.begin(); itr != m_appliedAuras.end(); ++itr) + { + SpellInfo const* spellInfo = itr->second->GetBase()->GetSpellInfo(); + if (spellInfo->GetDiminishingReturnsGroupForSpell(triggered) != diminishGroup) + continue; + + int32 existingDuration = itr->second->GetBase()->GetMaxDuration(); + int32 newDuration = auraSpellInfo->GetMaxDuration(); + ApplyDiminishingToDuration(auraSpellInfo, triggered, newDuration, caster, level); + if (newDuration > 0 && newDuration < existingDuration) + return true; + } + + return false; +} + AuraEffect* Unit::IsScriptOverriden(SpellInfo const* spell, int32 script) const { AuraEffectList const& auras = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); @@ -9908,31 +9917,28 @@ void Unit::ModSpellDurationTime(SpellInfo const* spellInfo, int32 & duration, Sp duration = int32(float(duration) * m_modAttackSpeedPct[RANGED_ATTACK]); } -DiminishingLevels Unit::GetDiminishing(DiminishingGroup group) +DiminishingLevels Unit::GetDiminishing(DiminishingGroup group) const { - DiminishingReturn& diminish = m_Diminishing[group]; + DiminishingReturn const& diminish = m_Diminishing[group]; if (!diminish.hitCount) return DIMINISHING_LEVEL_1; - // If last spell was cast more than 15 seconds ago - reset the count. + // If last spell was cast more than 15 seconds ago - reset level if (!diminish.stack && GetMSTimeDiffToNow(diminish.hitTime) > 15000) - { - diminish.hitCount = DIMINISHING_LEVEL_1; return DIMINISHING_LEVEL_1; - } return DiminishingLevels(diminish.hitCount); } void Unit::IncrDiminishing(SpellInfo const* auraSpellInfo, bool triggered) { - DiminishingGroup const group = auraSpellInfo->GetDiminishingReturnsGroupForSpell(triggered); - DiminishingLevels const maxLevel = auraSpellInfo->GetDiminishingReturnsMaxLevel(triggered); + DiminishingGroup group = auraSpellInfo->GetDiminishingReturnsGroupForSpell(triggered); + uint32 currentLevel = GetDiminishing(group); + uint32 const maxLevel = auraSpellInfo->GetDiminishingReturnsMaxLevel(triggered); - // Checking for existing in the table DiminishingReturn& diminish = m_Diminishing[group]; - if (static_cast<int32>(diminish.hitCount) < maxLevel) - ++diminish.hitCount; + if (currentLevel < maxLevel) + diminish.hitCount = currentLevel + 1; } bool Unit::ApplyDiminishingToDuration(SpellInfo const* auraSpellInfo, bool triggered, int32& duration, Unit* caster, DiminishingLevels previousLevel) const @@ -9953,9 +9959,7 @@ bool Unit::ApplyDiminishingToDuration(SpellInfo const* auraSpellInfo, bool trigg Unit const* target = targetOwner ? targetOwner : this; Unit const* source = casterOwner ? casterOwner : caster; - if ((target->GetTypeId() == TYPEID_PLAYER - || target->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_ALL_DIMINISH) - && source->GetTypeId() == TYPEID_PLAYER) + if (target->IsAffectedByDiminishingReturns() && source->GetTypeId() == TYPEID_PLAYER) duration = limitDuration; } @@ -9977,10 +9981,9 @@ bool Unit::ApplyDiminishingToDuration(SpellInfo const* auraSpellInfo, bool trigg } } // Some diminishings applies to mobs too (for example, Stun) - else if ((auraSpellInfo->GetDiminishingReturnsGroupType(triggered) == DRTYPE_PLAYER - && ((targetOwner ? (targetOwner->GetTypeId() == TYPEID_PLAYER) : (GetTypeId() == TYPEID_PLAYER)) - || (GetTypeId() == TYPEID_UNIT && ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_ALL_DIMINISH))) - || auraSpellInfo->GetDiminishingReturnsGroupType(triggered) == DRTYPE_ALL) + else if (auraSpellInfo->GetDiminishingReturnsGroupType(triggered) == DRTYPE_ALL || + (auraSpellInfo->GetDiminishingReturnsGroupType(triggered) == DRTYPE_PLAYER && + (targetOwner ? targetOwner->IsAffectedByDiminishingReturns() : IsAffectedByDiminishingReturns()))) { DiminishingLevels diminish = previousLevel; switch (diminish) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index fcce38c092f..af0676ad2af 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -977,7 +977,8 @@ class TC_GAME_API Unit : public WorldObject void CleanupBeforeRemoveFromMap(bool finalCleanup); void CleanupsBeforeDelete(bool finalCleanup = true) override; // used in ~Creature/~Player (or before mass creature delete to remove cross-references to already deleted units) - DiminishingLevels GetDiminishing(DiminishingGroup group); + virtual bool IsAffectedByDiminishingReturns() const { return (GetCharmerOrOwnerPlayerOrPlayerItself() != nullptr); } + DiminishingLevels GetDiminishing(DiminishingGroup group) const; void IncrDiminishing(SpellInfo const* auraSpellInfo, bool triggered); bool ApplyDiminishingToDuration(SpellInfo const* auraSpellInfo, bool triggered, int32& duration, Unit* caster, DiminishingLevels previousLevel) const; void ApplyDiminishingAura(DiminishingGroup group, bool apply); @@ -1525,8 +1526,8 @@ class TC_GAME_API Unit : public WorldObject bool HasAuraTypeWithAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const; bool HasAuraTypeWithValue(AuraType auratype, int32 value) const; bool HasNegativeAuraWithInterruptFlag(uint32 flag, ObjectGuid guid = ObjectGuid::Empty) const; - bool HasNegativeAuraWithAttribute(uint32 flag, ObjectGuid guid = ObjectGuid::Empty) const; bool HasAuraWithMechanic(uint32 mechanicMask) const; + bool HasStrongerAuraWithDR(SpellInfo const* auraSpellInfo, Unit* caster, bool triggered) const; AuraEffect* IsScriptOverriden(SpellInfo const* spell, int32 script) const; uint32 GetDiseasesByCaster(ObjectGuid casterGUID, bool remove = false); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 020cf8efb8b..1418f7cff4c 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2603,9 +2603,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA diminishLevel = unit->GetDiminishing(diminishGroup); DiminishingReturnsType type = m_spellInfo->GetDiminishingReturnsGroupType(triggered); // Increase Diminishing on unit, current informations for actually casts will use values above - if ((type == DRTYPE_PLAYER && - (unit->GetCharmerOrOwnerPlayerOrPlayerItself() || (unit->GetTypeId() == TYPEID_UNIT && unit->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_ALL_DIMINISH))) || - type == DRTYPE_ALL) + if (type == DRTYPE_ALL || (type == DRTYPE_PLAYER && unit->IsAffectedByDiminishingReturns())) unit->IncrDiminishing(m_spellInfo, triggered); } @@ -3179,11 +3177,9 @@ void Spell::_cast(bool skipCheck) // skip check if done already (for instant cast spells for example) if (!skipCheck) { - uint32 param1 = 0, param2 = 0; - SpellCastResult castResult = CheckCast(false, ¶m1, ¶m2); - if (castResult != SPELL_CAST_OK) + auto cleanupSpell = [this, modOwner](SpellCastResult res, uint32* p1 = nullptr, uint32* p2 = nullptr) { - SendCastResult(castResult, ¶m1, ¶m2); + SendCastResult(res, p1, p2); SendInterrupted(0); if (modOwner) @@ -3191,6 +3187,13 @@ void Spell::_cast(bool skipCheck) finish(false); SetExecutedCurrently(false); + }; + + uint32 param1 = 0, param2 = 0; + SpellCastResult castResult = CheckCast(false, ¶m1, ¶m2); + if (castResult != SPELL_CAST_OK) + { + cleanupSpell(castResult, ¶m1, ¶m2); return; } @@ -3206,14 +3209,35 @@ void Spell::_cast(bool skipCheck) { // Spell will be cast after completing the trade. Silently ignore at this place my_trade->SetSpell(m_spellInfo->Id, m_CastItem); - SendCastResult(SPELL_FAILED_DONT_REPORT); - SendInterrupted(0); + cleanupSpell(SPELL_FAILED_DONT_REPORT); + return; + } + } + } + } - modOwner->SetSpellModTakingSpell(this, false); + // check diminishing returns (again, only after finish cast bar, tested on retail) + if (Unit* target = m_targets.GetUnitTarget()) + { + uint8 aura_effmask = 0; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + if (m_spellInfo->Effects[i].IsUnitOwnedAuraEffect()) + aura_effmask |= 1 << i; - finish(false); - SetExecutedCurrently(false); - return; + if (aura_effmask) + { + bool const triggered = m_triggeredByAuraSpell != nullptr; + if (DiminishingGroup diminishGroup = m_spellInfo->GetDiminishingReturnsGroupForSpell(triggered)) + { + DiminishingReturnsType type = m_spellInfo->GetDiminishingReturnsGroupType(triggered); + if (type == DRTYPE_ALL || (type == DRTYPE_PLAYER && target->IsAffectedByDiminishingReturns())) + { + Unit* caster = m_originalCaster ? m_originalCaster : m_caster; + if (target->HasStrongerAuraWithDR(m_spellInfo, caster, triggered)) + { + cleanupSpell(SPELL_FAILED_AURA_BOUNCED); + return; + } } } } |