diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 99 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 24 | ||||
| -rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 4 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 27 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.h | 4 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 333 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellInfo.h | 419 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 311 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellMgr.h | 8 | ||||
| -rw-r--r-- | src/server/game/World/World.cpp | 3 | 
10 files changed, 648 insertions, 584 deletions
| diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 95f16a88c80..370600861ef 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9756,63 +9756,56 @@ void Unit::ModSpellDurationTime(SpellInfo const* spellInfo, int32 & duration, Sp  DiminishingLevels Unit::GetDiminishing(DiminishingGroup group)  { -    for (Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) -    { -        if (i->DRGroup != group) -            continue; - -        if (!i->hitCount) -            return DIMINISHING_LEVEL_1; +    DiminishingReturn& diminish = m_Diminishing[group]; +    if (!diminish.hitCount) +        return DIMINISHING_LEVEL_1; -        if (!i->hitTime) -            return DIMINISHING_LEVEL_1; +    if (!diminish.hitTime) +        return DIMINISHING_LEVEL_1; -        // If last spell was cast more than 15 seconds ago - reset the count. -        if (i->stack == 0 && getMSTimeDiff(i->hitTime, getMSTime()) > 15000) -        { -            i->hitCount = DIMINISHING_LEVEL_1; -            return DIMINISHING_LEVEL_1; -        } -        // or else increase the count. -        else -            return DiminishingLevels(i->hitCount); +    // If last spell was cast more than 15 seconds ago - reset the count. +    if (!diminish.stack && GetMSTimeDiffToNow(diminish.hitTime) > 15000) +    { +        diminish.hitCount = DIMINISHING_LEVEL_1; +        return DIMINISHING_LEVEL_1;      } -    return DIMINISHING_LEVEL_1; + +    return DiminishingLevels(diminish.hitCount);  } -void Unit::IncrDiminishing(DiminishingGroup group) +void Unit::IncrDiminishing(SpellInfo const* auraSpellInfo, bool triggered)  { +    DiminishingGroup const group = auraSpellInfo->GetDiminishingReturnsGroupForSpell(triggered); +    DiminishingLevels const maxLevel = auraSpellInfo->GetDiminishingReturnsMaxLevel(triggered); +      // Checking for existing in the table -    for (Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) -    { -        if (i->DRGroup != group) -            continue; -        if (int32(i->hitCount) < GetDiminishingReturnsMaxLevel(group)) -            i->hitCount += 1; -        return; -    } -    m_Diminishing.push_back(DiminishingReturn(group, getMSTime(), DIMINISHING_LEVEL_2)); +    DiminishingReturn& diminish = m_Diminishing[group]; +    if (static_cast<int32>(diminish.hitCount) < maxLevel) +        ++diminish.hitCount;  } -float Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, Unit* caster, DiminishingLevels Level, int32 limitduration) +float Unit::ApplyDiminishingToDuration(SpellInfo const* auraSpellInfo, bool triggered, int32& duration, Unit* caster, DiminishingLevels previousLevel)  { +    DiminishingGroup const group = auraSpellInfo->GetDiminishingReturnsGroupForSpell(triggered);      if (duration == -1 || group == DIMINISHING_NONE)          return 1.0f; +    int32 const limitDuration = auraSpellInfo->GetDiminishingReturnsLimitDuration(triggered); +      // test pet/charm masters instead pets/charmeds -    Unit const* tarGetOwner = GetCharmerOrOwner(); +    Unit const* targetOwner = GetCharmerOrOwner();      Unit const* casterOwner = caster->GetCharmerOrOwner();      // Duration of crowd control abilities on pvp target is limited by 10 sec. (2.2.0) -    if (limitduration > 0 && duration > limitduration) +    if (limitDuration > 0 && duration > limitDuration)      { -        Unit const* target = tarGetOwner ? tarGetOwner : this; +        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) -            duration = limitduration; +            duration = limitDuration;      }      float mod = 1.0f; @@ -9821,7 +9814,7 @@ float Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,      {          if (GetTypeId() == TYPEID_UNIT && (ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_TAUNT_DIMINISH))          { -            DiminishingLevels diminish = Level; +            DiminishingLevels diminish = previousLevel;              switch (diminish)              {                  case DIMINISHING_LEVEL_1: break; @@ -9834,12 +9827,12 @@ float Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,          }      }      // Some diminishings applies to mobs too (for example, Stun) -    else if ((GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER -        && ((tarGetOwner ? (tarGetOwner->GetTypeId() == TYPEID_PLAYER) : (GetTypeId() == TYPEID_PLAYER)) +    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))) -        || GetDiminishingReturnsGroupType(group) == DRTYPE_ALL) +        || auraSpellInfo->GetDiminishingReturnsGroupType(triggered) == DRTYPE_ALL)      { -        DiminishingLevels diminish = Level; +        DiminishingLevels diminish = previousLevel;          switch (diminish)          {              case DIMINISHING_LEVEL_1: break; @@ -9857,24 +9850,26 @@ float Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,  void Unit::ApplyDiminishingAura(DiminishingGroup group, bool apply)  {      // Checking for existing in the table -    for (Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) +    DiminishingReturn& diminish = m_Diminishing[group]; + +    if (apply) +        ++diminish.stack; +    else if (diminish.stack)      { -        if (i->DRGroup != group) -            continue; +        --diminish.stack; -        if (apply) -            i->stack += 1; -        else if (i->stack) -        { -            i->stack -= 1; -            // Remember time after last aura from group removed -            if (i->stack == 0) -                i->hitTime = getMSTime(); -        } -        break; +        // Remember time after last aura from group removed +        if (!diminish.stack) +            diminish.hitTime = getMSTime();      }  } +void Unit::ClearDiminishings() +{ +    for (uint32 i = 0; i < DIMINISHING_MAX; ++i) +        m_Diminishing[i].Clear(); +} +  float Unit::GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const  {      if (!spellInfo->RangeEntry) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 06aa2db8e0b..92c9554800a 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -802,11 +802,15 @@ namespace Movement{  struct DiminishingReturn  { -    DiminishingReturn(DiminishingGroup group, uint32 t, uint32 count) -        : DRGroup(group), stack(0), hitTime(t), hitCount(count) -    { } +    DiminishingReturn() : stack(0), hitTime(0), hitCount(DIMINISHING_LEVEL_1) { } + +    void Clear() +    { +        stack = 0; +        hitTime = 0; +        hitCount = DIMINISHING_LEVEL_1; +    } -    DiminishingGroup        DRGroup;      uint16                  stack;      uint32                  hitTime;      uint32                  hitCount; @@ -1256,7 +1260,7 @@ class TC_GAME_API Unit : public WorldObject          typedef std::list<AuraEffect*> AuraEffectList;          typedef std::list<Aura*> AuraList;          typedef std::list<AuraApplication *> AuraApplicationList; -        typedef std::list<DiminishingReturn> Diminishing; +        typedef std::array<DiminishingReturn, DIMINISHING_MAX> Diminishing;          typedef std::deque<std::pair<uint8 /*procEffectMask*/, AuraApplication*>> AuraApplicationProcContainer; @@ -1273,11 +1277,11 @@ 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); -        void IncrDiminishing(DiminishingGroup group); -        float ApplyDiminishingToDuration(DiminishingGroup  group, int32 &duration, Unit* caster, DiminishingLevels Level, int32 limitduration); -        void ApplyDiminishingAura(DiminishingGroup  group, bool apply); -        void ClearDiminishings() { m_Diminishing.clear(); } +        DiminishingLevels GetDiminishing(DiminishingGroup group); +        void IncrDiminishing(SpellInfo const* auraSpellInfo, bool triggered); +        float ApplyDiminishingToDuration(SpellInfo const* auraSpellInfo, bool triggered, int32& duration, Unit* caster, DiminishingLevels previousLevel); +        void ApplyDiminishingAura(DiminishingGroup group, bool apply); +        void ClearDiminishings();          // target dependent range checks          float GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const; diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index f7c440ce8bc..ce0c749c294 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -3136,7 +3136,9 @@ enum DiminishingGroup : uint16      DIMINISHING_SLEEP               = 17,      DIMINISHING_TAUNT               = 18,      DIMINISHING_LIMITONLY           = 19, -    DIMINISHING_DRAGONS_BREATH      = 20 +    DIMINISHING_DRAGONS_BREATH      = 20, + +    DIMINISHING_MAX  };  enum SummonCategory diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 22456c90d7f..3e7783cfc62 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -586,8 +586,6 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO      destTarget = NULL;      damage = 0;      effectHandleMode = SPELL_EFFECT_HANDLE_LAUNCH; -    m_diminishLevel = DIMINISHING_LEVEL_1; -    m_diminishGroup = DIMINISHING_NONE;      m_damage = 0;      m_healing = 0;      m_procAttacker = 0; @@ -2588,16 +2586,19 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA              aura_effmask |= 1 << i;      // Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add -    m_diminishGroup = GetDiminishingReturnsGroupForSpell(m_spellInfo, m_triggeredByAuraSpell != nullptr); -    if (m_diminishGroup && aura_effmask) +    bool const triggered = m_triggeredByAuraSpell != nullptr; +    DiminishingGroup const diminishGroup = m_spellInfo->GetDiminishingReturnsGroupForSpell(triggered); + +    DiminishingLevels diminishLevel = DIMINISHING_LEVEL_1; +    if (diminishGroup && aura_effmask)      { -        m_diminishLevel = unit->GetDiminishing(m_diminishGroup); -        DiminishingReturnsType type = GetDiminishingReturnsGroupType(m_diminishGroup); +        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) -            unit->IncrDiminishing(m_diminishGroup); +            unit->IncrDiminishing(m_spellInfo, triggered);      }      if (aura_effmask) @@ -2640,8 +2641,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA                  // Now Reduce spell duration using data received at spell hit                  int32 duration = m_spellAura->GetMaxDuration(); -                int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup, aurSpellInfo); -                float diminishMod = unit->ApplyDiminishingToDuration(m_diminishGroup, duration, m_originalCaster, m_diminishLevel, limitduration); +                float diminishMod = unit->ApplyDiminishingToDuration(aurSpellInfo, triggered, duration, m_originalCaster, diminishLevel);                  // unit is immune to aura if it was diminished to 0 duration                  if (diminishMod == 0.0f) @@ -2656,7 +2656,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA                  }                  else                  { -                    ((UnitAura*)m_spellAura)->SetDiminishGroup(m_diminishGroup); +                    ((UnitAura*)m_spellAura)->SetDiminishGroup(diminishGroup);                      bool positive = m_spellAura->GetSpellInfo()->IsPositive();                      if (AuraApplication* aurApp = m_spellAura->GetApplicationOfTarget(m_originalCaster->GetGUID())) @@ -3457,9 +3457,6 @@ uint64 Spell::handle_delayed(uint64 t_offset)  void Spell::_handle_immediate_phase()  {      m_spellAura = NULL; -    // initialize Diminishing Returns Data -    m_diminishLevel = DIMINISHING_LEVEL_1; -    m_diminishGroup = DIMINISHING_NONE;      // handle some immediate features of the spell here      HandleThreatSpells(); @@ -4692,7 +4689,7 @@ void Spell::HandleThreatSpells()              continue;          // positive spells distribute threat among all units that are in combat with target, like healing -        if (m_spellInfo->_IsPositiveSpell()) +        if (m_spellInfo->IsPositive())              target->getHostileRefManager().threatAssist(m_caster, threatToAdd, m_spellInfo);          // for negative spells threat gets distributed among affected targets          else @@ -4703,7 +4700,7 @@ void Spell::HandleThreatSpells()              target->AddThreat(m_caster, threatToAdd, m_spellInfo->GetSchoolMask(), m_spellInfo);          }      } -    TC_LOG_DEBUG("spells", "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, m_spellInfo->_IsPositiveSpell() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size())); +    TC_LOG_DEBUG("spells", "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, m_spellInfo->IsPositive() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size()));  }  void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode) diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 5823ea72dbd..5087ececa09 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -561,10 +561,6 @@ class TC_GAME_API Spell          // used in effects handlers          Aura* m_spellAura; -        // this is set in Spell Hit, but used in Apply Aura handler -        DiminishingLevels m_diminishLevel; -        DiminishingGroup m_diminishGroup; -          // -------------------------------------------          GameObject* focusObject; diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index ff5cd925c8c..8589a8bc98e 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -2108,6 +2108,339 @@ void SpellInfo::_LoadSpellSpecific()      }();  } +void SpellInfo::_LoadSpellDiminishInfo() +{ +    auto diminishingGroupCompute = [this](bool triggered) -> DiminishingGroup +    { +        if (IsPositive()) +            return DIMINISHING_NONE; + +        for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) +        { +            if (Effects[i].ApplyAuraName == SPELL_AURA_MOD_TAUNT) +                return DIMINISHING_TAUNT; +        } + +        // Explicit Diminishing Groups +        switch (SpellFamilyName) +        { +            case SPELLFAMILY_GENERIC: +            { +                // Pet charge effects (Infernal Awakening, Demon Charge) +                if (SpellVisual[0] == 2816 && SpellIconID == 15) +                    return DIMINISHING_CONTROLLED_STUN; +                // Frost Tomb +                else if (Id == 48400) +                    return DIMINISHING_NONE; +                // Gnaw +                else if (Id == 47481) +                    return DIMINISHING_CONTROLLED_STUN; +                // ToC Icehowl Arctic Breath +                else if (SpellVisual[0] == 14153) +                    return DIMINISHING_NONE; +                // Black Plague +                else if (Id == 64155) +                    return DIMINISHING_NONE; +                // Screams of the Dead (King Ymiron) +                else if (Id == 51750) +                    return DIMINISHING_NONE; +                break; +            } +            // Event spells +            case SPELLFAMILY_UNK1: +                return DIMINISHING_NONE; +            case SPELLFAMILY_MAGE: +            { +                // Frostbite +                if (SpellFamilyFlags[1] & 0x80000000) +                    return DIMINISHING_ROOT; +                // Shattered Barrier +                else if (SpellVisual[0] == 12297) +                    return DIMINISHING_ROOT; +                // Deep Freeze +                else if (SpellIconID == 2939 && SpellVisual[0] == 9963) +                    return DIMINISHING_CONTROLLED_STUN; +                // Frost Nova / Freeze (Water Elemental) +                else if (SpellIconID == 193) +                    return DIMINISHING_CONTROLLED_ROOT; +                // Dragon's Breath +                else if (SpellFamilyFlags[0] & 0x800000) +                    return DIMINISHING_DRAGONS_BREATH; +                break; +            } +            case SPELLFAMILY_WARRIOR: +            { +                // Hamstring - limit duration to 10s in PvP +                if (SpellFamilyFlags[0] & 0x2) +                    return DIMINISHING_LIMITONLY; +                // Charge Stun (own diminishing) +                else if (SpellFamilyFlags[0] & 0x01000000) +                    return DIMINISHING_CHARGE; +                break; +            } +            case SPELLFAMILY_WARLOCK: +            { +                // Curses/etc +                if ((SpellFamilyFlags[0] & 0x80000000) || (SpellFamilyFlags[1] & 0x200)) +                    return DIMINISHING_LIMITONLY; +                // Seduction +                else if (SpellFamilyFlags[1] & 0x10000000) +                    return DIMINISHING_FEAR; +                break; +            } +            case SPELLFAMILY_DRUID: +            { +                // Pounce +                if (SpellFamilyFlags[0] & 0x20000) +                    return DIMINISHING_OPENING_STUN; +                // Cyclone +                else if (SpellFamilyFlags[1] & 0x20) +                    return DIMINISHING_CYCLONE; +                // Entangling Roots +                // Nature's Grasp +                else if (SpellFamilyFlags[0] & 0x00000200) +                    return DIMINISHING_CONTROLLED_ROOT; +                // Faerie Fire +                else if (SpellFamilyFlags[0] & 0x400) +                    return DIMINISHING_LIMITONLY; +                break; +            } +            case SPELLFAMILY_ROGUE: +            { +                // Gouge +                if (SpellFamilyFlags[0] & 0x8) +                    return DIMINISHING_DISORIENT; +                // Blind +                else if (SpellFamilyFlags[0] & 0x1000000) +                    return DIMINISHING_FEAR; +                // Cheap Shot +                else if (SpellFamilyFlags[0] & 0x400) +                    return DIMINISHING_OPENING_STUN; +                // Crippling poison - Limit to 10 seconds in PvP (No SpellFamilyFlags) +                else if (SpellIconID == 163) +                    return DIMINISHING_LIMITONLY; +                break; +            } +            case SPELLFAMILY_HUNTER: +            { +                // Hunter's Mark +                if ((SpellFamilyFlags[0] & 0x400) && SpellIconID == 538) +                    return DIMINISHING_LIMITONLY; +                // Scatter Shot (own diminishing) +                else if ((SpellFamilyFlags[0] & 0x40000) && SpellIconID == 132) +                    return DIMINISHING_SCATTER_SHOT; +                // Entrapment (own diminishing) +                else if (SpellVisual[0] == 7484 && SpellIconID == 20) +                    return DIMINISHING_ENTRAPMENT; +                // Wyvern Sting mechanic is MECHANIC_SLEEP but the diminishing is DIMINISHING_DISORIENT +                else if ((SpellFamilyFlags[1] & 0x1000) && SpellIconID == 1721) +                    return DIMINISHING_DISORIENT; +                // Freezing Arrow +                else if (SpellFamilyFlags[0] & 0x8) +                    return DIMINISHING_DISORIENT; +                break; +            } +            case SPELLFAMILY_PALADIN: +            { +                // Judgement of Justice - limit duration to 10s in PvP +                if (SpellFamilyFlags[0] & 0x100000) +                    return DIMINISHING_LIMITONLY; +                // Turn Evil +                else if ((SpellFamilyFlags[1] & 0x804000) && SpellIconID == 309) +                    return DIMINISHING_FEAR; +                break; +            } +            case SPELLFAMILY_SHAMAN: +            { +                // Storm, Earth and Fire - Earthgrab +                if (SpellFamilyFlags[2] & 0x4000) +                    return DIMINISHING_NONE; +                break; +            } +            case SPELLFAMILY_DEATHKNIGHT: +            { +                // Hungering Cold (no flags) +                if (SpellIconID == 2797) +                    return DIMINISHING_DISORIENT; +                // Mark of Blood +                else if ((SpellFamilyFlags[0] & 0x10000000) && SpellIconID == 2285) +                    return DIMINISHING_LIMITONLY; +                break; +            } +            default: +                break; +        } + +        // Lastly - Set diminishing depending on mechanic +        uint32 mechanic = GetAllEffectsMechanicMask(); +        if (mechanic & (1 << MECHANIC_CHARM)) +            return DIMINISHING_MIND_CONTROL; +        if (mechanic & (1 << MECHANIC_SILENCE)) +            return DIMINISHING_SILENCE; +        if (mechanic & (1 << MECHANIC_SLEEP)) +            return DIMINISHING_SLEEP; +        if (mechanic & ((1 << MECHANIC_SAPPED) | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_SHACKLE))) +            return DIMINISHING_DISORIENT; +        // Mechanic Knockout, except Blast Wave +        if (mechanic & (1 << MECHANIC_KNOCKOUT) && SpellIconID != 292) +            return DIMINISHING_DISORIENT; +        if (mechanic & (1 << MECHANIC_DISARM)) +            return DIMINISHING_DISARM; +        if (mechanic & (1 << MECHANIC_FEAR)) +            return DIMINISHING_FEAR; +        if (mechanic & (1 << MECHANIC_STUN)) +            return triggered ? DIMINISHING_STUN : DIMINISHING_CONTROLLED_STUN; +        if (mechanic & (1 << MECHANIC_BANISH)) +            return DIMINISHING_BANISH; +        if (mechanic & (1 << MECHANIC_ROOT)) +            return triggered ? DIMINISHING_ROOT : DIMINISHING_CONTROLLED_ROOT; +        if (mechanic & (1 << MECHANIC_HORROR)) +            return DIMINISHING_HORROR; + +        return DIMINISHING_NONE; +    }; + +    auto diminishingTypeCompute = [](DiminishingGroup group) -> DiminishingReturnsType +    { +        switch (group) +        { +            case DIMINISHING_TAUNT: +            case DIMINISHING_CONTROLLED_STUN: +            case DIMINISHING_STUN: +            case DIMINISHING_OPENING_STUN: +            case DIMINISHING_CYCLONE: +            case DIMINISHING_CHARGE: +                return DRTYPE_ALL; +            case DIMINISHING_LIMITONLY: +            case DIMINISHING_NONE: +                return DRTYPE_NONE; +            default: +                return DRTYPE_PLAYER; +        } +    }; + +    auto diminishingMaxLevelCompute = [](DiminishingGroup group) -> DiminishingLevels +    { +        switch (group) +        { +            case DIMINISHING_TAUNT: +                return DIMINISHING_LEVEL_TAUNT_IMMUNE; +            default: +                return DIMINISHING_LEVEL_IMMUNE; +        } +    }; + +    auto diminishingLimitDurationCompute = [this](DiminishingGroup group) -> int32 +    { +        auto isGroupDurationLimited = [group]() -> bool +        { +            switch (group) +            { +                case DIMINISHING_BANISH: +                case DIMINISHING_CONTROLLED_STUN: +                case DIMINISHING_CONTROLLED_ROOT: +                case DIMINISHING_CYCLONE: +                case DIMINISHING_DISORIENT: +                case DIMINISHING_ENTRAPMENT: +                case DIMINISHING_FEAR: +                case DIMINISHING_HORROR: +                case DIMINISHING_MIND_CONTROL: +                case DIMINISHING_OPENING_STUN: +                case DIMINISHING_ROOT: +                case DIMINISHING_STUN: +                case DIMINISHING_SLEEP: +                case DIMINISHING_LIMITONLY: +                    return true; +                default: +                    return false; +            } +        }; + +        if (!isGroupDurationLimited()) +            return 0; + +        // Explicit diminishing duration +        switch (SpellFamilyName) +        { +            case SPELLFAMILY_DRUID: +            { +                // Faerie Fire - limit to 40 seconds in PvP (3.1) +                if (SpellFamilyFlags[0] & 0x400) +                    return 40 * IN_MILLISECONDS; +                break; +            } +            case SPELLFAMILY_HUNTER: +            { +                // Wyvern Sting +                if (SpellFamilyFlags[1] & 0x1000) +                    return 6 * IN_MILLISECONDS; +                // Hunter's Mark +                if (SpellFamilyFlags[0] & 0x400) +                    return 120 * IN_MILLISECONDS; +                break; +            } +            case SPELLFAMILY_PALADIN: +            { +                // Repentance - limit to 6 seconds in PvP +                if (SpellFamilyFlags[0] & 0x4) +                    return 6 * IN_MILLISECONDS; +                break; +            } +            case SPELLFAMILY_WARLOCK: +            { +                // Banish - limit to 6 seconds in PvP +                if (SpellFamilyFlags[1] & 0x8000000) +                    return 6 * IN_MILLISECONDS; +                // Curse of Tongues - limit to 12 seconds in PvP +                else if (SpellFamilyFlags[2] & 0x800) +                    return 12 * IN_MILLISECONDS; +                // Curse of Elements - limit to 120 seconds in PvP +                else if (SpellFamilyFlags[1] & 0x200) +                    return 120 * IN_MILLISECONDS; +                break; +            } +            default: +                break; +        } + +        return 10 * IN_MILLISECONDS; +    }; + +    SpellDiminishInfo triggeredInfo, normalInfo; +    triggeredInfo.DiminishGroup = diminishingGroupCompute(true); +    triggeredInfo.DiminishReturnType = diminishingTypeCompute(triggeredInfo.DiminishGroup); +    triggeredInfo.DiminishMaxLevel = diminishingMaxLevelCompute(triggeredInfo.DiminishGroup); +    triggeredInfo.DiminishDurationLimit = diminishingLimitDurationCompute(triggeredInfo.DiminishGroup); + +    normalInfo.DiminishGroup = diminishingGroupCompute(false); +    normalInfo.DiminishReturnType = diminishingTypeCompute(normalInfo.DiminishGroup); +    normalInfo.DiminishMaxLevel = diminishingMaxLevelCompute(normalInfo.DiminishGroup); +    normalInfo.DiminishDurationLimit = diminishingLimitDurationCompute(normalInfo.DiminishGroup); + +    _diminishInfoTriggered = triggeredInfo; +    _diminishInfoNonTriggered = normalInfo; +} + +DiminishingGroup SpellInfo::GetDiminishingReturnsGroupForSpell(bool triggered) const +{ +    return triggered ? _diminishInfoTriggered.DiminishGroup : _diminishInfoNonTriggered.DiminishGroup; +} + +DiminishingReturnsType SpellInfo::GetDiminishingReturnsGroupType(bool triggered) const +{ +    return triggered ? _diminishInfoTriggered.DiminishReturnType : _diminishInfoNonTriggered.DiminishReturnType; +} + +DiminishingLevels SpellInfo::GetDiminishingReturnsMaxLevel(bool triggered) const +{ +    return triggered ? _diminishInfoTriggered.DiminishMaxLevel : _diminishInfoNonTriggered.DiminishMaxLevel; +} + +int32 SpellInfo::GetDiminishingReturnsLimitDuration(bool triggered) const +{ +    return triggered ? _diminishInfoTriggered.DiminishDurationLimit : _diminishInfoNonTriggered.DiminishDurationLimit; +} +  float SpellInfo::GetMinRange(bool positive) const  {      if (!RangeEntry) diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 2f94555e493..b2566ecf533 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -28,6 +28,7 @@ class Unit;  class Player;  class Item;  class Spell; +class SpellMgr;  class SpellInfo;  struct SpellChainNode;  struct SpellTargetPosition; @@ -291,207 +292,227 @@ private:      static StaticData _data[TOTAL_SPELL_EFFECTS];  }; -class TC_GAME_API SpellInfo +struct TC_GAME_API SpellDiminishInfo  { -public: -    uint32 Id; -    SpellCategoryEntry const* CategoryEntry; -    uint32 Dispel; -    uint32 Mechanic; -    uint32 Attributes; -    uint32 AttributesEx; -    uint32 AttributesEx2; -    uint32 AttributesEx3; -    uint32 AttributesEx4; -    uint32 AttributesEx5; -    uint32 AttributesEx6; -    uint32 AttributesEx7; -    uint32 AttributesCu; -    uint64 Stances; -    uint64 StancesNot; -    uint32 Targets; -    uint32 TargetCreatureType; -    uint32 RequiresSpellFocus; -    uint32 FacingCasterFlags; -    uint32 CasterAuraState; -    uint32 TargetAuraState; -    uint32 CasterAuraStateNot; -    uint32 TargetAuraStateNot; -    uint32 CasterAuraSpell; -    uint32 TargetAuraSpell; -    uint32 ExcludeCasterAuraSpell; -    uint32 ExcludeTargetAuraSpell; -    SpellCastTimesEntry const* CastTimeEntry; -    uint32 RecoveryTime; -    uint32 CategoryRecoveryTime; -    uint32 StartRecoveryCategory; -    uint32 StartRecoveryTime; -    uint32 InterruptFlags; -    uint32 AuraInterruptFlags; -    uint32 ChannelInterruptFlags; -    uint32 ProcFlags; -    uint32 ProcChance; -    uint32 ProcCharges; -    uint32 MaxLevel; -    uint32 BaseLevel; -    uint32 SpellLevel; -    SpellDurationEntry const* DurationEntry; -    uint32 PowerType; -    uint32 ManaCost; -    uint32 ManaCostPerlevel; -    uint32 ManaPerSecond; -    uint32 ManaPerSecondPerLevel; -    uint32 ManaCostPercentage; -    uint32 RuneCostID; -    SpellRangeEntry const* RangeEntry; -    float  Speed; -    uint32 StackAmount; -    uint32 Totem[2]; -    int32  Reagent[MAX_SPELL_REAGENTS]; -    uint32 ReagentCount[MAX_SPELL_REAGENTS]; -    int32  EquippedItemClass; -    int32  EquippedItemSubClassMask; -    int32  EquippedItemInventoryTypeMask; -    uint32 TotemCategory[2]; -    uint32 SpellVisual[2]; -    uint32 SpellIconID; -    uint32 ActiveIconID; -    char* SpellName[16]; -    char* Rank[16]; -    uint32 MaxTargetLevel; -    uint32 MaxAffectedTargets; -    uint32 SpellFamilyName; -    flag96 SpellFamilyFlags; -    uint32 DmgClass; -    uint32 PreventionType; -    int32  AreaGroupId; -    uint32 SchoolMask; -    SpellEffectInfo Effects[MAX_SPELL_EFFECTS]; -    uint32 ExplicitTargetMask; -    SpellChainNode const* ChainEntry; - -    SpellInfo(SpellEntry const* spellEntry); -    ~SpellInfo(); - -    uint32 GetCategory() const; -    bool HasEffect(SpellEffects effect) const; -    bool HasAura(AuraType aura) const; -    bool HasAreaAuraEffect() const; - -    inline bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); } -    inline bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); } -    inline bool HasAttribute(SpellAttr2 attribute) const { return !!(AttributesEx2 & attribute); } -    inline bool HasAttribute(SpellAttr3 attribute) const { return !!(AttributesEx3 & attribute); } -    inline bool HasAttribute(SpellAttr4 attribute) const { return !!(AttributesEx4 & attribute); } -    inline bool HasAttribute(SpellAttr5 attribute) const { return !!(AttributesEx5 & attribute); } -    inline bool HasAttribute(SpellAttr6 attribute) const { return !!(AttributesEx6 & attribute); } -    inline bool HasAttribute(SpellAttr7 attribute) const { return !!(AttributesEx7 & attribute); } -    inline bool HasAttribute(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); } - -    bool IsExplicitDiscovery() const; -    bool IsLootCrafting() const; -    bool IsQuestTame() const; -    bool IsProfessionOrRiding() const; -    bool IsProfession() const; -    bool IsPrimaryProfession() const; -    bool IsPrimaryProfessionFirstRank() const; -    bool IsAbilityLearnedWithProfession() const; -    bool IsAbilityOfSkillType(uint32 skillType) const; - -    bool IsAffectingArea() const; -    bool IsTargetingArea() const; -    bool NeedsExplicitUnitTarget() const; -    bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const; - -    bool IsPassive() const; -    bool IsAutocastable() const; -    bool IsStackableWithRanks() const; -    bool IsPassiveStackableWithRanks() const; -    bool IsMultiSlotAura() const; -    bool IsStackableOnOneSlotWithDifferentCasters() const; -    bool IsCooldownStartedOnEvent() const; -    bool IsDeathPersistent() const; -    bool IsRequiringDeadTarget() const; -    bool IsAllowingDeadTarget() const; -    bool IsGroupBuff() const; -    bool CanBeUsedInCombat() const; -    bool IsPositive() const; -    bool IsPositiveEffect(uint8 effIndex) const; -    bool IsChanneled() const; -    bool NeedsComboPoints() const; -    bool IsBreakingStealth() const; -    bool IsRangedWeaponSpell() const; -    bool IsAutoRepeatRangedSpell() const; -    bool HasInitialAggro() const; - -    bool IsAffectedBySpellMods() const; -    bool IsAffectedBySpellMod(SpellModifier const* mod) const; - -    bool CanPierceImmuneAura(SpellInfo const* aura) const; -    bool CanDispelAura(SpellInfo const* aura) const; - -    bool IsSingleTarget() const; -    bool IsAuraExclusiveBySpecificWith(SpellInfo const* spellInfo) const; -    bool IsAuraExclusiveBySpecificPerCasterWith(SpellInfo const* spellInfo) const; - -    SpellCastResult CheckShapeshift(uint32 form) const; -    SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) const; -    SpellCastResult CheckTarget(Unit const* caster, WorldObject const* target, bool implicit = true) const; -    SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = NULL) const; -    SpellCastResult CheckVehicle(Unit const* caster) const; -    bool CheckTargetCreatureType(Unit const* target) const; - -    SpellSchoolMask GetSchoolMask() const; -    uint32 GetAllEffectsMechanicMask() const; -    uint32 GetEffectMechanicMask(uint8 effIndex) const; -    uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const; -    Mechanics GetEffectMechanic(uint8 effIndex) const; -    bool HasAnyEffectMechanic() const; -    uint32 GetDispelMask() const; -    static uint32 GetDispelMask(DispelType type); -    uint32 GetExplicitTargetMask() const; - -    AuraStateType GetAuraState() const; -    SpellSpecificType GetSpellSpecific() const; - -    float GetMinRange(bool positive = false) const; -    float GetMaxRange(bool positive = false, Unit* caster = NULL, Spell* spell = NULL) const; - -    int32 GetDuration() const; -    int32 GetMaxDuration() const; - -    uint32 GetMaxTicks() const; - -    uint32 CalcCastTime(Spell* spell = NULL) const; -    uint32 GetRecoveryTime() const; - -    int32 CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) const; - -    bool IsRanked() const; -    uint8 GetRank() const; -    SpellInfo const* GetFirstRankSpell() const; -    SpellInfo const* GetLastRankSpell() const; -    SpellInfo const* GetNextRankSpell() const; -    SpellInfo const* GetPrevRankSpell() const; -    SpellInfo const* GetAuraRankForLevel(uint8 level) const; -    bool IsRankOf(SpellInfo const* spellInfo) const; -    bool IsDifferentRankOf(SpellInfo const* spellInfo) const; -    bool IsHighRankOf(SpellInfo const* spellInfo) const; - -    // loading helpers -    void _InitializeExplicitTargetMask(); -    bool _IsPositiveEffect(uint8 effIndex, bool deep) const; -    bool _IsPositiveSpell() const; -    static bool _IsPositiveTarget(uint32 targetA, uint32 targetB); -    void _LoadSpellSpecific(); -    void _LoadAuraState(); - -    // unloading helpers -    void _UnloadImplicitTargetConditionLists(); +    DiminishingGroup DiminishGroup = DIMINISHING_NONE; +    DiminishingReturnsType DiminishReturnType = DRTYPE_NONE; +    DiminishingLevels DiminishMaxLevel = DIMINISHING_LEVEL_IMMUNE; +    int32 DiminishDurationLimit = 0; +}; -private: -    SpellSpecificType _spellSpecific; -    AuraStateType _auraState; +class TC_GAME_API SpellInfo +{ +    friend class SpellMgr; + +    public: +        uint32 Id; +        SpellCategoryEntry const* CategoryEntry; +        uint32 Dispel; +        uint32 Mechanic; +        uint32 Attributes; +        uint32 AttributesEx; +        uint32 AttributesEx2; +        uint32 AttributesEx3; +        uint32 AttributesEx4; +        uint32 AttributesEx5; +        uint32 AttributesEx6; +        uint32 AttributesEx7; +        uint32 AttributesCu; +        uint64 Stances; +        uint64 StancesNot; +        uint32 Targets; +        uint32 TargetCreatureType; +        uint32 RequiresSpellFocus; +        uint32 FacingCasterFlags; +        uint32 CasterAuraState; +        uint32 TargetAuraState; +        uint32 CasterAuraStateNot; +        uint32 TargetAuraStateNot; +        uint32 CasterAuraSpell; +        uint32 TargetAuraSpell; +        uint32 ExcludeCasterAuraSpell; +        uint32 ExcludeTargetAuraSpell; +        SpellCastTimesEntry const* CastTimeEntry; +        uint32 RecoveryTime; +        uint32 CategoryRecoveryTime; +        uint32 StartRecoveryCategory; +        uint32 StartRecoveryTime; +        uint32 InterruptFlags; +        uint32 AuraInterruptFlags; +        uint32 ChannelInterruptFlags; +        uint32 ProcFlags; +        uint32 ProcChance; +        uint32 ProcCharges; +        uint32 MaxLevel; +        uint32 BaseLevel; +        uint32 SpellLevel; +        SpellDurationEntry const* DurationEntry; +        uint32 PowerType; +        uint32 ManaCost; +        uint32 ManaCostPerlevel; +        uint32 ManaPerSecond; +        uint32 ManaPerSecondPerLevel; +        uint32 ManaCostPercentage; +        uint32 RuneCostID; +        SpellRangeEntry const* RangeEntry; +        float  Speed; +        uint32 StackAmount; +        uint32 Totem[2]; +        int32  Reagent[MAX_SPELL_REAGENTS]; +        uint32 ReagentCount[MAX_SPELL_REAGENTS]; +        int32  EquippedItemClass; +        int32  EquippedItemSubClassMask; +        int32  EquippedItemInventoryTypeMask; +        uint32 TotemCategory[2]; +        uint32 SpellVisual[2]; +        uint32 SpellIconID; +        uint32 ActiveIconID; +        char* SpellName[16]; +        char* Rank[16]; +        uint32 MaxTargetLevel; +        uint32 MaxAffectedTargets; +        uint32 SpellFamilyName; +        flag96 SpellFamilyFlags; +        uint32 DmgClass; +        uint32 PreventionType; +        int32  AreaGroupId; +        uint32 SchoolMask; +        SpellEffectInfo Effects[MAX_SPELL_EFFECTS]; +        uint32 ExplicitTargetMask; +        SpellChainNode const* ChainEntry; + +        SpellInfo(SpellEntry const* spellEntry); +        ~SpellInfo(); + +        uint32 GetCategory() const; +        bool HasEffect(SpellEffects effect) const; +        bool HasAura(AuraType aura) const; +        bool HasAreaAuraEffect() const; + +        inline bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); } +        inline bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); } +        inline bool HasAttribute(SpellAttr2 attribute) const { return !!(AttributesEx2 & attribute); } +        inline bool HasAttribute(SpellAttr3 attribute) const { return !!(AttributesEx3 & attribute); } +        inline bool HasAttribute(SpellAttr4 attribute) const { return !!(AttributesEx4 & attribute); } +        inline bool HasAttribute(SpellAttr5 attribute) const { return !!(AttributesEx5 & attribute); } +        inline bool HasAttribute(SpellAttr6 attribute) const { return !!(AttributesEx6 & attribute); } +        inline bool HasAttribute(SpellAttr7 attribute) const { return !!(AttributesEx7 & attribute); } +        inline bool HasAttribute(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); } + +        bool IsExplicitDiscovery() const; +        bool IsLootCrafting() const; +        bool IsQuestTame() const; +        bool IsProfessionOrRiding() const; +        bool IsProfession() const; +        bool IsPrimaryProfession() const; +        bool IsPrimaryProfessionFirstRank() const; +        bool IsAbilityLearnedWithProfession() const; +        bool IsAbilityOfSkillType(uint32 skillType) const; + +        bool IsAffectingArea() const; +        bool IsTargetingArea() const; +        bool NeedsExplicitUnitTarget() const; +        bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const; + +        bool IsPassive() const; +        bool IsAutocastable() const; +        bool IsStackableWithRanks() const; +        bool IsPassiveStackableWithRanks() const; +        bool IsMultiSlotAura() const; +        bool IsStackableOnOneSlotWithDifferentCasters() const; +        bool IsCooldownStartedOnEvent() const; +        bool IsDeathPersistent() const; +        bool IsRequiringDeadTarget() const; +        bool IsAllowingDeadTarget() const; +        bool IsGroupBuff() const; +        bool CanBeUsedInCombat() const; +        bool IsPositive() const; +        bool IsPositiveEffect(uint8 effIndex) const; +        bool IsChanneled() const; +        bool NeedsComboPoints() const; +        bool IsBreakingStealth() const; +        bool IsRangedWeaponSpell() const; +        bool IsAutoRepeatRangedSpell() const; +        bool HasInitialAggro() const; + +        bool IsAffectedBySpellMods() const; +        bool IsAffectedBySpellMod(SpellModifier const* mod) const; + +        bool CanPierceImmuneAura(SpellInfo const* aura) const; +        bool CanDispelAura(SpellInfo const* aura) const; + +        bool IsSingleTarget() const; +        bool IsAuraExclusiveBySpecificWith(SpellInfo const* spellInfo) const; +        bool IsAuraExclusiveBySpecificPerCasterWith(SpellInfo const* spellInfo) const; + +        SpellCastResult CheckShapeshift(uint32 form) const; +        SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) const; +        SpellCastResult CheckTarget(Unit const* caster, WorldObject const* target, bool implicit = true) const; +        SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = NULL) const; +        SpellCastResult CheckVehicle(Unit const* caster) const; +        bool CheckTargetCreatureType(Unit const* target) const; + +        SpellSchoolMask GetSchoolMask() const; +        uint32 GetAllEffectsMechanicMask() const; +        uint32 GetEffectMechanicMask(uint8 effIndex) const; +        uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const; +        Mechanics GetEffectMechanic(uint8 effIndex) const; +        bool HasAnyEffectMechanic() const; +        uint32 GetDispelMask() const; +        static uint32 GetDispelMask(DispelType type); +        uint32 GetExplicitTargetMask() const; + +        AuraStateType GetAuraState() const; +        SpellSpecificType GetSpellSpecific() const; + +        float GetMinRange(bool positive = false) const; +        float GetMaxRange(bool positive = false, Unit* caster = NULL, Spell* spell = NULL) const; + +        int32 GetDuration() const; +        int32 GetMaxDuration() const; + +        uint32 GetMaxTicks() const; + +        uint32 CalcCastTime(Spell* spell = NULL) const; +        uint32 GetRecoveryTime() const; + +        int32 CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) const; + +        bool IsRanked() const; +        uint8 GetRank() const; +        SpellInfo const* GetFirstRankSpell() const; +        SpellInfo const* GetLastRankSpell() const; +        SpellInfo const* GetNextRankSpell() const; +        SpellInfo const* GetPrevRankSpell() const; +        SpellInfo const* GetAuraRankForLevel(uint8 level) const; +        bool IsRankOf(SpellInfo const* spellInfo) const; +        bool IsDifferentRankOf(SpellInfo const* spellInfo) const; +        bool IsHighRankOf(SpellInfo const* spellInfo) const; + +        // spell diminishing returns +        DiminishingGroup GetDiminishingReturnsGroupForSpell(bool triggered) const; +        DiminishingReturnsType GetDiminishingReturnsGroupType(bool triggered) const; +        DiminishingLevels GetDiminishingReturnsMaxLevel(bool triggered) const; +        int32 GetDiminishingReturnsLimitDuration(bool triggered) const; + +    private: +        // loading helpers +        void _InitializeExplicitTargetMask(); +        bool _IsPositiveEffect(uint8 effIndex, bool deep) const; +        bool _IsPositiveSpell() const; +        static bool _IsPositiveTarget(uint32 targetA, uint32 targetB); +        void _LoadSpellSpecific(); +        void _LoadAuraState(); +        void _LoadSpellDiminishInfo(); + +        // unloading helpers +        void _UnloadImplicitTargetConditionLists(); + +        SpellSpecificType _spellSpecific; +        AuraStateType _auraState; + +        SpellDiminishInfo _diminishInfoNonTriggered; +        SpellDiminishInfo _diminishInfoTriggered;  };  #endif // _SPELLINFO_H diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index badb5fc4997..3e42b62f9bb 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -51,302 +51,6 @@ bool IsPartOfSkillLine(uint32 skillId, uint32 spellId)      return false;  } -DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto, bool triggered) -{ -    if (spellproto->IsPositive()) -        return DIMINISHING_NONE; - -    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) -    { -        if (spellproto->Effects[i].ApplyAuraName == SPELL_AURA_MOD_TAUNT) -            return DIMINISHING_TAUNT; -    } - -    // Explicit Diminishing Groups -    switch (spellproto->SpellFamilyName) -    { -        case SPELLFAMILY_GENERIC: -        { -            // Pet charge effects (Infernal Awakening, Demon Charge) -            if (spellproto->SpellVisual[0] == 2816 && spellproto->SpellIconID == 15) -                return DIMINISHING_CONTROLLED_STUN; -            // Frost Tomb -            else if (spellproto->Id == 48400) -                return DIMINISHING_NONE; -            // Gnaw -            else if (spellproto->Id == 47481) -                return DIMINISHING_CONTROLLED_STUN; -            // ToC Icehowl Arctic Breath -            else if (spellproto->SpellVisual[0] == 14153) -                return DIMINISHING_NONE; -            // Black Plague -            else if (spellproto->Id == 64155) -                return DIMINISHING_NONE; -            // Screams of the Dead (King Ymiron) -            else if (spellproto->Id == 51750) -                return DIMINISHING_NONE; -            break; -        } -        // Event spells -        case SPELLFAMILY_UNK1: -            return DIMINISHING_NONE; -        case SPELLFAMILY_MAGE: -        { -            // Frostbite -            if (spellproto->SpellFamilyFlags[1] & 0x80000000) -                return DIMINISHING_ROOT; -            // Shattered Barrier -            else if (spellproto->SpellVisual[0] == 12297) -                return DIMINISHING_ROOT; -            // Deep Freeze -            else if (spellproto->SpellIconID == 2939 && spellproto->SpellVisual[0] == 9963) -                return DIMINISHING_CONTROLLED_STUN; -            // Frost Nova / Freeze (Water Elemental) -            else if (spellproto->SpellIconID == 193) -                return DIMINISHING_CONTROLLED_ROOT; -            // Dragon's Breath -            else if (spellproto->SpellFamilyFlags[0] & 0x800000) -                return DIMINISHING_DRAGONS_BREATH; -            break; -        } -        case SPELLFAMILY_WARRIOR: -        { -            // Hamstring - limit duration to 10s in PvP -            if (spellproto->SpellFamilyFlags[0] & 0x2) -                return DIMINISHING_LIMITONLY; -            // Charge Stun (own diminishing) -            else if (spellproto->SpellFamilyFlags[0] & 0x01000000) -                return DIMINISHING_CHARGE; -            break; -        } -        case SPELLFAMILY_WARLOCK: -        { -            // Curses/etc -            if ((spellproto->SpellFamilyFlags[0] & 0x80000000) || (spellproto->SpellFamilyFlags[1] & 0x200)) -                return DIMINISHING_LIMITONLY; -            // Seduction -            else if (spellproto->SpellFamilyFlags[1] & 0x10000000) -                return DIMINISHING_FEAR; -            break; -        } -        case SPELLFAMILY_DRUID: -        { -            // Pounce -            if (spellproto->SpellFamilyFlags[0] & 0x20000) -                return DIMINISHING_OPENING_STUN; -            // Cyclone -            else if (spellproto->SpellFamilyFlags[1] & 0x20) -                return DIMINISHING_CYCLONE; -            // Entangling Roots -            // Nature's Grasp -            else if (spellproto->SpellFamilyFlags[0] & 0x00000200) -                return DIMINISHING_CONTROLLED_ROOT; -            // Faerie Fire -            else if (spellproto->SpellFamilyFlags[0] & 0x400) -                return DIMINISHING_LIMITONLY; -            break; -        } -        case SPELLFAMILY_ROGUE: -        { -            // Gouge -            if (spellproto->SpellFamilyFlags[0] & 0x8) -                return DIMINISHING_DISORIENT; -            // Blind -            else if (spellproto->SpellFamilyFlags[0] & 0x1000000) -                return DIMINISHING_FEAR; -            // Cheap Shot -            else if (spellproto->SpellFamilyFlags[0] & 0x400) -                return DIMINISHING_OPENING_STUN; -            // Crippling poison - Limit to 10 seconds in PvP (No SpellFamilyFlags) -            else if (spellproto->SpellIconID == 163) -                return DIMINISHING_LIMITONLY; -            break; -        } -        case SPELLFAMILY_HUNTER: -        { -            // Hunter's Mark -            if ((spellproto->SpellFamilyFlags[0] & 0x400) && spellproto->SpellIconID == 538) -                return DIMINISHING_LIMITONLY; -            // Scatter Shot (own diminishing) -            else if ((spellproto->SpellFamilyFlags[0] & 0x40000) && spellproto->SpellIconID == 132) -                return DIMINISHING_SCATTER_SHOT; -            // Entrapment (own diminishing) -            else if (spellproto->SpellVisual[0] == 7484 && spellproto->SpellIconID == 20) -                return DIMINISHING_ENTRAPMENT; -            // Wyvern Sting mechanic is MECHANIC_SLEEP but the diminishing is DIMINISHING_DISORIENT -            else if ((spellproto->SpellFamilyFlags[1] & 0x1000) && spellproto->SpellIconID == 1721) -                return DIMINISHING_DISORIENT; -            // Freezing Arrow -            else if (spellproto->SpellFamilyFlags[0] & 0x8) -                return DIMINISHING_DISORIENT; -            break; -        } -        case SPELLFAMILY_PALADIN: -        { -            // Judgement of Justice - limit duration to 10s in PvP -            if (spellproto->SpellFamilyFlags[0] & 0x100000) -                return DIMINISHING_LIMITONLY; -            // Turn Evil -            else if ((spellproto->SpellFamilyFlags[1] & 0x804000) && spellproto->SpellIconID == 309) -                return DIMINISHING_FEAR; -            break; -        } -        case SPELLFAMILY_SHAMAN: -        { -            // Storm, Earth and Fire - Earthgrab -            if (spellproto->SpellFamilyFlags[2] & 0x4000) -                return DIMINISHING_NONE; -            break; -        } -        case SPELLFAMILY_DEATHKNIGHT: -        { -            // Hungering Cold (no flags) -            if (spellproto->SpellIconID == 2797) -                return DIMINISHING_DISORIENT; -            // Mark of Blood -            else if ((spellproto->SpellFamilyFlags[0] & 0x10000000) && spellproto->SpellIconID == 2285) -                return DIMINISHING_LIMITONLY; -            break; -        } -        default: -            break; -    } - -    // Lastly - Set diminishing depending on mechanic -    uint32 mechanic = spellproto->GetAllEffectsMechanicMask(); -    if (mechanic & (1 << MECHANIC_CHARM)) -        return DIMINISHING_MIND_CONTROL; -    if (mechanic & (1 << MECHANIC_SILENCE)) -        return DIMINISHING_SILENCE; -    if (mechanic & (1 << MECHANIC_SLEEP)) -        return DIMINISHING_SLEEP; -    if (mechanic & ((1 << MECHANIC_SAPPED) | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_SHACKLE))) -        return DIMINISHING_DISORIENT; -    // Mechanic Knockout, except Blast Wave -    if (mechanic & (1 << MECHANIC_KNOCKOUT) && spellproto->SpellIconID != 292) -        return DIMINISHING_DISORIENT; -    if (mechanic & (1 << MECHANIC_DISARM)) -        return DIMINISHING_DISARM; -    if (mechanic & (1 << MECHANIC_FEAR)) -        return DIMINISHING_FEAR; -    if (mechanic & (1 << MECHANIC_STUN)) -        return triggered ? DIMINISHING_STUN : DIMINISHING_CONTROLLED_STUN; -    if (mechanic & (1 << MECHANIC_BANISH)) -        return DIMINISHING_BANISH; -    if (mechanic & (1 << MECHANIC_ROOT)) -        return triggered ? DIMINISHING_ROOT : DIMINISHING_CONTROLLED_ROOT; -    if (mechanic & (1 << MECHANIC_HORROR)) -        return DIMINISHING_HORROR; - -    return DIMINISHING_NONE; -} - -DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group) -{ -    switch (group) -    { -        case DIMINISHING_TAUNT: -        case DIMINISHING_CONTROLLED_STUN: -        case DIMINISHING_STUN: -        case DIMINISHING_OPENING_STUN: -        case DIMINISHING_CYCLONE: -        case DIMINISHING_CHARGE: -            return DRTYPE_ALL; -        case DIMINISHING_LIMITONLY: -        case DIMINISHING_NONE: -            return DRTYPE_NONE; -        default: -            return DRTYPE_PLAYER; -    } -} - -DiminishingLevels GetDiminishingReturnsMaxLevel(DiminishingGroup group) -{ -    switch (group) -    { -        case DIMINISHING_TAUNT: -            return DIMINISHING_LEVEL_TAUNT_IMMUNE; -        default: -            return DIMINISHING_LEVEL_IMMUNE; -    } -} - -int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellInfo const* spellproto) -{ -    if (!IsDiminishingReturnsGroupDurationLimited(group)) -        return 0; - -    // Explicit diminishing duration -    switch (spellproto->SpellFamilyName) -    { -        case SPELLFAMILY_DRUID: -        { -            // Faerie Fire - limit to 40 seconds in PvP (3.1) -            if (spellproto->SpellFamilyFlags[0] & 0x400) -                return 40 * IN_MILLISECONDS; -            break; -        } -        case SPELLFAMILY_HUNTER: -        { -            // Wyvern Sting -            if (spellproto->SpellFamilyFlags[1] & 0x1000) -                return 6 * IN_MILLISECONDS; -            // Hunter's Mark -            if (spellproto->SpellFamilyFlags[0] & 0x400) -                return 120 * IN_MILLISECONDS; -            break; -        } -        case SPELLFAMILY_PALADIN: -        { -            // Repentance - limit to 6 seconds in PvP -            if (spellproto->SpellFamilyFlags[0] & 0x4) -                return 6 * IN_MILLISECONDS; -            break; -        } -        case SPELLFAMILY_WARLOCK: -        { -            // Banish - limit to 6 seconds in PvP -            if (spellproto->SpellFamilyFlags[1] & 0x8000000) -                return 6 * IN_MILLISECONDS; -            // Curse of Tongues - limit to 12 seconds in PvP -            else if (spellproto->SpellFamilyFlags[2] & 0x800) -                return 12 * IN_MILLISECONDS; -            // Curse of Elements - limit to 120 seconds in PvP -            else if (spellproto->SpellFamilyFlags[1] & 0x200) -               return 120 * IN_MILLISECONDS; -            break; -        } -        default: -            break; -    } - -    return 10 * IN_MILLISECONDS; -} - -bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group) -{ -    switch (group) -    { -        case DIMINISHING_BANISH: -        case DIMINISHING_CONTROLLED_STUN: -        case DIMINISHING_CONTROLLED_ROOT: -        case DIMINISHING_CYCLONE: -        case DIMINISHING_DISORIENT: -        case DIMINISHING_ENTRAPMENT: -        case DIMINISHING_FEAR: -        case DIMINISHING_HORROR: -        case DIMINISHING_MIND_CONTROL: -        case DIMINISHING_OPENING_STUN: -        case DIMINISHING_ROOT: -        case DIMINISHING_STUN: -        case DIMINISHING_SLEEP: -        case DIMINISHING_LIMITONLY: -            return true; -        default: -            return false; -    } -} -  SpellMgr::SpellMgr() { }  SpellMgr::~SpellMgr() @@ -3769,3 +3473,18 @@ void SpellMgr::LoadSpellInfoSpellSpecificAndAuraState()      TC_LOG_INFO("server.loading", ">> Loaded SpellInfo SpellSpecific and AuraState in %u ms", GetMSTimeDiffToNow(oldMSTime));  } + +void SpellMgr::LoadSpellInfoDiminishing() +{ +    uint32 oldMSTime = getMSTime(); + +    for (SpellInfo* spellInfo : mSpellInfoMap) +    { +        if (!spellInfo) +            continue; + +        spellInfo->_LoadSpellDiminishInfo(); +    } + +    TC_LOG_INFO("server.loading", ">> Loaded SpellInfo diminishing infos in %u ms", GetMSTimeDiffToNow(oldMSTime)); +} diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 60af9bd94bf..f119d164789 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -547,13 +547,6 @@ inline bool IsProfessionOrRidingSkill(uint32 skill)  bool IsPartOfSkillLine(uint32 skillId, uint32 spellId); -// spell diminishing returns -TC_GAME_API DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto, bool triggered); -TC_GAME_API DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group); -TC_GAME_API DiminishingLevels GetDiminishingReturnsMaxLevel(DiminishingGroup group); -TC_GAME_API int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellInfo const* spellproto); -TC_GAME_API bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group); -  class TC_GAME_API SpellMgr  {      // Constructors @@ -686,6 +679,7 @@ class TC_GAME_API SpellMgr          void LoadSpellInfoCustomAttributes();          void LoadSpellInfoCorrections();          void LoadSpellInfoSpellSpecificAndAuraState(); +        void LoadSpellInfoDiminishing();      private:          SpellDifficultySearcherMap mSpellDifficultySearcherMap; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 443d0c63efa..59a1e757183 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1452,6 +1452,9 @@ void World::SetInitialWorldSettings()      TC_LOG_INFO("server.loading", "Loading SpellInfo SpellSpecific and AuraState...");      sSpellMgr->LoadSpellInfoSpellSpecificAndAuraState(); +    TC_LOG_INFO("server.loading", "Loading SpellInfo diminishing infos..."); +    sSpellMgr->LoadSpellInfoDiminishing(); +      TC_LOG_INFO("server.loading", "Loading GameObject models...");      LoadGameObjectModelList(m_dataPath); | 
