diff options
| author | ForesterDev <forester.manv@gmail.com> | 2016-05-27 12:51:28 +0400 | 
|---|---|---|
| committer | ForesterDev <forester.manv@gmail.com> | 2016-05-27 12:51:28 +0400 | 
| commit | c73c51d7b106c11e96e8f11054f3c87e5de426e5 (patch) | |
| tree | 83c6625c875ca10e441804c8d32c0b182c6370cb /src | |
| parent | 8eac30448fa538fa94edf2417c3c39bae6eec9cf (diff) | |
| parent | dc67505a081fed7d59fe833ad9ec5a3741a78e8f (diff) | |
Merge branch '3.3.5' into creature_family
Diffstat (limited to 'src')
46 files changed, 1715 insertions, 722 deletions
diff --git a/src/common/Utilities/Containers.h b/src/common/Utilities/Containers.h index 0f83b52f9d0..5edb245fd87 100644 --- a/src/common/Utilities/Containers.h +++ b/src/common/Utilities/Containers.h @@ -31,9 +31,9 @@ namespace Trinity      namespace Containers      {          template<class T> -        void RandomResizeList(std::list<T> &list, uint32 size) +        void RandomResizeList(std::list<T>& list, uint32 size)          { -            size_t list_size = list.size(); +            uint32 list_size = uint32(list.size());              while (list_size > size)              { @@ -56,7 +56,7 @@ namespace Trinity              if (size)                  RandomResizeList(listCopy, size); -            list = listCopy; +            list = std::move(listCopy);          }          /* @@ -68,7 +68,7 @@ namespace Trinity          typename C::value_type const& SelectRandomContainerElement(C const& container)          {              typename C::const_iterator it = container.begin(); -            std::advance(it, urand(0, container.size() - 1)); +            std::advance(it, urand(0, uint32(container.size()) - 1));              return *it;          } @@ -170,7 +170,6 @@ namespace Trinity                      ++itr;              }          } -      }      //! namespace Containers  } diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp index 7a183d5bf78..83720c1a996 100644 --- a/src/server/database/Database/Implementation/WorldDatabase.cpp +++ b/src/server/database/Database/Implementation/WorldDatabase.cpp @@ -30,8 +30,8 @@ void WorldDatabaseConnection::DoPrepareStatements()      PrepareStatement(WORLD_SEL_SMARTAI_WP, "SELECT entry, pointid, position_x, position_y, position_z FROM waypoints ORDER BY entry, pointid", CONNECTION_SYNCH);      PrepareStatement(WORLD_DEL_GAMEOBJECT, "DELETE FROM gameobject WHERE guid = ?", CONNECTION_ASYNC);      PrepareStatement(WORLD_DEL_EVENT_GAMEOBJECT, "DELETE FROM game_event_gameobject WHERE guid = ?", CONNECTION_ASYNC); -    PrepareStatement(WORLD_INS_GRAVEYARD_ZONE, "INSERT INTO game_graveyard_zone (id, ghost_zone, faction) VALUES (?, ?, ?)", CONNECTION_ASYNC); -    PrepareStatement(WORLD_DEL_GRAVEYARD_ZONE, "DELETE FROM game_graveyard_zone WHERE id = ? AND ghost_zone = ? AND faction = ?", CONNECTION_ASYNC); +    PrepareStatement(WORLD_INS_GRAVEYARD_ZONE, "INSERT INTO graveyard_zone (ID, GhostZone, Faction) VALUES (?, ?, ?)", CONNECTION_ASYNC); +    PrepareStatement(WORLD_DEL_GRAVEYARD_ZONE, "DELETE FROM graveyard_zone WHERE ID = ? AND GhostZone = ? AND Faction = ?", CONNECTION_ASYNC);      PrepareStatement(WORLD_INS_GAME_TELE, "INSERT INTO game_tele (id, position_x, position_y, position_z, orientation, map, name) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);      PrepareStatement(WORLD_DEL_GAME_TELE, "DELETE FROM game_tele WHERE name = ?", CONNECTION_ASYNC);      PrepareStatement(WORLD_INS_NPC_VENDOR, "INSERT INTO npc_vendor (entry, item, maxcount, incrtime, extendedcost) VALUES(?, ?, ?, ?, ?)", CONNECTION_ASYNC); diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index 8c088e4da19..6475cc8117e 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -547,7 +547,7 @@ void BossAI::UpdateAI(uint32 diff)      DoMeleeAttackIfReady();  } -void BossAI::_DespawnAtEvade(uint32 delayToRespawn) +void BossAI::_DespawnAtEvade(uint32 delayToRespawn, Creature* who)  {      if (delayToRespawn < 2)      { @@ -555,18 +555,28 @@ void BossAI::_DespawnAtEvade(uint32 delayToRespawn)          delayToRespawn = 2;      } -    uint32 corpseDelay = me->GetCorpseDelay(); -    uint32 respawnDelay = me->GetRespawnDelay(); +    if (!who) +        who = me; -    me->SetCorpseDelay(1); -    me->SetRespawnDelay(delayToRespawn - 1); +    if (TempSummon* whoSummon = who->ToTempSummon()) +    { +        TC_LOG_WARN("scripts", "_DespawnAtEvade called on a temporary summon."); +        whoSummon->UnSummon(); +        return; +    } -    me->DespawnOrUnsummon(); +    uint32 corpseDelay = who->GetCorpseDelay(); +    uint32 respawnDelay = who->GetRespawnDelay(); -    me->SetCorpseDelay(corpseDelay); -    me->SetRespawnDelay(respawnDelay); +    who->SetCorpseDelay(1); +    who->SetRespawnDelay(delayToRespawn - 1); -    if (instance) +    who->DespawnOrUnsummon(); + +    who->SetCorpseDelay(corpseDelay); +    who->SetRespawnDelay(respawnDelay); + +    if (instance && who == me)          instance->SetBossState(_bossId, FAIL);  } diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index 58a0253e46b..6144a4e5203 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -367,7 +367,7 @@ class TC_GAME_API BossAI : public ScriptedAI          void _EnterCombat();          void _JustDied();          void _JustReachedHome() { me->setActive(false); } -        void _DespawnAtEvade(uint32 delayToRespawn = 30); +        void _DespawnAtEvade(uint32 delayToRespawn = 30,  Creature* who = nullptr);          void TeleportCheaters(); diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp index fa80634e0f0..1b8b472b805 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp @@ -72,7 +72,7 @@ bool npc_escortAI::AssistPlayerInCombat(Unit* who)          return false;      //experimental (unknown) flag not present -    if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_AID_PLAYERS)) +    if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST))          return false;      //not a player diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp index 778edf8cab5..bd07e688fb0 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp @@ -69,7 +69,7 @@ bool FollowerAI::AssistPlayerInCombat(Unit* who)          return false;      //experimental (unknown) flag not present -    if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_AID_PLAYERS)) +    if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST))          return false;      //not a player diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 60df4fe6d5a..e21f59fe582 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -468,7 +468,7 @@ bool SmartAI::AssistPlayerInCombat(Unit* who)          return false;      //experimental (unknown) flag not present -    if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_AID_PLAYERS)) +    if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST))          return false;      //not a player diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 9dd56ec8180..d1d418b0931 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -540,7 +540,7 @@ enum RBACPermissions      RBAC_PERM_COMMAND_RELOAD_DISENCHANT_LOOT_TEMPLATE        = 642,      RBAC_PERM_COMMAND_RELOAD_EVENT_SCRIPTS                   = 643,      RBAC_PERM_COMMAND_RELOAD_FISHING_LOOT_TEMPLATE           = 644, -    RBAC_PERM_COMMAND_RELOAD_GAME_GRAVEYARD_ZONE             = 645, +    RBAC_PERM_COMMAND_RELOAD_GRAVEYARD_ZONE                  = 645,      RBAC_PERM_COMMAND_RELOAD_GAME_TELE                       = 646,      RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUESTENDER           = 647,      RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUEST_LOOT_TEMPLATE  = 648, diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index afb6255079b..74e94135b86 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -738,7 +738,7 @@ bool ConditionMgr::IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo,              //! If not found, add an entry in the store and set to true (placeholder)              if (itr == elseGroupStore.end())                  elseGroupStore[condition->ElseGroup] = true; -            else if (!(*itr).second) +            else if (!(*itr).second) //! If another condition in this group was unmatched before this, don't bother checking (the group is false anyway)                  continue;              if (condition->ReferenceId)//handle reference diff --git a/src/server/game/DataStores/M2Stores.cpp b/src/server/game/DataStores/M2Stores.cpp index 5cff66e6107..69581f16549 100644 --- a/src/server/game/DataStores/M2Stores.cpp +++ b/src/server/game/DataStores/M2Stores.cpp @@ -193,7 +193,7 @@ void LoadM2Cameras(std::string const& dataPath)      {          if (CinematicCameraEntry const* dbcentry = sCinematicCameraStore.LookupEntry(i))          { -            std::string filenameWork = dataPath.c_str(); +            std::string filenameWork = dataPath;              filenameWork.append(dbcentry->Model);              // Replace slashes (always to forward slash, because boost!) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 450cf2396a8..22e917448c3 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1823,7 +1823,7 @@ bool Creature::isWorldBoss() const      if (IsPet())          return false; -    return (GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_BOSS) != 0; +    return (GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_BOSS_MOB) != 0;  }  SpellInfo const* Creature::reachWithSpellAttack(Unit* victim) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 97b7b86d4b9..cc0e0559d28 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -146,11 +146,11 @@ struct TC_GAME_API CreatureTemplate      // helpers      SkillType GetRequiredLootSkill() const      { -        if (type_flags & CREATURE_TYPEFLAGS_HERBLOOT) +        if (type_flags & CREATURE_TYPE_FLAG_HERB_SKINNING_SKILL)              return SKILL_HERBALISM; -        else if (type_flags & CREATURE_TYPEFLAGS_MININGLOOT) +        else if (type_flags & CREATURE_TYPE_FLAG_MINING_SKINNING_SKILL)              return SKILL_MINING; -        else if (type_flags & CREATURE_TYPEFLAGS_ENGINEERLOOT) +        else if (type_flags & CREATURE_TYPE_FLAG_ENGINEERING_SKINNING_SKILL)              return SKILL_ENGINEERING;          else              return SKILL_SKINNING;                          // normal case @@ -158,12 +158,12 @@ struct TC_GAME_API CreatureTemplate      bool IsExotic() const      { -        return (type_flags & CREATURE_TYPEFLAGS_EXOTIC) != 0; +        return (type_flags & CREATURE_TYPE_FLAG_EXOTIC_PET) != 0;      }      bool IsTameable(bool canTameExotic) const      { -        if (type != CREATURE_TYPE_BEAST || family == CREATURE_FAMILY_NONE || (type_flags & CREATURE_TYPEFLAGS_TAMEABLE) == 0) +        if (type != CREATURE_TYPE_BEAST || family == CREATURE_FAMILY_NONE || (type_flags & CREATURE_TYPE_FLAG_TAMEABLE_PET) == 0)              return false;          // if can tame exotic then can tame any tameable diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index a2f519a681c..daad0c9d958 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1154,9 +1154,13 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const      if (!IsInMap(obj))          return false; -    float ox, oy, oz; -    obj->GetPosition(ox, oy, oz); -    return IsWithinLOS(ox, oy, oz); +    float x, y, z; +    if (obj->GetTypeId() == TYPEID_PLAYER) +        obj->GetPosition(x, y, z); +    else +        obj->GetHitSpherePointFor(GetPosition(), x, y, z); + +    return IsWithinLOS(x, y, z);  }  float WorldObject::GetDistance(const WorldObject* obj) const @@ -1240,11 +1244,36 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const      VMAP::IVMapManager* vMapManager = VMAP::VMapFactory::createOrGetVMapManager();      return vMapManager->isInLineOfSight(GetMapId(), x, y, z+2.0f, ox, oy, oz+2.0f);*/      if (IsInWorld()) -        return GetMap()->isInLineOfSight(GetPositionX(), GetPositionY(), GetPositionZ()+2.f, ox, oy, oz+2.f, GetPhaseMask()); +    { +        float x, y, z; +        if (GetTypeId() == TYPEID_PLAYER) +            GetPosition(x, y, z); +        else +            GetHitSpherePointFor({ ox, oy, oz }, x, y, z); + +        return GetMap()->isInLineOfSight(x, y, z + 2.0f, ox, oy, oz + 2.0f, GetPhaseMask()); +    }      return true;  } +Position WorldObject::GetHitSpherePointFor(Position const& dest) const +{ +    G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ()); +    G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ()); +    G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * GetObjectSize(); + +    return Position(contactPoint.x, contactPoint.y, contactPoint.z, GetAngle(contactPoint.x, contactPoint.y)); +} + +void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const +{ +    Position pos = GetHitSpherePointFor(dest); +    x = pos.GetPositionX(); +    y = pos.GetPositionY(); +    z = pos.GetPositionZ(); +} +  bool WorldObject::GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D /* = true */) const  {      float dx1 = GetPositionX() - obj1->GetPositionX(); @@ -2038,7 +2067,10 @@ void WorldObject::SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list      std::vector<TempSummonData> const* data = sObjectMgr->GetSummonGroup(GetEntry(), GetTypeId() == TYPEID_GAMEOBJECT ? SUMMONER_TYPE_GAMEOBJECT : SUMMONER_TYPE_CREATURE, group);      if (!data) +    { +        TC_LOG_WARN("scripts", "%s (%s) tried to summon non-existing summon group %u.", GetName().c_str(), GetGUID().ToString().c_str(), group);          return; +    }      for (std::vector<TempSummonData>::const_iterator itr = data->begin(); itr != data->end(); ++itr)          if (TempSummon* summon = SummonCreature(itr->entry, itr->pos, itr->type, itr->time)) diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 5c8a84453c3..47b28d8ea3a 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -488,6 +488,8 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation          bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true) const;          bool IsWithinLOS(float x, float y, float z) const;          bool IsWithinLOSInMap(WorldObject const* obj) const; +        Position GetHitSpherePointFor(Position const& dest) const; +        void GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const;          bool GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D = true) const;          bool IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D = true) const;          bool IsInRange2d(float x, float y, float minRange, float maxRange) const; diff --git a/src/server/game/Entities/Player/CinematicMgr.cpp b/src/server/game/Entities/Player/CinematicMgr.cpp index 07bf733c9ff..cc5a62300ad 100644 --- a/src/server/game/Entities/Player/CinematicMgr.cpp +++ b/src/server/game/Entities/Player/CinematicMgr.cpp @@ -27,6 +27,7 @@ CinematicMgr::CinematicMgr(Player* playerref)      m_cinematicDiff = 0;      m_lastCinematicCheck = 0;      m_activeCinematicCameraId = 0; +    m_cinematicLength = 0;      m_cinematicCamera = nullptr;      m_remoteSightPosition = Position(0.0f, 0.0f, 0.0f);      m_CinematicObject = nullptr; @@ -70,6 +71,8 @@ void CinematicMgr::BeginCinematic()              FlyByCameraCollection::const_reverse_iterator camrevitr = m_cinematicCamera->rbegin();              if (camrevitr != m_cinematicCamera->rend())                  m_cinematicLength = camrevitr->timeStamp; +            else +                m_cinematicLength = 0;          }      }  } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index ad53c750de6..586491e31be 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -567,6 +567,7 @@ Player::~Player()      delete m_runes;      delete m_achievementMgr;      delete m_reputationMgr; +    delete _cinematicMgr;      sWorld->DecreasePlayerCount();  } @@ -2418,11 +2419,11 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid const& guid, uint32 npcflag          return nullptr;      // Deathstate checks -    if (!IsAlive() && !(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_GHOST)) +    if (!IsAlive() && !(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_GHOST_VISIBLE))          return nullptr;      // alive or spirit healer -    if (!creature->IsAlive() && !(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_DEAD_INTERACT)) +    if (!creature->IsAlive() && !(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_INTERACT_WHILE_DEAD))          return nullptr;      // appropriate npc type @@ -4940,6 +4941,9 @@ void Player::DurabilityPointsLossAll(int32 points, bool inventory)  void Player::DurabilityPointsLoss(Item* item, int32 points)  { +    if (HasAuraType(SPELL_AURA_PREVENT_DURABILITY_LOSS)) +        return; +      int32 pMaxDurability = item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY);      int32 pOldDurability = item->GetUInt32Value(ITEM_FIELD_DURABILITY);      int32 pNewDurability = pOldDurability - points; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 372a49b4f9d..6a38cd3b9fe 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1596,7 +1596,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>          void AddSpellMod(SpellModifier* mod, bool apply);          bool IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod, Spell* spell = nullptr) const; -        template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell* spell = nullptr); +        template <class T> +        void ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* spell = nullptr);          void RemoveSpellMods(Spell* spell);          void RestoreSpellMods(Spell* spell, uint32 ownerAuraId = 0, Aura* aura = nullptr);          void RestoreAllSpellMods(uint32 ownerAuraId = 0, Aura* aura = nullptr); @@ -2604,11 +2605,13 @@ TC_GAME_API void AddItemsSetItem(Player* player, Item* item);  TC_GAME_API void RemoveItemsSetItem(Player* player, ItemTemplate const* proto);  // "the bodies of template functions must be made available in a header file" -template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell* spell) +template <class T> +void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* spell /*= nullptr*/)  {      SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);      if (!spellInfo) -        return 0; +        return; +      float totalmul = 1.0f;      int32 totalflat = 0; @@ -2644,9 +2647,8 @@ template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &bas          DropModCharge(mod, spell);      } -    float diff = (float)basevalue * (totalmul - 1.0f) + (float)totalflat; -    basevalue = T((float)basevalue + diff); -    return T(diff); + +    basevalue = T(float(basevalue + totalflat) * totalmul);  }  #endif diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index ee815f199bd..9afc2987319 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -599,11 +599,14 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam      if (victim->GetTypeId() == TYPEID_PLAYER && this != victim)      { -        // Signal to pets that their owner was attacked -        Pet* pet = victim->ToPlayer()->GetPet(); +        // Signal to pets that their owner was attacked - except when DOT. +        if (damagetype != DOT) +        { +            Pet* pet = victim->ToPlayer()->GetPet(); -        if (pet && pet->IsAlive()) -            pet->AI()->OwnerAttackedBy(this); +            if (pet && pet->IsAlive()) +                pet->AI()->OwnerAttackedBy(this); +        }          if (victim->ToPlayer()->GetCommandStatus(CHEAT_GOD))              return 0; @@ -3189,6 +3192,15 @@ int32 Unit::GetCurrentSpellCastTime(uint32 spell_id) const      return 0;  } +bool Unit::CanMoveDuringChannel() const +{ +    if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) +        if (spell->getState() != SPELL_STATE_FINISHED) +            return spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING) && spell->IsChannelActive(); + +    return false; +} +  bool Unit::isInFrontInMap(Unit const* target, float distance,  float arc) const  {      return IsWithinDistInMap(target, distance) && HasInArc(arc, target); @@ -5287,7 +5299,7 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType  }  //victim may be NULL -bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown) +bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, Milliseconds& cooldown)  {      SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo();      uint32 effIndex = triggeredByAura->GetEffIndex(); @@ -5297,8 +5309,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere          ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL;      uint32 triggered_spell_id = 0; -    uint32 cooldown_spell_id = 0; // for random trigger, will be one of the triggered spell to avoid repeatable triggers -                                  // otherwise, it's the triggered_spell_id by default      Unit* target = victim;      int32 basepoints0 = 0;      ObjectGuid originalCaster; @@ -5374,24 +5384,20 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere                          case CLASS_PALADIN:                 // 39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409                          case CLASS_DRUID:                   // 39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409                              triggered_spell_id = RAND(39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409); -                            cooldown_spell_id = 39511;                              break;                          case CLASS_ROGUE:                   // 39511, 40997, 40998, 41002, 41005, 41011                          case CLASS_WARRIOR:                 // 39511, 40997, 40998, 41002, 41005, 41011                          case CLASS_DEATH_KNIGHT:                              triggered_spell_id = RAND(39511, 40997, 40998, 41002, 41005, 41011); -                            cooldown_spell_id = 39511;                              break;                          case CLASS_PRIEST:                  // 40999, 41002, 41005, 41009, 41011, 41406, 41409                          case CLASS_SHAMAN:                  // 40999, 41002, 41005, 41009, 41011, 41406, 41409                          case CLASS_MAGE:                    // 40999, 41002, 41005, 41009, 41011, 41406, 41409                          case CLASS_WARLOCK:                 // 40999, 41002, 41005, 41009, 41011, 41406, 41409                              triggered_spell_id = RAND(40999, 41002, 41005, 41009, 41011, 41406, 41409); -                            cooldown_spell_id = 40999;                              break;                          case CLASS_HUNTER:                  // 40997, 40999, 41002, 41005, 41009, 41011, 41406, 41409                              triggered_spell_id = RAND(40997, 40999, 41002, 41005, 41009, 41011, 41406, 41409); -                            cooldown_spell_id = 40997;                              break;                          default:                              return false; @@ -5621,11 +5627,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere                      uint8 rand_spell = urand(0, (RandomSpells.size() - 1));                      CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster); -                    for (std::vector<uint32>::iterator itr = RandomSpells.begin(); itr != RandomSpells.end(); ++itr) -                    { -                        if (!GetSpellHistory()->HasCooldown(*itr)) -                            GetSpellHistory()->AddCooldown(*itr, 0, std::chrono::seconds(cooldown)); -                    }                      break;                  }                  case 71562: // Deathbringer's Will Heroic @@ -5667,11 +5668,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere                      uint8 rand_spell = urand(0, (RandomSpells.size() - 1));                      CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster); -                    for (std::vector<uint32>::iterator itr = RandomSpells.begin(); itr != RandomSpells.end(); ++itr) -                    { -                        if (!GetSpellHistory()->HasCooldown(*itr)) -                            GetSpellHistory()->AddCooldown(*itr, 0, std::chrono::seconds(cooldown)); -                    }                      break;                  }                  case 65032: // Boom aura (321 Boombot) @@ -6309,24 +6305,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere                      return true;                  }              } -            // Eclipse -            if (dummySpell->SpellIconID == 2856 && GetTypeId() == TYPEID_PLAYER) -            { -                if (!procSpell || effIndex != 0) -                    return false; - -                bool isWrathSpell = (procSpell->SpellFamilyFlags[0] & 1); - -                if (!roll_chance_f(dummySpell->ProcChance * (isWrathSpell ? 0.6f : 1.0f))) -                    return false; - -                target = this; -                if (target->HasAura(isWrathSpell ? 48517 : 48518)) -                    return false; - -                triggered_spell_id = isWrathSpell ? 48518 : 48517; -                break; -            }              break;          }          case SPELLFAMILY_ROGUE: @@ -6507,7 +6485,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere                      // Item - Paladin T8 Holy 4P Bonus                      if (Unit* caster = triggeredByAura->GetCaster())                          if (AuraEffect const* aurEff = caster->GetAuraEffect(64895, 0)) -                            cooldown = aurEff->GetAmount(); +                            cooldown = Milliseconds(aurEff->GetAmount());                      target = this;                      break; @@ -6822,10 +6800,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere                      if (!player || !castItem || !castItem->IsEquipped() || !victim || !victim->IsAlive())                          return false; -                    // custom cooldown processing case -                    if (cooldown && GetSpellHistory()->HasCooldown(dummySpell->Id)) -                        return false; -                      if (triggeredByAura->GetBase() && castItem->GetGUID() != triggeredByAura->GetBase()->GetCastItemGUID())                          return false; @@ -6888,8 +6862,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere                          triggered_spell_id = 33750;                      // apply cooldown before cast to prevent processing itself -                    if (cooldown) -                        player->GetSpellHistory()->AddCooldown(dummySpell->Id, 0, std::chrono::seconds(cooldown)); +                    triggeredByAura->GetBase()->AddProcCooldown(std::chrono::steady_clock::now() + cooldown); +                    cooldown = Milliseconds::zero();                      // Attack Twice                      for (uint32 i = 0; i < 2; ++i) @@ -7132,10 +7106,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere                  if (!procSpell || GetTypeId() != TYPEID_PLAYER || !victim)                      return false; -                // custom cooldown processing case -                if (cooldown && GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(dummySpell->Id)) -                    return false; -                  uint32 spellId = 0;                  // Every Lightning Bolt and Chain Lightning spell have duplicate vs half damage and zero cost                  switch (procSpell->Id) @@ -7181,10 +7151,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere                  }                  CastSpell(victim, spellId, true, castItem, triggeredByAura); - -                if (cooldown && GetTypeId() == TYPEID_PLAYER) -                    GetSpellHistory()->AddCooldown(dummySpell->Id, 0, std::chrono::seconds(cooldown)); -                  return true;              }              // Static Shock @@ -7486,26 +7452,17 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere          return false;      } -    if (cooldown_spell_id == 0) -        cooldown_spell_id = triggered_spell_id; - -    if (cooldown && GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(cooldown_spell_id)) -        return false; -      if (basepoints0)          CastCustomSpell(target, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura, originalCaster);      else          CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura, originalCaster); -    if (cooldown && GetTypeId() == TYPEID_PLAYER) -        GetSpellHistory()->AddCooldown(cooldown_spell_id, 0, std::chrono::seconds(cooldown)); -      return true;  }  // Used in case when access to whole aura is needed  // All procs should be handled like this... -bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 /*procFlag*/, uint32 procEx, uint32 cooldown, bool * handled) +bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 /*procFlag*/, uint32 procEx, bool* handled)  {      SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo(); @@ -7717,12 +7674,6 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp                  case 49222:                  {                      *handled = true; -                    if (cooldown && GetTypeId() == TYPEID_PLAYER) -                    { -                        if (GetSpellHistory()->HasCooldown(100000)) -                            return false; -                        GetSpellHistory()->AddCooldown(100000, 0, std::chrono::seconds(cooldown)); -                    }                      return true;                  }                  // Hungering Cold aura drop @@ -7765,7 +7716,7 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp      return false;  } -bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlags, uint32 procEx, uint32 cooldown) +bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx)  {      // Get triggered aura spell info      SpellInfo const* auraSpellInfo = triggeredByAura->GetSpellInfo(); @@ -7791,95 +7742,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg      {          switch (auraSpellInfo->SpellFamilyName)          { -            case SPELLFAMILY_GENERIC: -                switch (auraSpellInfo->Id) -                { -                    case 43820:             // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket) -                        // Pct value stored in dummy -                        basepoints0 = victim->GetCreateHealth() * auraSpellInfo->Effects[1].CalcValue() / 100; -                        target = victim; -                        break; -                    case 57345:             // Darkmoon Card: Greatness -                    { -                        float stat = 0.0f; -                        // strength -                        if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 60229;stat = GetStat(STAT_STRENGTH); } -                        // agility -                        if (GetStat(STAT_AGILITY)  > stat) { trigger_spell_id = 60233;stat = GetStat(STAT_AGILITY);  } -                        // intellect -                        if (GetStat(STAT_INTELLECT)> stat) { trigger_spell_id = 60234;stat = GetStat(STAT_INTELLECT);} -                        // spirit -                        if (GetStat(STAT_SPIRIT)   > stat) { trigger_spell_id = 60235;                               } -                        break; -                    } -                    case 64568:             // Blood Reserve -                    { -                        if (HealthBelowPctDamaged(35, damage)) -                        { -                            CastCustomSpell(this, 64569, &triggerAmount, NULL, NULL, true); -                            RemoveAura(64568); -                        } -                        return false; -                    } -                    case 67702:             // Death's Choice, Item - Coliseum 25 Normal Melee Trinket -                    { -                        float stat = 0.0f; -                        // strength -                        if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 67708;stat = GetStat(STAT_STRENGTH); } -                        // agility -                        if (GetStat(STAT_AGILITY)  > stat) { trigger_spell_id = 67703;                               } -                        break; -                    } -                    case 67771:             // Death's Choice (heroic), Item - Coliseum 25 Heroic Melee Trinket -                    { -                        float stat = 0.0f; -                        // strength -                        if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 67773;stat = GetStat(STAT_STRENGTH); } -                        // agility -                        if (GetStat(STAT_AGILITY)  > stat) { trigger_spell_id = 67772;                               } -                        break; -                    } -                    // Mana Drain Trigger -                    case 27522: -                    case 40336: -                    { -                        // On successful melee or ranged attack gain $29471s1 mana and if possible drain $27526s1 mana from the target. -                        if (IsAlive()) -                            CastSpell(this, 29471, true, castItem, triggeredByAura); -                        if (victim && victim->IsAlive()) -                            CastSpell(victim, 27526, true, castItem, triggeredByAura); -                        return true; -                    } -                    // Evasive Maneuvers -                    case 50240: -                    { -                        // Remove a Evasive Charge -                        Aura* charge = GetAura(50241); -                        if (charge && charge->ModStackAmount(-1, AURA_REMOVE_BY_ENEMY_SPELL)) -                            RemoveAurasDueToSpell(50240); -                        break; -                    } -                    // Battle Experience -                    // already handled in gunship battle script -                    case 71201: -                        return false; -                } -                break; -            case SPELLFAMILY_MAGE: -                if (auraSpellInfo->SpellIconID == 2127)     // Blazing Speed -                { -                    switch (auraSpellInfo->Id) -                    { -                        case 31641:  // Rank 1 -                        case 31642:  // Rank 2 -                            trigger_spell_id = 31643; -                            break; -                        default: -                            TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u miss posibly Blazing Speed", auraSpellInfo->Id); -                            return false; -                    } -                } -                break;              case SPELLFAMILY_WARLOCK:              {                  // Drain Soul @@ -7902,325 +7764,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg                      // Need for correct work Drain Soul SPELL_AURA_CHANNEL_DEATH_ITEM aura                      return false;                  } -                // Nether Protection -                else if (auraSpellInfo->SpellIconID == 1985) -                { -                    if (!procSpell) -                        return false; -                    switch (GetFirstSchoolInMask(procSpell->GetSchoolMask())) -                    { -                        case SPELL_SCHOOL_NORMAL: -                            return false;                   // ignore -                        case SPELL_SCHOOL_HOLY:   trigger_spell_id = 54370; break; -                        case SPELL_SCHOOL_FIRE:   trigger_spell_id = 54371; break; -                        case SPELL_SCHOOL_NATURE: trigger_spell_id = 54375; break; -                        case SPELL_SCHOOL_FROST:  trigger_spell_id = 54372; break; -                        case SPELL_SCHOOL_SHADOW: trigger_spell_id = 54374; break; -                        case SPELL_SCHOOL_ARCANE: trigger_spell_id = 54373; break; -                        default: -                            return false; -                    } -                } -                break; -            } -            case SPELLFAMILY_PRIEST: -            { -                // Blessed Recovery -                if (auraSpellInfo->SpellIconID == 1875) -                { -                    switch (auraSpellInfo->Id) -                    { -                        case 27811: trigger_spell_id = 27813; break; -                        case 27815: trigger_spell_id = 27817; break; -                        case 27816: trigger_spell_id = 27818; break; -                        default: -                            TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id); -                        return false; -                    } -                    basepoints0 = CalculatePct(int32(damage), triggerAmount) / 3; -                    target = this; -                    // Add remaining ticks to healing done -                    basepoints0 += GetRemainingPeriodicAmount(GetGUID(), trigger_spell_id, SPELL_AURA_PERIODIC_HEAL); -                } -                break; -            } -            case SPELLFAMILY_DRUID: -            { -                switch (auraSpellInfo->Id) -                { -                    // Druid Forms Trinket -                    case 37336: -                    { -                        switch (GetShapeshiftForm()) -                        { -                            case FORM_NONE:     trigger_spell_id = 37344; break; -                            case FORM_CAT:      trigger_spell_id = 37341; break; -                            case FORM_BEAR: -                            case FORM_DIREBEAR: trigger_spell_id = 37340; break; -                            case FORM_TREE:     trigger_spell_id = 37342; break; -                            case FORM_MOONKIN:  trigger_spell_id = 37343; break; -                            default: -                                return false; -                        } -                        break; -                    } -                    // Druid T9 Feral Relic (Lacerate, Swipe, Mangle, and Shred) -                    case 67353: -                    { -                        switch (GetShapeshiftForm()) -                        { -                            case FORM_CAT:      trigger_spell_id = 67355; break; -                            case FORM_BEAR: -                            case FORM_DIREBEAR: trigger_spell_id = 67354; break; -                            default: -                                return false; -                        } -                        break; -                    } -                    default: -                        break; -                } -                break; -            } -            case SPELLFAMILY_HUNTER: -            { -                if (auraSpellInfo->SpellIconID == 3247)     // Piercing Shots -                { -                    switch (auraSpellInfo->Id) -                    { -                        case 53234:  // Rank 1 -                        case 53237:  // Rank 2 -                        case 53238:  // Rank 3 -                            trigger_spell_id = 63468; -                            break; -                        default: -                            TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u miss posibly Piercing Shots", auraSpellInfo->Id); -                            return false; -                    } -                    SpellInfo const* TriggerPS = sSpellMgr->GetSpellInfo(trigger_spell_id); -                    if (!TriggerPS) -                        return false; - -                    basepoints0 = CalculatePct(int32(damage), triggerAmount) / (TriggerPS->GetMaxDuration() / TriggerPS->Effects[0].Amplitude); -                    basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), trigger_spell_id, SPELL_AURA_PERIODIC_DAMAGE); -                    break; -                } -                // Item - Hunter T9 4P Bonus -                if (auraSpellInfo->Id == 67151) -                { -                    trigger_spell_id = 68130; -                    target = this; -                    break; -                } -                break; -            } -            case SPELLFAMILY_PALADIN: -            { -                switch (auraSpellInfo->Id) -                { -                    // Soul Preserver -                    case 60510: -                    { -                        switch (getClass()) -                        { -                            case CLASS_DRUID: -                                trigger_spell_id = 60512; -                                break; -                            case CLASS_PALADIN: -                                trigger_spell_id = 60513; -                                break; -                            case CLASS_PRIEST: -                                trigger_spell_id = 60514; -                                break; -                            case CLASS_SHAMAN: -                                trigger_spell_id = 60515; -                                break; -                        } - -                        target = this; -                        break; -                    } -                    case 37657: // Lightning Capacitor -                    case 54841: // Thunder Capacitor -                    case 67712: // Item - Coliseum 25 Normal Caster Trinket -                    case 67758: // Item - Coliseum 25 Heroic Caster Trinket -                    { -                        if (!victim || !victim->IsAlive() || GetTypeId() != TYPEID_PLAYER) -                            return false; - -                        uint32 stack_spell_id = 0; -                        switch (auraSpellInfo->Id) -                        { -                            case 37657: -                                stack_spell_id = 37658; -                                trigger_spell_id = 37661; -                                break; -                            case 54841: -                                stack_spell_id = 54842; -                                trigger_spell_id = 54843; -                                break; -                            case 67712: -                                stack_spell_id = 67713; -                                trigger_spell_id = 67714; -                                break; -                            case 67758: -                                stack_spell_id = 67759; -                                trigger_spell_id = 67760; -                                break; -                        } - -                        CastSpell(this, stack_spell_id, true, NULL, triggeredByAura); - -                        Aura* dummy = GetAura(stack_spell_id); -                        if (!dummy || dummy->GetStackAmount() < triggerAmount) -                            return false; - -                        RemoveAurasDueToSpell(stack_spell_id); -                        target = victim; -                        break; -                    } -                    default: -                        // Illumination -                        if (auraSpellInfo->SpellIconID == 241) -                        { -                            if (!procSpell) -                                return false; -                            // procspell is triggered spell but we need mana cost of original cast spell -                            uint32 originalSpellId = procSpell->Id; -                            // Holy Shock heal -                            if (procSpell->SpellFamilyFlags[1] & 0x00010000) -                            { -                                switch (procSpell->Id) -                                { -                                    case 25914: originalSpellId = 20473; break; -                                    case 25913: originalSpellId = 20929; break; -                                    case 25903: originalSpellId = 20930; break; -                                    case 27175: originalSpellId = 27174; break; -                                    case 33074: originalSpellId = 33072; break; -                                    case 48820: originalSpellId = 48824; break; -                                    case 48821: originalSpellId = 48825; break; -                                    default: -                                        TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u not handled in HShock", procSpell->Id); -                                       return false; -                                } -                            } -                            SpellInfo const* originalSpell = sSpellMgr->GetSpellInfo(originalSpellId); -                            if (!originalSpell) -                            { -                                TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u unknown but selected as original in Illu", originalSpellId); -                                return false; -                            } -                            // percent stored in effect 1 (class scripts) base points -                            int32 cost = int32(originalSpell->ManaCost + CalculatePct(GetCreateMana(), originalSpell->ManaCostPercentage)); -                            basepoints0 = CalculatePct(cost, auraSpellInfo->Effects[1].CalcValue()); -                            trigger_spell_id = 20272; -                            target = this; -                        } -                        break; -                } -                break; -            } -            case SPELLFAMILY_SHAMAN: -            { -                switch (auraSpellInfo->Id) -                { -                    case 30881: // Nature's Guardian Rank 1 -                    case 30883: // Nature's Guardian Rank 2 -                    case 30884: // Nature's Guardian Rank 3 -                    case 30885: // Nature's Guardian Rank 4 -                    case 30886: // Nature's Guardian Rank 5 -                    { -                        if (HealthBelowPct(30)) -                        { -                            basepoints0 = int32(auraSpellInfo->Effects[EFFECT_0].CalcValue() * GetMaxHealth() / 100.0f); -                            target = this; -                            trigger_spell_id = 31616; -                            /// @todo Threat part -                        } -                        else -                            return false; -                        break; -                    } -                    default: -                    { -                        // Lightning Shield (overwrite non existing triggered spell call in spell.dbc -                        if (auraSpellInfo->SpellFamilyFlags[0] & 0x400) -                        { -                            trigger_spell_id = sSpellMgr->GetSpellWithRank(26364, auraSpellInfo->GetRank()); -                        } -                        // Nature's Guardian -                        else if (auraSpellInfo->SpellIconID == 2013) -                        { -                            // Check health condition - should drop to less 30% (damage deal after this!) -                            if (!HealthBelowPctDamaged(30, damage)) -                                return false; - -                             if (victim && victim->IsAlive()) -                                 victim->getThreatManager().modifyThreatPercent(this, -10); - -                            basepoints0 = int32(CountPctFromMaxHealth(triggerAmount)); -                            trigger_spell_id = 31616; -                            target = this; -                        } -                    } -                } -                break; -            } -            case SPELLFAMILY_DEATHKNIGHT: -            { -                // Acclimation -                if (auraSpellInfo->SpellIconID == 1930) -                { -                    if (!procSpell) -                        return false; -                    switch (GetFirstSchoolInMask(procSpell->GetSchoolMask())) -                    { -                        case SPELL_SCHOOL_NORMAL: -                            return false;                   // ignore -                        case SPELL_SCHOOL_HOLY:   trigger_spell_id = 50490; break; -                        case SPELL_SCHOOL_FIRE:   trigger_spell_id = 50362; break; -                        case SPELL_SCHOOL_NATURE: trigger_spell_id = 50488; break; -                        case SPELL_SCHOOL_FROST:  trigger_spell_id = 50485; break; -                        case SPELL_SCHOOL_SHADOW: trigger_spell_id = 50489; break; -                        case SPELL_SCHOOL_ARCANE: trigger_spell_id = 50486; break; -                        default: -                            return false; -                    } -                } -                // Blood Presence (Improved) -                else if (auraSpellInfo->Id == 63611) -                { -                    if (GetTypeId() != TYPEID_PLAYER) -                        return false; - -                    trigger_spell_id = 50475; -                    basepoints0 = CalculatePct(int32(damage), triggerAmount); -                } -                // Item - Death Knight T10 Melee 4P Bonus -                else if (auraSpellInfo->Id == 70656) -                { -                    if (GetTypeId() != TYPEID_PLAYER || getClass() != CLASS_DEATH_KNIGHT) -                        return false; - -                    for (uint8 i = 0; i < MAX_RUNES; ++i) -                        if (ToPlayer()->GetRuneCooldown(i) == 0) -                            return false; -                } -                break; -            } -            case SPELLFAMILY_ROGUE: -            { -                switch (auraSpellInfo->Id) -                { -                    // Rogue T10 2P bonus, should only proc on caster -                    case 70805: -                    { -                        if (victim != this) -                            return false; -                        break; -                    } -                } -                break;              }              default:                   break; @@ -8254,7 +7797,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg              float averageDmg = 0;              // now compute approximate weapon damage by formula from wowwiki.com -            if (procFlags & PROC_FLAG_DONE_OFFHAND_ATTACK) +            if (procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)                  averageDmg = (GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE)) / 2.f;              else                  averageDmg = (GetFloatValue(UNIT_FIELD_MINDAMAGE) + GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2.f; @@ -8416,13 +7959,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg              if (!target)                  return false; -            if (cooldown && target->GetTypeId() == TYPEID_PLAYER && target->GetSpellHistory()->HasCooldown(trigger_spell_id)) -                return false; -              target->CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura); - -            if (cooldown && GetTypeId() == TYPEID_PLAYER) -                GetSpellHistory()->AddCooldown(trigger_spell_id, 0, std::chrono::seconds(cooldown));              return true;          }          // Cast positive spell on enemy target @@ -8553,7 +8090,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg          case 56453:          {              // Proc only from Frost/Freezing trap activation or from Freezing Arrow (the periodic dmg proc handled elsewhere) -            if (!(procFlags & PROC_FLAG_DONE_TRAP_ACTIVATION) || !procSpell || !(procSpell->SchoolMask & SPELL_SCHOOL_MASK_FROST) || !roll_chance_i(triggerAmount)) +            if (!(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION) || !procSpell || !(procSpell->SchoolMask & SPELL_SCHOOL_MASK_FROST) || !roll_chance_i(triggerAmount))                  return false;              break;          } @@ -8600,29 +8137,23 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg          }      } -    if (cooldown && GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(trigger_spell_id)) -        return false; -      // extra attack should hit same target      if (triggerEntry->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))          target = victim;      // try detect target manually if not set      if (target == NULL) -        target = !(procFlags & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && triggerEntry->IsPositive() ? this : victim; +        target = !(procFlag & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && triggerEntry->IsPositive() ? this : victim;      if (basepoints0)          CastCustomSpell(target, trigger_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);      else          CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura); -    if (cooldown && GetTypeId() == TYPEID_PLAYER) -        GetSpellHistory()->AddCooldown(trigger_spell_id, 0, std::chrono::seconds(cooldown)); -      return true;  } -bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown) +bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* procSpell)  {      int32 scriptId = triggeredByAura->GetMiscValue(); @@ -8713,14 +8244,7 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, Au          return false;      } -    if (cooldown && GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(triggered_spell_id)) -        return false; -      CastSpell(victim, triggered_spell_id, true, castItem, triggeredByAura); - -    if (cooldown && GetTypeId() == TYPEID_PLAYER) -        GetSpellHistory()->AddCooldown(triggered_spell_id, 0, std::chrono::seconds(cooldown)); -      return true;  } @@ -11889,7 +11413,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy)              UpdateSpeed(MOVE_FLIGHT);          } -        if (!(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_MOUNTED_COMBAT)) +        if (!(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_MOUNTED_COMBAT_ALLOWED))              Dismount();      } @@ -12042,7 +11566,7 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo      }      Creature const* creatureAttacker = ToCreature(); -    if (creatureAttacker && creatureAttacker->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER) +    if (creatureAttacker && creatureAttacker->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT)          return false;      // check duel - before sanctuary checks @@ -12126,7 +11650,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co      // can't assist non-friendly targets      if (GetReactionTo(target) < REP_NEUTRAL          && target->GetReactionTo(this) < REP_NEUTRAL -        && (!ToCreature() || !(ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER))) +        && (!ToCreature() || !(ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT)))          return false;      // PvP case @@ -12160,7 +11684,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co          && !((target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_PVP)))      {          if (Creature const* creatureTarget = target->ToCreature()) -            return creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER || creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_AID_PLAYERS; +            return creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT || creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST;      }      return true;  } @@ -14254,6 +13778,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u      HealInfo healInfo = HealInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL);      ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, nullptr, &damageInfo, &healInfo); +    std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();      ProcTriggeredList procTriggered;      // Fill procTriggered list      for (AuraApplicationMap::const_iterator itr = GetAppliedAuras().begin(); itr!= GetAppliedAuras().end(); ++itr) @@ -14261,6 +13786,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u          // Do not allow auras to proc from effect triggered by itself          if (procAura && procAura->Id == itr->first)              continue; + +        if (itr->second->GetBase()->IsProcOnCooldown(now)) +            continue; +          ProcTriggeredData triggerData(itr->second->GetBase());          // Defensive procs are active on absorbs (so absorption effects are not a hindrance)          bool active = damage || (procExtra & PROC_EX_BLOCK && isVictim); @@ -14285,6 +13814,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u          if (!triggerData.aura->CallScriptCheckProcHandlers(itr->second, eventInfo))              continue; +        bool procSuccess = RollProcResult(target, triggerData.aura, attType, isVictim, triggerData.spellProcEvent); +        if (!procSuccess) +            continue; +          // Triggered spells not triggering additional spells          bool triggered = !spellProto->HasAttribute(SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED) ?              (procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION)) : false; @@ -14338,9 +13871,9 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u          bool prepare = i->aura->CallScriptPrepareProcHandlers(aurApp, eventInfo);          // For players set spell cooldown if need -        uint32 cooldown = 0; +        Milliseconds cooldown = Milliseconds::zero();          if (prepare && GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown) -            cooldown = i->spellProcEvent->cooldown; +            cooldown = Seconds(i->spellProcEvent->cooldown);          // Note: must SetCantProc(false) before return          if (spellInfo->HasAttribute(SPELL_ATTR3_DISABLE_PROC)) @@ -14349,9 +13882,9 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u          bool handled = i->aura->CallScriptProcHandlers(aurApp, eventInfo);          // "handled" is needed as long as proc can be handled in multiple places -        if (!handled && HandleAuraProc(target, damage, i->aura, procSpell, procFlag, procExtra, cooldown, &handled)) +        if (!handled && HandleAuraProc(target, damage, i->aura, procSpell, procFlag, procExtra, &handled))          { -            TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), Id); +            TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), Id);              takeCharges = true;          } @@ -14359,7 +13892,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u          {              for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)              { -                if (!(i->effMask & (1<<effIndex))) +                if (!(i->effMask & (1 << effIndex)))                      continue;                  AuraEffect* triggeredByAura = i->aura->GetEffect(effIndex); @@ -14376,9 +13909,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u                  {                      case SPELL_AURA_PROC_TRIGGER_SPELL:                      { -                        TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); +                        TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", +                            spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());                          // Don`t drop charge or add cooldown for not started trigger -                        if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) +                        if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra))                              takeCharges = true;                          break;                      } @@ -14395,7 +13929,8 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u                      case SPELL_AURA_MANA_SHIELD:                      case SPELL_AURA_DUMMY:                      { -                        TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); +                        TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", +                            spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());                          if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))                              takeCharges = true;                          break; @@ -14404,20 +13939,22 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u                      case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:                      case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:                      case SPELL_AURA_MOD_MELEE_HASTE: -                        TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, isVictim ? "a victim's" : "an attacker's", triggeredByAura->GetId()); +                        TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", +                            spellInfo->Id, isVictim ? "a victim's" : "an attacker's", triggeredByAura->GetId());                          takeCharges = true;                          break;                      case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:                      { -                        TC_LOG_DEBUG("spells", "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(target, damage, triggeredByAura, procSpell, cooldown)) +                        TC_LOG_DEBUG("spells", "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(target, damage, triggeredByAura, procSpell))                              takeCharges = true;                          break;                      }                      case SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE:                      {                          TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)", -                            (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); +                            (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());                          HandleAuraRaidProcFromChargeWithValue(triggeredByAura);                          takeCharges = true; @@ -14426,7 +13963,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u                      case SPELL_AURA_RAID_PROC_FROM_CHARGE:                      {                          TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)", -                            (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); +                            (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());                          HandleAuraRaidProcFromCharge(triggeredByAura);                          takeCharges = true; @@ -14434,9 +13971,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u                      }                      case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE:                      { -                        TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); +                        TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", +                            spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId()); -                        if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) +                        if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra))                              takeCharges = true;                          break;                      } @@ -14521,6 +14059,9 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u              } // for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)          } // if (!handled) +        if (prepare && takeCharges && cooldown != Milliseconds::zero()) +            i->aura->AddProcCooldown(now + cooldown); +          // Remove charge (aura can be removed by triggers)          if (prepare && useCharges && takeCharges)          { @@ -14549,6 +14090,8 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u  void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTriggeringProc, std::list<AuraApplication*>* procAuras, ProcEventInfo eventInfo)  { +    std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); +      // use provided list of auras which can proc      if (procAuras)      { @@ -14556,9 +14099,9 @@ void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTrigge          {              ASSERT((*itr)->GetTarget() == this);              if (!(*itr)->GetRemoveMode()) -                if ((*itr)->GetBase()->IsProcTriggeredOnEvent(*itr, eventInfo)) +                if ((*itr)->GetBase()->IsProcTriggeredOnEvent(*itr, eventInfo, now))                  { -                    (*itr)->GetBase()->PrepareProcToTrigger(*itr, eventInfo); +                    (*itr)->GetBase()->PrepareProcToTrigger(*itr, eventInfo, now);                      aurasTriggeringProc.push_back(*itr);                  }          } @@ -14568,9 +14111,9 @@ void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTrigge      {          for (AuraApplicationMap::iterator itr = GetAppliedAuras().begin(); itr!= GetAppliedAuras().end(); ++itr)          { -            if (itr->second->GetBase()->IsProcTriggeredOnEvent(itr->second, eventInfo)) +            if (itr->second->GetBase()->IsProcTriggeredOnEvent(itr->second, eventInfo, now))              { -                itr->second->GetBase()->PrepareProcToTrigger(itr->second, eventInfo); +                itr->second->GetBase()->PrepareProcToTrigger(itr->second, eventInfo, now);                  aurasTriggeringProc.push_back(itr->second);              }          } @@ -15192,23 +14735,23 @@ bool Unit::InitTamedPet(Pet* pet, uint8 level, uint32 spell_id)      return true;  } -bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const* & spellProcEvent) +bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent)  { -    SpellInfo const* spellProto = aura->GetSpellInfo(); +    SpellInfo const* spellInfo = aura->GetSpellInfo();      // let the aura be handled by new proc system if it has new entry -    if (sSpellMgr->GetSpellProcEntry(spellProto->Id)) +    if (sSpellMgr->GetSpellProcEntry(spellInfo->Id))          return false;      // Get proc Event Entry -    spellProcEvent = sSpellMgr->GetSpellProcEvent(spellProto->Id); +    spellProcEvent = sSpellMgr->GetSpellProcEvent(spellInfo->Id);      // Get EventProcFlag      uint32 EventProcFlag;      if (spellProcEvent && spellProcEvent->procFlags) // if exist get custom spellProcEvent->procFlags          EventProcFlag = spellProcEvent->procFlags;      else -        EventProcFlag = spellProto->ProcFlags;       // else get from spell proto +        EventProcFlag = spellInfo->ProcFlags;        // else get from spell proto      // Continue if no trigger exist      if (!EventProcFlag)          return false; @@ -15216,12 +14759,12 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const      // Additional checks for triggered spells (ignore trap casts)      if (procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION))      { -        if (!spellProto->HasAttribute(SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED)) +        if (!spellInfo->HasAttribute(SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED))              return false;      }      // Check spellProcEvent data requirements -    if (!sSpellMgr->IsSpellProcEventCanTriggeredBy(spellProto, spellProcEvent, EventProcFlag, procSpell, procFlag, procExtra, active)) +    if (!sSpellMgr->IsSpellProcEventCanTriggeredBy(spellInfo, spellProcEvent, EventProcFlag, procSpell, procFlag, procExtra, active))          return false;      // In most cases req get honor or XP from kill      if (EventProcFlag & PROC_FLAG_KILL && GetTypeId() == TYPEID_PLAYER) @@ -15239,15 +14782,15 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const      }      // Aura added by spell can`t trigger from self (prevent drop charges/do triggers)      // But except periodic and kill triggers (can triggered from self) -    if (procSpell && procSpell->Id == spellProto->Id -        && !(spellProto->ProcFlags&(PROC_FLAG_TAKEN_PERIODIC | PROC_FLAG_KILL))) +    if (procSpell && procSpell->Id == spellInfo->Id +        && !(spellInfo->ProcFlags&(PROC_FLAG_TAKEN_PERIODIC | PROC_FLAG_KILL)))          return false;      // Check if current equipment allows aura to proc      if (!isVictim && GetTypeId() == TYPEID_PLAYER)      {          Player* player = ToPlayer(); -        if (spellProto->EquippedItemClass == ITEM_CLASS_WEAPON) +        if (spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON)          {              Item* item = NULL;              if (attType == BASE_ATTACK) @@ -15260,19 +14803,26 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const              if (player->IsInFeralForm())                  return false; -            if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_WEAPON || !((1<<item->GetTemplate()->SubClass) & spellProto->EquippedItemSubClassMask)) +            if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_WEAPON || !((1<<item->GetTemplate()->SubClass) & spellInfo->EquippedItemSubClassMask))                  return false;          } -        else if (spellProto->EquippedItemClass == ITEM_CLASS_ARMOR) +        else if (spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR)          {              // Check if player is wearing shield              Item* item = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); -            if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_ARMOR || !((1<<item->GetTemplate()->SubClass) & spellProto->EquippedItemSubClassMask)) +            if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_ARMOR || !((1<<item->GetTemplate()->SubClass) & spellInfo->EquippedItemSubClassMask))                  return false;          }      } + +    return true; +} + +bool Unit::RollProcResult(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, SpellProcEventEntry const* spellProcEvent) +{ +    SpellInfo const* spellInfo = aura->GetSpellInfo();      // Get chance from spell -    float chance = float(spellProto->ProcChance); +    float chance = float(spellInfo->ProcChance);      // If in spellProcEvent exist custom chance, chance = spellProcEvent->customChance;      if (spellProcEvent && spellProcEvent->customChance)          chance = spellProcEvent->customChance; @@ -15282,19 +14832,18 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const          if (!isVictim)          {              uint32 weaponSpeed = GetAttackTime(attType); -            chance = GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellProto); +            chance = GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellInfo);          }          else if (victim)          {              uint32 weaponSpeed = victim->GetAttackTime(attType); -            chance = victim->GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellProto); +            chance = victim->GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellInfo);          }      }      // Apply chance modifer aura      if (Player* modOwner = GetSpellModOwner()) -    { -        modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CHANCE_OF_SUCCESS, chance); -    } +        modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CHANCE_OF_SUCCESS, chance); +      return roll_chance_f(chance);  } @@ -16300,8 +15849,8 @@ bool Unit::IsInPartyWith(Unit const* unit) const      if (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER)          return u1->ToPlayer()->IsInSameGroupWith(u2->ToPlayer()); -    else if ((u2->GetTypeId() == TYPEID_PLAYER && u1->GetTypeId() == TYPEID_UNIT && u1->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER) || -        (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_UNIT && u2->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER)) +    else if ((u2->GetTypeId() == TYPEID_PLAYER && u1->GetTypeId() == TYPEID_UNIT && u1->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT) || +        (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_UNIT && u2->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT))          return true;      else          return false; @@ -16319,8 +15868,8 @@ bool Unit::IsInRaidWith(Unit const* unit) const      if (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER)          return u1->ToPlayer()->IsInSameRaidWith(u2->ToPlayer()); -    else if ((u2->GetTypeId() == TYPEID_PLAYER && u1->GetTypeId() == TYPEID_UNIT && u1->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER) || -            (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_UNIT && u2->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER)) +    else if ((u2->GetTypeId() == TYPEID_PLAYER && u1->GetTypeId() == TYPEID_UNIT && u1->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT) || +            (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_UNIT && u2->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT))          return true;      else          return false; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index d49d2fd9842..30ef6eb394f 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1858,6 +1858,9 @@ class TC_GAME_API Unit : public WorldObject          Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;          int32 GetCurrentSpellCastTime(uint32 spell_id) const; +        // Check if our current channel spell has attribute SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING +        bool CanMoveDuringChannel() const; +          SpellHistory* GetSpellHistory() { return m_spellHistory; }          SpellHistory const* GetSpellHistory() const { return m_spellHistory; } @@ -2252,11 +2255,12 @@ class TC_GAME_API Unit : public WorldObject          void DisableSpline();      private: -        bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const* & spellProcEvent); -        bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); -        bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool * handled); -        bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); -        bool HandleOverrideClassScriptAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown); +        bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent); +        bool RollProcResult(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, SpellProcEventEntry const* spellProcEvent); +        bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, Milliseconds& cooldown); +        bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, bool* handled); +        bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx); +        bool HandleOverrideClassScriptAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell);          bool HandleAuraRaidProcFromChargeWithValue(AuraEffect* triggeredByAura);          bool HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 0976534f3ca..33a0325851a 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -5946,14 +5946,14 @@ void ObjectMgr::LoadGraveyardZones()  {      uint32 oldMSTime = getMSTime(); -    GraveYardStore.clear();                                  // need for reload case +    GraveYardStore.clear(); // need for reload case -    //                                                0       1         2 -    QueryResult result = WorldDatabase.Query("SELECT id, ghost_zone, faction FROM game_graveyard_zone"); +    //                                               0   1          2 +    QueryResult result = WorldDatabase.Query("SELECT ID, GhostZone, Faction FROM graveyard_zone");      if (!result)      { -        TC_LOG_INFO("server.loading", ">> Loaded 0 graveyard-zone links. DB table `game_graveyard_zone` is empty."); +        TC_LOG_INFO("server.loading", ">> Loaded 0 graveyard-zone links. DB table `graveyard_zone` is empty.");          return;      } @@ -5972,31 +5972,31 @@ void ObjectMgr::LoadGraveyardZones()          WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(safeLocId);          if (!entry)          { -            TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has a record for not existing graveyard (WorldSafeLocs.dbc id) %u, skipped.", safeLocId); +            TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for non-existing graveyard (WorldSafeLocsID: %u), skipped.", safeLocId);              continue;          }          AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId);          if (!areaEntry)          { -            TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has a record for not existing zone id (%u), skipped.", zoneId); +            TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for non-existing Zone (ID: %u), skipped.", zoneId);              continue;          }          if (areaEntry->zone != 0)          { -            TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has a record for subzone id (%u) instead of zone, skipped.", zoneId); +            TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for SubZone (ID: %u) instead of zone, skipped.", zoneId);              continue;          }          if (team != 0 && team != HORDE && team != ALLIANCE)          { -            TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has a record for non player faction (%u), skipped.", team); +            TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for non player faction (%u), skipped.", team);              continue;          }          if (!AddGraveYardLink(safeLocId, zoneId, team, false)) -            TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has a duplicate record for Graveyard (ID: %u) and Zone (ID: %u), skipped.", safeLocId, zoneId); +            TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` has a duplicate record for Graveyard (ID: %u) and Zone (ID: %u), skipped.", safeLocId, zoneId);      } while (result->NextRow());      TC_LOG_INFO("server.loading", ">> Loaded %u graveyard-zone links in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); @@ -6045,7 +6045,7 @@ WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(float x, float y, float      if (range.first == range.second && !map->IsBattlegroundOrArena())      {          if (zoneId != 0) // zone == 0 can't be fixed, used by bliz for bugged zones -            TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team); +            TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team);          return GetDefaultGraveYard(team);      } @@ -6071,7 +6071,7 @@ WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(float x, float y, float          WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(data.safeLocId);          if (!entry)          { -            TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has record for not existing graveyard (WorldSafeLocs.dbc id) %u, skipped.", data.safeLocId); +            TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` has record for not existing graveyard (WorldSafeLocsID %u), skipped.", data.safeLocId);              continue;          } @@ -6186,7 +6186,7 @@ void ObjectMgr::RemoveGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool      GraveYardMapBoundsNonConst range = GraveYardStore.equal_range(zoneId);      if (range.first == range.second)      { -        //TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team); +        //TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team);          return;      } diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 5cede9a32d5..390b636bb5e 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -704,7 +704,7 @@ void Loot::DeleteLootItemFromContainerItemDB(uint32 itemID)          if (_itr->itemid != itemID)              continue; -        _itr->canSave = true; +        _itr->canSave = false;          break;      }  } diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index a7fdc37d324..91a26c29150 100644 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -126,9 +126,9 @@ class TC_GAME_API MapManager          template<typename Worker>          void DoForAllMapsWithMapId(uint32 mapId, Worker&& worker); -        uint32 IncreaseScheduledScriptsCount() { return ++_scheduledScripts; } -        uint32 DecreaseScheduledScriptCount() { return --_scheduledScripts; } -        uint32 DecreaseScheduledScriptCount(size_t count) { return _scheduledScripts -= count; } +        void IncreaseScheduledScriptsCount() { ++_scheduledScripts; } +        void DecreaseScheduledScriptCount() { --_scheduledScripts; } +        void DecreaseScheduledScriptCount(std::size_t count) { _scheduledScripts -= count; }          bool IsScriptScheduled() const { return _scheduledScripts > 0; }      private: @@ -157,7 +157,7 @@ class TC_GAME_API MapManager          MapUpdater m_updater;          // atomic op counter for active scripts amount -        std::atomic<uint32> _scheduledScripts; +        std::atomic<std::size_t> _scheduledScripts;  };  template<typename Worker> diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 42eac0ead79..b9df9e3accc 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -456,7 +456,7 @@ enum SpellAttr4  enum SpellAttr5  { -    SPELL_ATTR5_UNK0                             = 0x00000001, //  0 +    SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING          = 0x00000001, //  0 available casting channel spell when moving      SPELL_ATTR5_NO_REAGENT_WHILE_PREP            = 0x00000002, //  1 not need reagents if UNIT_FLAG_PREPARATION      SPELL_ATTR5_UNK2                             = 0x00000004, //  2      SPELL_ATTR5_USABLE_WHILE_STUNNED             = 0x00000008, //  3 usable while stunned @@ -2577,38 +2577,38 @@ enum CreatureFamily  enum CreatureTypeFlags  { -    CREATURE_TYPEFLAGS_TAMEABLE         = 0x00000001,         // Tameable by any hunter -    CREATURE_TYPEFLAGS_GHOST            = 0x00000002,         // Creature are also visible for not alive player. Allow gossip interaction if npcflag allow? -    CREATURE_TYPEFLAGS_BOSS             = 0x00000004, -    CREATURE_TYPEFLAGS_UNK3             = 0x00000008, -    CREATURE_TYPEFLAGS_UNK4             = 0x00000010, -    CREATURE_TYPEFLAGS_UNK5             = 0x00000020, -    CREATURE_TYPEFLAGS_UNK6             = 0x00000040, -    CREATURE_TYPEFLAGS_DEAD_INTERACT    = 0x00000080,         // Player can interact with the creature if its dead (not player dead) -    CREATURE_TYPEFLAGS_HERBLOOT         = 0x00000100,         // Can be looted by herbalist -    CREATURE_TYPEFLAGS_MININGLOOT       = 0x00000200,         // Can be looted by miner -    CREATURE_TYPEFLAGS_DONT_LOG_DEATH   = 0x00000400,         // Death event will not show up in combat log -    CREATURE_TYPEFLAGS_MOUNTED_COMBAT   = 0x00000800,         // Creature can remain mounted when entering combat -    CREATURE_TYPEFLAGS_AID_PLAYERS      = 0x00001000,         // ? Can aid any player in combat if in range? -    CREATURE_TYPEFLAGS_UNK13            = 0x00002000, -    CREATURE_TYPEFLAGS_UNK14            = 0x00004000,         // ? Possibly not in use -    CREATURE_TYPEFLAGS_ENGINEERLOOT     = 0x00008000,         // Can be looted by engineer -    CREATURE_TYPEFLAGS_EXOTIC           = 0x00010000,         // Can be tamed by hunter as exotic pet -    CREATURE_TYPEFLAGS_UNK17            = 0x00020000,         // ? Related to vehicles/pvp? -    CREATURE_TYPEFLAGS_UNK18            = 0x00040000,         // ? Related to vehicle/siege weapons? -    CREATURE_TYPEFLAGS_PROJECTILE_COLLISION = 0x00080000,     // Projectiles can collide with this creature - interacts with TARGET_DEST_TRAJ -    CREATURE_TYPEFLAGS_UNK20            = 0x00100000, -    CREATURE_TYPEFLAGS_UNK21            = 0x00200000, -    CREATURE_TYPEFLAGS_UNK22            = 0x00400000, -    CREATURE_TYPEFLAGS_UNK23            = 0x00800000,         // ? First seen in 3.2.2. Related to banner/backpack of creature/companion? -    CREATURE_TYPEFLAGS_UNK24            = 0x01000000, -    CREATURE_TYPEFLAGS_UNK25            = 0x02000000, -    CREATURE_TYPEFLAGS_PARTY_MEMBER     = 0x04000000,         //! Creature can be targeted by spells that require target to be in caster's party/raid -    CREATURE_TYPEFLAGS_UNK27            = 0x08000000, -    CREATURE_TYPEFLAGS_UNK28            = 0x10000000, -    CREATURE_TYPEFLAGS_UNK29            = 0x20000000, -    CREATURE_TYPEFLAGS_UNK30            = 0x40000000, -    CREATURE_TYPEFLAGS_UNK31            = 0x80000000 +    CREATURE_TYPE_FLAG_TAMEABLE_PET                         = 0x00000001,   // Makes the mob tameable (must also be a beast and have family set) +    CREATURE_TYPE_FLAG_GHOST_VISIBLE                        = 0x00000002,   // Creature are also visible for not alive player. Allow gossip interaction if npcflag allow? +    CREATURE_TYPE_FLAG_BOSS_MOB                             = 0x00000004,   // Changes creature's visible level to "??" in the creature's portrait - Immune Knockback. +    CREATURE_TYPE_FLAG_DO_NOT_PLAY_WOUND_PARRY_ANIMATION    = 0x00000008, +    CREATURE_TYPE_FLAG_HIDE_FACTION_TOOLTIP                 = 0x00000010, +    CREATURE_TYPE_FLAG_UNK5                                 = 0x00000020,   // Sound related +    CREATURE_TYPE_FLAG_SPELL_ATTACKABLE                     = 0x00000040, +    CREATURE_TYPE_FLAG_CAN_INTERACT_WHILE_DEAD              = 0x00000080,   // Player can interact with the creature if its dead (not player dead) +    CREATURE_TYPE_FLAG_HERB_SKINNING_SKILL                  = 0x00000100,   // Can be looted by herbalist +    CREATURE_TYPE_FLAG_MINING_SKINNING_SKILL                = 0x00000200,   // Can be looted by miner +    CREATURE_TYPE_FLAG_DO_NOT_LOG_DEATH                     = 0x00000400,   // Death event will not show up in combat log +    CREATURE_TYPE_FLAG_MOUNTED_COMBAT_ALLOWED               = 0x00000800,   // Creature can remain mounted when entering combat +    CREATURE_TYPE_FLAG_CAN_ASSIST                           = 0x00001000,   // ? Can aid any player in combat if in range? +    CREATURE_TYPE_FLAG_IS_PET_BAR_USED                      = 0x00002000, +    CREATURE_TYPE_FLAG_MASK_UID                             = 0x00004000, +    CREATURE_TYPE_FLAG_ENGINEERING_SKINNING_SKILL           = 0x00008000,   // Can be looted by engineer +    CREATURE_TYPE_FLAG_EXOTIC_PET                           = 0x00010000,   // Can be tamed by hunter as exotic pet +    CREATURE_TYPE_FLAG_USE_DEFAULT_COLLISION_BOX            = 0x00020000,   // Collision related. (always using default collision box?) +    CREATURE_TYPE_FLAG_IS_SIEGE_WEAPON                      = 0x00040000, +    CREATURE_TYPE_FLAG_CAN_COLLIDE_WITH_MISSILES            = 0x00080000,   // Projectiles can collide with this creature - interacts with TARGET_DEST_TRAJ +    CREATURE_TYPE_FLAG_HIDE_NAME_PLATE                      = 0x00100000, +    CREATURE_TYPE_FLAG_DO_NOT_PLAY_MOUNTED_ANIMATIONS       = 0x00200000, +    CREATURE_TYPE_FLAG_IS_LINK_ALL                          = 0x00400000, +    CREATURE_TYPE_FLAG_INTERACT_ONLY_WITH_CREATOR           = 0x00800000, +    CREATURE_TYPE_FLAG_DO_NOT_PLAY_UNIT_EVENT_SOUNDS        = 0x01000000, +    CREATURE_TYPE_FLAG_HAS_NO_SHADOW_BLOB                   = 0x02000000, +    CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT                   = 0x04000000,   // ! Creature can be targeted by spells that require target to be in caster's party/raid +    CREATURE_TYPE_FLAG_FORCE_GOSSIP                         = 0x08000000,   // Allows the creature to display a single gossip option. +    CREATURE_TYPE_FLAG_DO_NOT_SHEATHE                       = 0x10000000, +    CREATURE_TYPE_FLAG_DO_NOT_TARGET_ON_INTERACTION         = 0x20000000, +    CREATURE_TYPE_FLAG_DO_NOT_RENDER_OBJECT_NAME            = 0x40000000, +    CREATURE_TYPE_FLAG_UNIT_IS_QUEST_BOSS                   = 0x80000000    // Not verified  };  enum CreatureEliteType diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 403ccf684e7..3fd3b702ba5 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -36,6 +36,9 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up      if (owner->HasUnitState(UNIT_STATE_NOT_MOVE))          return; +    if (owner->HasUnitState(UNIT_STATE_CASTING) && !owner->CanMoveDuringChannel()) +        return; +      if (owner->GetTypeId() == TYPEID_UNIT && !i_target->isInAccessiblePlaceFor(owner->ToCreature()))      {          owner->ToCreature()->SetCannotReachTarget(true); @@ -146,7 +149,7 @@ bool TargetedMovementGeneratorMedium<T, D>::DoUpdate(T* owner, uint32 time_diff)      }      // prevent movement while casting spells with cast time or channel time -    if (owner->HasUnitState(UNIT_STATE_CASTING)) +    if (owner->HasUnitState(UNIT_STATE_CASTING) && !owner->CanMoveDuringChannel())      {          if (!owner->IsStopped())              owner->StopMoving(); diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index e0daf59fcc2..02dd88e582a 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -348,7 +348,7 @@ enum AuraType      SPELL_AURA_ABILITY_PERIODIC_CRIT                        = 286,      SPELL_AURA_DEFLECT_SPELLS                               = 287,      SPELL_AURA_IGNORE_HIT_DIRECTION                         = 288, -    SPELL_AURA_289                                          = 289, +    SPELL_AURA_PREVENT_DURABILITY_LOSS                      = 289,      SPELL_AURA_MOD_CRIT_PCT                                 = 290,      SPELL_AURA_MOD_XP_QUEST_PCT                             = 291,      SPELL_AURA_OPEN_STABLE                                  = 292, diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index ffe79293430..4133d0c8d65 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -346,7 +346,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=      &AuraEffect::HandleNoImmediateEffect,                         //286 SPELL_AURA_ABILITY_PERIODIC_CRIT implemented in AuraEffect::PeriodicTick      &AuraEffect::HandleNoImmediateEffect,                         //287 SPELL_AURA_DEFLECT_SPELLS             implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult      &AuraEffect::HandleNoImmediateEffect,                         //288 SPELL_AURA_IGNORE_HIT_DIRECTION  implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult Unit::RollMeleeOutcomeAgainst -    &AuraEffect::HandleNULL,                                      //289 unused (3.2.0) +    &AuraEffect::HandleNoImmediateEffect,                         //289 SPELL_AURA_PREVENT_DURABILITY_LOSS implemented in Player::DurabilityPointsLoss      &AuraEffect::HandleAuraModCritPct,                            //290 SPELL_AURA_MOD_CRIT_PCT      &AuraEffect::HandleNoImmediateEffect,                         //291 SPELL_AURA_MOD_XP_QUEST_PCT  implemented in Player::RewardQuest      &AuraEffect::HandleAuraOpenStable,                            //292 SPELL_AURA_OPEN_STABLE diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 74a94a63594..3d35e4039ba 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -337,7 +337,8 @@ m_spellInfo(spellproto), m_casterGuid(casterGUID ? casterGUID : caster->GetGUID(  m_castItemGuid(castItem ? castItem->GetGUID() : ObjectGuid::Empty), m_applyTime(time(NULL)),  m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0),  m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1), -m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr) +m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr), +m_procCooldown(std::chrono::steady_clock::time_point::min())  {      if (m_spellInfo->ManaPerSecond || m_spellInfo->ManaPerSecondPerLevel)          m_timeCla = 1 * IN_MILLISECONDS; @@ -1851,22 +1852,17 @@ bool Aura::CanStackWith(Aura const* existingAura) const      return true;  } -bool Aura::IsProcOnCooldown() const +bool Aura::IsProcOnCooldown(std::chrono::steady_clock::time_point now) const  { -    /*if (m_procCooldown) -    { -        if (m_procCooldown > time(NULL)) -            return true; -    }*/ -    return false; +    return m_procCooldown > now;  } -void Aura::AddProcCooldown(Milliseconds /*msec*/) +void Aura::AddProcCooldown(std::chrono::steady_clock::time_point cooldownEnd)  { -    //m_procCooldown = std::chrono::steady_clock::now() + msec; +    m_procCooldown = cooldownEnd;  } -void Aura::PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo) +void Aura::PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now)  {      bool prepare = CallScriptPrepareProcHandlers(aurApp, eventInfo);      if (!prepare) @@ -1884,10 +1880,10 @@ void Aura::PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInf      ASSERT(procEntry);      // cooldowns should be added to the whole aura (see 51698 area aura) -    AddProcCooldown(procEntry->Cooldown); +    AddProcCooldown(now + procEntry->Cooldown);  } -bool Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo) const +bool Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now) const  {      SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetId());      // only auras with spell proc entry can trigger proc @@ -1899,7 +1895,7 @@ bool Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventI          return false;      // check proc cooldown -    if (IsProcOnCooldown()) +    if (IsProcOnCooldown(now))          return false;      /// @todo diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index f792581c86d..a147957f258 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -203,12 +203,12 @@ class TC_GAME_API Aura          // this subsystem is not yet in use - the core of it is functional, but still some research has to be done          // and some dependant problems fixed before it can replace old proc system (for example cooldown handling)          // currently proc system functionality is implemented in Unit::ProcDamageAndSpell -        bool IsProcOnCooldown() const; -        void AddProcCooldown(Milliseconds msec); +        bool IsProcOnCooldown(std::chrono::steady_clock::time_point now) const; +        void AddProcCooldown(std::chrono::steady_clock::time_point cooldownEnd);          bool IsUsingCharges() const { return m_isUsingCharges; }          void SetUsingCharges(bool val) { m_isUsingCharges = val; } -        void PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo); -        bool IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo) const; +        void PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now); +        bool IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now) const;          float CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const;          void TriggerProcOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo); @@ -269,6 +269,8 @@ class TC_GAME_API Aura          ChargeDropEvent* m_dropEvent; +        std::chrono::steady_clock::time_point m_procCooldown; +      private:          Unit::AuraApplicationList m_removedApplications;  }; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 60554e0717c..883f051b700 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1564,7 +1564,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex)              if (Creature* creatureTarget = unit->ToCreature())              { -                if (!(creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PROJECTILE_COLLISION)) +                if (!(creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_COLLIDE_WITH_MISSILES))                      continue;              }          } @@ -2320,8 +2320,13 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)          }      } +    bool enablePvP = false; // need to check PvP state before spell effects, but act on it afterwards +      if (spellHitTarget)      { +        // if target is flagged for pvp also flag caster if a player +        if (unit->IsPvP() && m_caster->GetTypeId() == TYPEID_PLAYER) +            enablePvP = true; // Decide on PvP flagging now, but act on it later.          SpellMissInfo missInfo2 = DoSpellHitOnUnit(spellHitTarget, mask, target->scaleAura);          if (missInfo2 != SPELL_MISS_NONE)          { @@ -2474,8 +2479,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)          // Needs to be called after dealing damage/healing to not remove breaking on damage auras          DoTriggersOnSpellHit(spellHitTarget, mask); -        // if target is fallged for pvp also flag caster if a player -        if (unit->IsPvP() && m_caster->GetTypeId() == TYPEID_PLAYER) +        if (enablePvP)              m_caster->ToPlayer()->UpdatePvP(true);          CallScriptAfterHitHandlers(); @@ -2986,12 +2990,17 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered          }      // don't allow channeled spells / spells with cast time to be cast while moving +    // exception are only channeled spells that have no casttime and SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING      // (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in)      if ((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->isMoving() && m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT)      { -        SendCastResult(SPELL_FAILED_MOVING); -        finish(false); -        return; +        // 1. Is a channel spell, 2. Has no casttime, 3. And has flag to allow movement during channel +        if (!(m_spellInfo->IsChanneled() && !m_casttime && m_spellInfo->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING))) +        { +            SendCastResult(SPELL_FAILED_MOVING); +            finish(false); +            return; +        }      }      // set timer base at cast time @@ -3219,6 +3228,10 @@ void Spell::cast(bool skipCheck)          return;      } +    if (m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET)) +        if (Creature* pet = ObjectAccessor::GetCreature(*m_caster, m_caster->GetPetGUID())) +            pet->DespawnOrUnsummon(); +      PrepareTriggersExecutedOnHit();      CallScriptOnCastHandlers(); @@ -3528,11 +3541,11 @@ void Spell::update(uint32 difftime)      // check if the player caster has moved before the spell finished      if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) && -        m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) && -        (m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR))) +        m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT && +        (m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR))))      {          // don't cancel for melee, autorepeat, triggered and instant spells -        if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered()) +        if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered() && !(IsChannelActive() && m_spellInfo->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING)))              cancel();      } @@ -5286,7 +5299,7 @@ SpellCastResult Spell::CheckCast(bool strict)                  switch (SummonProperties->Category)                  {                      case SUMMON_CATEGORY_PET: -                        if (m_caster->GetPetGUID()) +                        if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && m_caster->GetPetGUID())                              return SPELL_FAILED_ALREADY_HAVE_SUMMON;                      // intentional missing break, check both GetPetGUID() and GetCharmGUID for SUMMON_CATEGORY_PET                      case SUMMON_CATEGORY_PUPPET: @@ -5302,7 +5315,7 @@ SpellCastResult Spell::CheckCast(bool strict)                  {                      if (m_targets.GetUnitTarget()->GetTypeId() != TYPEID_PLAYER)                          return SPELL_FAILED_BAD_TARGETS; -                    if (m_targets.GetUnitTarget()->GetPetGUID()) +                    if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && m_targets.GetUnitTarget()->GetPetGUID())                          return SPELL_FAILED_ALREADY_HAVE_SUMMON;                  }                  break; @@ -5311,13 +5324,13 @@ SpellCastResult Spell::CheckCast(bool strict)              {                  if (m_caster->GetPetGUID())                  //let warlock do a replacement summon                  { -                    if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->getClass() == CLASS_WARLOCK) +                    if (m_caster->GetTypeId() == TYPEID_PLAYER)                      {                          if (strict)                         //starting cast, trigger pet stun (cast by pet so it doesn't attack player)                              if (Pet* pet = m_caster->ToPlayer()->GetPet())                                  pet->CastSpell(pet, 32752, true, NULL, NULL, pet->GetGUID());                      } -                    else +                    else if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET))                          return SPELL_FAILED_ALREADY_HAVE_SUMMON;                  } @@ -5444,7 +5457,7 @@ SpellCastResult Spell::CheckCast(bool strict)                  if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_CHARM                      || m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_POSSESS)                  { -                    if (m_caster->GetPetGUID()) +                    if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && m_caster->GetPetGUID())                          return SPELL_FAILED_ALREADY_HAVE_SUMMON;                      if (m_caster->GetCharmGUID()) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 51b6db197db..8a16812034c 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3019,6 +3019,12 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex)              //OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());              //OldSummon->SetMap(owner->GetMap());              //owner->GetMap()->Add(OldSummon->ToCreature()); +            if (OldSummon->getPetType() == SUMMON_PET) +            { +                OldSummon->SetHealth(OldSummon->GetMaxHealth()); +                OldSummon->SetPower(OldSummon->getPowerType(), +                    OldSummon->GetMaxPower(OldSummon->getPowerType())); +            }              if (owner->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled())                  owner->ToPlayer()->PetSpellInitialize(); @@ -5475,7 +5481,7 @@ void Spell::EffectActivateRune(SpellEffIndex effIndex)          for (uint32 l = 0; l + 1 < MAX_RUNES && count > 0; ++l)          {              // Check if both runes are on cd as that is the only time when this needs to come into effect -            if ((player->GetRuneCooldown(l) && player->GetCurrentRune(l) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB)) && (player->GetRuneCooldown(l+1) && player->GetCurrentRune(l+1) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB))) +            if ((player->GetRuneCooldown(l) && player->GetBaseRune(l) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB)) && (player->GetRuneCooldown(l+1) && player->GetBaseRune(l+1) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB)))              {                  // Should always update the rune with the lowest cd                  if (l + 1 < MAX_RUNES && player->GetRuneCooldown(l) >= player->GetRuneCooldown(l+1)) diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index f6078bd063f..ac157b48783 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -525,10 +525,10 @@ float SpellEffectInfo::CalcValueMultiplier(Unit* caster, Spell* spell) const  float SpellEffectInfo::CalcDamageMultiplier(Unit* caster, Spell* spell) const  { -    float multiplier = DamageMultiplier; +    float multiplierPercent = DamageMultiplier * 100.0f;      if (Player* modOwner = (caster ? caster->GetSpellModOwner() : NULL)) -        modOwner->ApplySpellMod(_spellInfo->Id, SPELLMOD_DAMAGE_MULTIPLIER, multiplier, spell); -    return multiplier; +        modOwner->ApplySpellMod(_spellInfo->Id, SPELLMOD_DAMAGE_MULTIPLIER, multiplierPercent, spell); +    return multiplierPercent / 100.0f;  }  bool SpellEffectInfo::HasRadius() const diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index eb28a8adae4..4470fa7de42 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -91,7 +91,7 @@ public:              { "disenchant_loot_template",      rbac::RBAC_PERM_COMMAND_RELOAD_DISENCHANT_LOOT_TEMPLATE,         true,  &HandleReloadLootTemplatesDisenchantCommand,    "" },              { "event_scripts",                 rbac::RBAC_PERM_COMMAND_RELOAD_EVENT_SCRIPTS,                    true,  &HandleReloadEventScriptsCommand,               "" },              { "fishing_loot_template",         rbac::RBAC_PERM_COMMAND_RELOAD_FISHING_LOOT_TEMPLATE,            true,  &HandleReloadLootTemplatesFishingCommand,       "" }, -            { "game_graveyard_zone",           rbac::RBAC_PERM_COMMAND_RELOAD_GAME_GRAVEYARD_ZONE,              true,  &HandleReloadGameGraveyardZoneCommand,          "" }, +            { "graveyard_zone",                rbac::RBAC_PERM_COMMAND_RELOAD_GRAVEYARD_ZONE,                   true,  &HandleReloadGameGraveyardZoneCommand,          "" },              { "game_tele",                     rbac::RBAC_PERM_COMMAND_RELOAD_GAME_TELE,                        true,  &HandleReloadGameTeleCommand,                   "" },              { "gameobject_questender",         rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUESTENDER,            true,  &HandleReloadGOQuestEnderCommand,               "" },              { "gameobject_loot_template",      rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUEST_LOOT_TEMPLATE,   true,  &HandleReloadLootTemplatesGameobjectCommand,    "" }, diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index d77842fff0a..73a7de36580 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -2461,6 +2461,33 @@ class spell_igb_teleport_players_on_victory : public SpellScriptLoader          }  }; +// 71201 - Battle Experience - proc should never happen, handled in script +class spell_igb_battle_experience_check : public SpellScriptLoader +{ +public: +    spell_igb_battle_experience_check() : SpellScriptLoader("spell_igb_battle_experience_check") { } + +    class spell_igb_battle_experience_check_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_igb_battle_experience_check_AuraScript); + +        bool CheckProc(ProcEventInfo& /*eventInfo*/) +        { +            return false; +        } + +        void Register() override +        { +            DoCheckProc += AuraCheckProcFn(spell_igb_battle_experience_check_AuraScript::CheckProc); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_igb_battle_experience_check_AuraScript(); +    } +}; +  class achievement_im_on_a_boat : public AchievementCriteriaScript  {      public: @@ -2500,5 +2527,6 @@ void AddSC_boss_icecrown_gunship_battle()      new spell_igb_gunship_fall_teleport();      new spell_igb_check_for_players();      new spell_igb_teleport_players_on_victory(); +    new spell_igb_battle_experience_check();      new achievement_im_on_a_boat();  } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index 05beacca638..fa59c021cad 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -171,8 +171,7 @@ enum FreyaNpcs  enum FreyaActions  { -    ACTION_ELDER_DEATH                           = 1, -    ACTION_ELDER_FREYA_KILLED                    = 2 +    ACTION_ELDER_FREYA_KILLED                    = 1  };  enum FreyaEvents @@ -619,7 +618,7 @@ class boss_freya : public CreatureScript                          Elder->AttackStop();                          Elder->CombatStop(true);                          Elder->DeleteThreatList(); -                        Elder->GetAI()->DoAction(ACTION_ELDER_FREYA_KILLED); +                        Elder->AI()->DoAction(ACTION_ELDER_FREYA_KILLED);                      }                  }              } @@ -705,19 +704,10 @@ class boss_elder_brightleaf : public CreatureScript                      Talk(SAY_ELDER_SLAY);              } -            void JustDied(Unit* killer) override +            void JustDied(Unit* /*killer*/) override              {                  _JustDied();                  Talk(SAY_ELDER_DEATH); - -                if (killer->GetTypeId() == TYPEID_PLAYER) -                { -                    if (Creature* Ironbranch = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_IRONBRANCH))) -                        Ironbranch->AI()->DoAction(ACTION_ELDER_DEATH); - -                    if (Creature* Stonebark = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_STONEBARK))) -                        Stonebark->AI()->DoAction(ACTION_ELDER_DEATH); -                }              }              void EnterCombat(Unit* /*who*/) override @@ -812,19 +802,10 @@ class boss_elder_stonebark : public CreatureScript                      Talk(SAY_ELDER_SLAY);              } -            void JustDied(Unit* killer) override +            void JustDied(Unit* /*killer*/) override              {                  _JustDied();                  Talk(SAY_ELDER_DEATH); - -                if (killer->GetTypeId() == TYPEID_PLAYER) -                { -                    if (Creature* Ironbranch = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_IRONBRANCH))) -                        Ironbranch->AI()->DoAction(ACTION_ELDER_DEATH); - -                    if (Creature* Brightleaf = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_BRIGHTLEAF))) -                        Brightleaf->AI()->DoAction(ACTION_ELDER_DEATH); -                }              }              void EnterCombat(Unit* /*who*/) override @@ -925,19 +906,10 @@ class boss_elder_ironbranch : public CreatureScript                      Talk(SAY_ELDER_SLAY);              } -            void JustDied(Unit* killer) override +            void JustDied(Unit* /*killer*/) override              {                  _JustDied();                  Talk(SAY_ELDER_DEATH); - -                if (killer->GetTypeId() == TYPEID_PLAYER) -                { -                    if (Creature* Brightleaf = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_BRIGHTLEAF))) -                        Brightleaf->AI()->DoAction(ACTION_ELDER_DEATH); - -                    if (Creature* Stonebark = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_STONEBARK))) -                        Stonebark->AI()->DoAction(ACTION_ELDER_DEATH); -                }              }              void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp index 4eafc1cd94e..adade245c2b 100644 --- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp +++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp @@ -1044,6 +1044,12 @@ public:      {          PrepareAuraScript(spell_z_check_AuraScript); +    public: +        spell_z_check_AuraScript() +        { +            _posZ = 0.0f; +        } +          void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)          {              _posZ = GetTarget()->GetPositionZ(); diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 724019a1b19..980c0db19cc 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -30,6 +30,13 @@  enum DeathKnightSpells  { +    SPELL_DK_ACCLIMATION_HOLY                   = 50490, +    SPELL_DK_ACCLIMATION_FIRE                   = 50362, +    SPELL_DK_ACCLIMATION_FROST                  = 50485, +    SPELL_DK_ACCLIMATION_ARCANE                 = 50486, +    SPELL_DK_ACCLIMATION_SHADOW                 = 50489, +    SPELL_DK_ACCLIMATION_NATURE                 = 50488, +    SPELL_DK_ADVANTAGE_T10_4P_MELEE             = 70657,      SPELL_DK_ANTI_MAGIC_SHELL_TALENT            = 51052,      SPELL_DK_BLACK_ICE_R1                       = 49140,      SPELL_DK_BLOOD_BOIL_TRIGGERED               = 65658, @@ -51,6 +58,7 @@ enum DeathKnightSpells      SPELL_DK_IMPROVED_BLOOD_PRESENCE_R1         = 50365,      SPELL_DK_IMPROVED_FROST_PRESENCE_R1         = 50384,      SPELL_DK_IMPROVED_UNHOLY_PRESENCE_R1        = 50391, +    SPELL_DK_IMPROVED_BLOOD_PRESENCE_HEAL       = 50475,      SPELL_DK_IMPROVED_BLOOD_PRESENCE_TRIGGERED  = 63611,      SPELL_DK_IMPROVED_UNHOLY_PRESENCE_TRIGGERED = 63622,      SPELL_DK_ITEM_SIGIL_VENGEFUL_HEART          = 64962, @@ -78,6 +86,141 @@ enum Misc      NPC_DK_GHOUL                                = 26125  }; +// -49200 - Acclimation +class spell_dk_acclimation : public SpellScriptLoader +{ +public: +    spell_dk_acclimation() : SpellScriptLoader("spell_dk_acclimation") { } + +    class spell_dk_acclimation_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_dk_acclimation_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_HOLY) || +                !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_FIRE) || +                !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_FROST) || +                !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_NATURE) || +                !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_SHADOW) || +                !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_ARCANE)) +                return false; +            return true; +        } + +        bool CheckProc(ProcEventInfo& eventInfo) +        { +            if (eventInfo.GetDamageInfo()) +            { +                switch (GetFirstSchoolInMask(eventInfo.GetDamageInfo()->GetSchoolMask())) +                { +                    case SPELL_SCHOOL_HOLY: +                    case SPELL_SCHOOL_FIRE: +                    case SPELL_SCHOOL_NATURE: +                    case SPELL_SCHOOL_FROST: +                    case SPELL_SCHOOL_SHADOW: +                    case SPELL_SCHOOL_ARCANE: +                        return true; +                    default: +                        break; +                } +            } + +            return false; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); +            uint32 triggerspell = 0; + +            switch (GetFirstSchoolInMask(eventInfo.GetDamageInfo()->GetSchoolMask())) +            { +                case SPELL_SCHOOL_HOLY: +                    triggerspell = SPELL_DK_ACCLIMATION_HOLY; +                    break; +                case SPELL_SCHOOL_FIRE: +                    triggerspell = SPELL_DK_ACCLIMATION_FIRE; +                    break; +                case SPELL_SCHOOL_NATURE: +                    triggerspell = SPELL_DK_ACCLIMATION_NATURE; +                    break; +                case SPELL_SCHOOL_FROST: +                    triggerspell = SPELL_DK_ACCLIMATION_FROST; +                    break; +                case SPELL_SCHOOL_SHADOW: +                    triggerspell = SPELL_DK_ACCLIMATION_SHADOW; +                    break; +                case SPELL_SCHOOL_ARCANE: +                    triggerspell = SPELL_DK_ACCLIMATION_ARCANE; +                    break; +                default: +                    return; +            } + +            if (Unit* target = eventInfo.GetActionTarget()) +                target->CastSpell(target, triggerspell, true, nullptr, aurEff); +        } + +        void Register() override +        { +            DoCheckProc += AuraCheckProcFn(spell_dk_acclimation_AuraScript::CheckProc); +            OnEffectProc += AuraEffectProcFn(spell_dk_acclimation_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_dk_acclimation_AuraScript(); +    } +}; + +// 70656 - Advantage (T10 4P Melee Bonus) +class spell_dk_advantage_t10_4p : public SpellScriptLoader +{ +public: +    spell_dk_advantage_t10_4p() : SpellScriptLoader("spell_dk_advantage_t10_4p") { } + +    class spell_dk_advantage_t10_4p_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_dk_advantage_t10_4p_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_DK_ADVANTAGE_T10_4P_MELEE)) +                return false; +            return true; +        } + +        bool CheckProc(ProcEventInfo& eventInfo) +        { +            if (Unit* caster = eventInfo.GetActor()) +            { +                if (caster->GetTypeId() != TYPEID_PLAYER || caster->getClass() != CLASS_DEATH_KNIGHT) +                    return false; + +                for (uint8 i = 0; i < MAX_RUNES; ++i) +                    if (caster->ToPlayer()->GetRuneCooldown(i) == 0) +                        return false; + +                return true; +            } + +            return false; +        } + +        void Register() override +        { +            DoCheckProc += AuraCheckProcFn(spell_dk_advantage_t10_4p_AuraScript::CheckProc); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_dk_advantage_t10_4p_AuraScript(); +    } +}; +  // 50462 - Anti-Magic Shell (on raid member)  class spell_dk_anti_magic_shell_raid : public SpellScriptLoader  { @@ -919,6 +1062,52 @@ class spell_dk_improved_blood_presence : public SpellScriptLoader          }  }; +// 63611 - Improved Blood Presence Triggered +class spell_dk_improved_blood_presence_triggered : public SpellScriptLoader +{ +public: +    spell_dk_improved_blood_presence_triggered() : SpellScriptLoader("spell_dk_improved_blood_presence_triggered") { } + +    class spell_dk_improved_blood_presence_triggered_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_dk_improved_blood_presence_triggered_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_DK_IMPROVED_BLOOD_PRESENCE_HEAL)) +                return false; +            return true; +        } + +        bool CheckProc(ProcEventInfo& eventInfo) +        { +            if (eventInfo.GetActor()->GetTypeId() == TYPEID_PLAYER) +                return true; + +            return false; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); +            if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo()) +                eventInfo.GetActor()->CastCustomSpell(SPELL_DK_IMPROVED_BLOOD_PRESENCE_HEAL, SPELLVALUE_BASE_POINT0, CalculatePct(int32(dmgInfo->GetDamage()), aurEff->GetAmount()), +                    eventInfo.GetActor(), true, nullptr, aurEff); +        } + +        void Register() override +        { +            DoCheckProc += AuraCheckProcFn(spell_dk_improved_blood_presence_triggered_AuraScript::CheckProc); +            OnEffectProc += AuraEffectProcFn(spell_dk_improved_blood_presence_triggered_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_dk_improved_blood_presence_triggered_AuraScript(); +    } +}; +  // -50384 - Improved Frost Presence  class spell_dk_improved_frost_presence : public SpellScriptLoader  { @@ -2006,6 +2195,8 @@ public:  void AddSC_deathknight_spell_scripts()  { +    new spell_dk_acclimation(); +    new spell_dk_advantage_t10_4p();      new spell_dk_anti_magic_shell_raid();      new spell_dk_anti_magic_shell_self();      new spell_dk_anti_magic_zone(); @@ -2022,6 +2213,7 @@ void AddSC_deathknight_spell_scripts()      new spell_dk_ghoul_explode();      new spell_dk_icebound_fortitude();      new spell_dk_improved_blood_presence(); +    new spell_dk_improved_blood_presence_triggered();      new spell_dk_improved_frost_presence();      new spell_dk_improved_unholy_presence();      new spell_dk_pestilence(); diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index c088ae07e66..0bf5ab01f45 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -31,6 +31,13 @@ enum DruidSpells  {      SPELL_DRUID_BEAR_FORM_PASSIVE           = 1178,      SPELL_DRUID_DIRE_BEAR_FORM_PASSIVE      = 9635, +    SPELL_DRUID_ECLIPSE_LUNAR_PROC          = 48518, +    SPELL_DRUID_ECLIPSE_SOLAR_PROC          = 48517, +    SPELL_DRUID_FORMS_TRINKET_BEAR          = 37340, +    SPELL_DRUID_FORMS_TRINKET_CAT           = 37341, +    SPELL_DRUID_FORMS_TRINKET_MOONKIN       = 37343, +    SPELL_DRUID_FORMS_TRINKET_NONE          = 37344, +    SPELL_DRUID_FORMS_TRINKET_TREE          = 37342,      SPELL_DRUID_ENRAGE                      = 5229,      SPELL_DRUID_ENRAGE_MOD_DAMAGE           = 51185,      SPELL_DRUID_ENRAGED_DEFENSE             = 70725, @@ -48,6 +55,8 @@ enum DruidSpells      SPELL_DRUID_NATURES_SPLENDOR            = 57865,      SPELL_DRUID_SURVIVAL_INSTINCTS          = 50322,      SPELL_DRUID_SAVAGE_ROAR                 = 62071, +    SPELL_DRUID_T9_FERAL_RELIC_BEAR         = 67354, +    SPELL_DRUID_T9_FERAL_RELIC_CAT          = 67355,      SPELL_DRUID_TIGER_S_FURY_ENERGIZE       = 51178  }; @@ -131,6 +140,69 @@ class spell_dru_dash : public SpellScriptLoader          }  }; +class spell_dru_eclipse : public SpellScriptLoader +{ +public: +    spell_dru_eclipse() : SpellScriptLoader("spell_dru_eclipse") { } + +    class spell_dru_eclipse_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_dru_eclipse_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_ECLIPSE_LUNAR_PROC)) +                return false; +            if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_ECLIPSE_SOLAR_PROC)) +                return false; +            return true; +        } + +        bool CheckProc(ProcEventInfo& eventInfo) +        { +            if (!eventInfo.GetSpellInfo()) +                return false; + +            if (eventInfo.GetActor()->HasAura(SPELL_DRUID_ECLIPSE_LUNAR_PROC) || eventInfo.GetActor()->HasAura(SPELL_DRUID_ECLIPSE_SOLAR_PROC)) +                return false; + +            // Triggered by Wrath? +            if (eventInfo.GetSpellInfo()->SpellFamilyFlags[0] & 1) +                return roll_chance_f(GetSpellInfo()->ProcChance * 0.6f) && _lunarProcCooldownEnd <= std::chrono::steady_clock::now(); + +            return _solarProcCooldownEnd <= std::chrono::steady_clock::now(); +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            if (eventInfo.GetSpellInfo()->SpellFamilyFlags[0] & 1) +            { +                _lunarProcCooldownEnd = std::chrono::steady_clock::now() + Seconds(aurEff->GetAmount()); +                eventInfo.GetActor()->CastSpell(eventInfo.GetActor(), SPELL_DRUID_ECLIPSE_LUNAR_PROC, TRIGGERED_FULL_MASK, nullptr, aurEff); +            } +            else +            { +                _solarProcCooldownEnd = std::chrono::steady_clock::now() + Seconds(aurEff->GetAmount()); +                eventInfo.GetActor()->CastSpell(eventInfo.GetActor(), SPELL_DRUID_ECLIPSE_SOLAR_PROC, TRIGGERED_FULL_MASK, nullptr, aurEff); +            } +        } + +        void Register() override +        { +            DoCheckProc += AuraCheckProcFn(spell_dru_eclipse_AuraScript::CheckProc); +            OnEffectProc += AuraEffectProcFn(spell_dru_eclipse_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); +        } + +        std::chrono::steady_clock::time_point _lunarProcCooldownEnd = std::chrono::steady_clock::time_point::min(); +        std::chrono::steady_clock::time_point _solarProcCooldownEnd = std::chrono::steady_clock::time_point::min(); +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_dru_eclipse_AuraScript(); +    } +}; +  // 5229 - Enrage  class spell_dru_enrage : public SpellScriptLoader  { @@ -197,6 +269,91 @@ class spell_dru_enrage : public SpellScriptLoader          }  }; +// 37336 - Druid Forms Trinket +class spell_dru_forms_trinket : public SpellScriptLoader +{ +public: +    spell_dru_forms_trinket() : SpellScriptLoader("spell_dru_forms_trinket") { } + +    class spell_dru_forms_trinket_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_dru_forms_trinket_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_BEAR) || +                !sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_CAT) || +                !sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_MOONKIN) || +                !sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_NONE) || +                !sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_TREE)) +                return false; +            return true; +        } + +        bool CheckProc(ProcEventInfo& eventInfo) +        { +            Unit* target = eventInfo.GetActor(); + +            switch (target->GetShapeshiftForm()) +            { +                case FORM_BEAR: +                case FORM_DIREBEAR: +                case FORM_CAT: +                case FORM_MOONKIN: +                case FORM_NONE: +                case FORM_TREE: +                    return true; +                default: +                    break; +            } + +            return false; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); +            Unit* target = eventInfo.GetActor(); +            uint32 triggerspell = 0; + +            switch (target->GetShapeshiftForm()) +            { +                case FORM_BEAR: +                case FORM_DIREBEAR: +                    triggerspell = SPELL_DRUID_FORMS_TRINKET_BEAR; +                    break; +                case FORM_CAT: +                    triggerspell = SPELL_DRUID_FORMS_TRINKET_CAT; +                    break; +                case FORM_MOONKIN: +                    triggerspell = SPELL_DRUID_FORMS_TRINKET_MOONKIN; +                    break; +                case FORM_NONE: +                    triggerspell = SPELL_DRUID_FORMS_TRINKET_NONE; +                    break; +                case FORM_TREE: +                    triggerspell = SPELL_DRUID_FORMS_TRINKET_TREE; +                    break; +                default: +                    return; +            } + +            target->CastSpell(target, triggerspell, true, nullptr, aurEff); +        } + +        void Register() override +        { +            DoCheckProc += AuraCheckProcFn(spell_dru_forms_trinket_AuraScript::CheckProc); +            OnEffectProc += AuraEffectProcFn(spell_dru_forms_trinket_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_dru_forms_trinket_AuraScript(); +    } +}; +  // 54846 - Glyph of Starfire  class spell_dru_glyph_of_starfire : public SpellScriptLoader  { @@ -1079,6 +1236,77 @@ class spell_dru_typhoon : public SpellScriptLoader          }  }; +// 67353 - T9 Feral Relic (Idol of Mutilation) +class spell_dru_t9_feral_relic : public SpellScriptLoader +{ +public: +    spell_dru_t9_feral_relic() : SpellScriptLoader("spell_dru_t9_feral_relic") { } + +    class spell_dru_t9_feral_relic_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_dru_t9_feral_relic_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_T9_FERAL_RELIC_BEAR) || +                !sSpellMgr->GetSpellInfo(SPELL_DRUID_T9_FERAL_RELIC_CAT)) +                return false; +            return true; +        } + +        bool CheckProc(ProcEventInfo& eventInfo) +        { +            Unit* target = eventInfo.GetActor(); + +            switch (target->GetShapeshiftForm()) +            { +                case FORM_BEAR: +                case FORM_DIREBEAR: +                case FORM_CAT: +                    return true; +                default: +                    break; +            } + +            return false; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); +            uint32 triggerspell = 0; + +            Unit* target = eventInfo.GetActor(); + +            switch (target->GetShapeshiftForm()) +            { +                case FORM_BEAR: +                case FORM_DIREBEAR: +                    triggerspell = SPELL_DRUID_T9_FERAL_RELIC_BEAR; +                    break; +                case FORM_CAT: +                    triggerspell = SPELL_DRUID_T9_FERAL_RELIC_CAT; +                    break; +                default: +                    return; +            } + +            target->CastSpell(target, triggerspell, true, nullptr, aurEff); +        } + +        void Register() override +        { +            DoCheckProc += AuraCheckProcFn(spell_dru_t9_feral_relic_AuraScript::CheckProc); +            OnEffectProc += AuraEffectProcFn(spell_dru_t9_feral_relic_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_dru_t9_feral_relic_AuraScript(); +    } +}; +  // 70691 - Item T10 Restoration 4P Bonus  class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader  { @@ -1208,7 +1436,9 @@ void AddSC_druid_spell_scripts()  {      new spell_dru_bear_form_passive();      new spell_dru_dash(); +    new spell_dru_eclipse();      new spell_dru_enrage(); +    new spell_dru_forms_trinket();      new spell_dru_glyph_of_starfire();      new spell_dru_idol_lifebloom();      new spell_dru_innervate(); @@ -1230,6 +1460,7 @@ void AddSC_druid_spell_scripts()      new spell_dru_flight_form();      new spell_dru_tiger_s_fury();      new spell_dru_typhoon(); +    new spell_dru_t9_feral_relic();      new spell_dru_t10_restoration_4p_bonus();      new spell_dru_wild_growth();  } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 8b8c5300a9e..233819b04e8 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -430,6 +430,61 @@ class spell_gen_bandage : public SpellScriptLoader          }  }; +// Blood Reserve - 64568 +enum BloodReserve +{ +    SPELL_GEN_BLOOD_RESERVE_AURA = 64568, +    SPELL_GEN_BLOOD_RESERVE_HEAL = 64569 +}; + +class spell_gen_blood_reserve : public SpellScriptLoader +{ +    public: +        spell_gen_blood_reserve() : SpellScriptLoader("spell_gen_blood_reserve") { } + +        class spell_gen_blood_reserve_AuraScript : public AuraScript +        { +            PrepareAuraScript(spell_gen_blood_reserve_AuraScript); + +            bool Validate(SpellInfo const* /*spellInfo*/) override +            { +                if (!sSpellMgr->GetSpellInfo(SPELL_GEN_BLOOD_RESERVE_HEAL)) +                    return false; +                return true; +            } + +            bool CheckProc(ProcEventInfo& eventInfo) +            { +                if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo()) +                    if (Unit* caster = eventInfo.GetActionTarget()) +                        if (caster->HealthBelowPctDamaged(35, dmgInfo->GetDamage())) +                            return true; + +                return false; +            } + +            void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +            { +                PreventDefaultAction(); + +                Unit* caster = eventInfo.GetActionTarget(); +                caster->CastCustomSpell(SPELL_GEN_BLOOD_RESERVE_HEAL, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), caster, TRIGGERED_FULL_MASK, nullptr, aurEff); +                caster->RemoveAura(SPELL_GEN_BLOOD_RESERVE_AURA); +            } + +            void Register() override +            { +                DoCheckProc += AuraCheckProcFn(spell_gen_blood_reserve_AuraScript::CheckProc); +                OnEffectProc += AuraEffectProcFn(spell_gen_blood_reserve_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +            } +        }; + +        AuraScript* GetAuraScript() const override +        { +            return new spell_gen_blood_reserve_AuraScript(); +        } +}; +  enum Bonked  {      SPELL_BONKED            = 62991, @@ -4199,6 +4254,7 @@ void AddSC_generic_spell_scripts()      new spell_gen_aura_service_uniform();      new spell_gen_av_drekthar_presence();      new spell_gen_bandage(); +    new spell_gen_blood_reserve();      new spell_gen_bonked();      new spell_gen_break_shield("spell_gen_break_shield");      new spell_gen_break_shield("spell_gen_tournament_counterattack"); diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 82d9d134445..0e952818a2f 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -51,9 +51,11 @@ enum HunterSpells      SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_TRIGGERED = 54114,      SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_DEBUFF    = 55711,      SPELL_HUNTER_PET_CARRION_FEEDER_TRIGGERED       = 54045, +    SPELL_HUNTER_PIERCING_SHOTS                     = 63468,      SPELL_HUNTER_READINESS                          = 23989,      SPELL_HUNTER_SNIPER_TRAINING_R1                 = 53302,      SPELL_HUNTER_SNIPER_TRAINING_BUFF_R1            = 64418, +    SPELL_HUNTER_T9_4P_GREATNESS                    = 68130,      SPELL_HUNTER_VICIOUS_VIPER                      = 61609,      SPELL_HUNTER_VIPER_ATTACK_SPEED                 = 60144,      SPELL_DRAENEI_GIFT_OF_THE_NAARU                 = 59543 @@ -704,6 +706,63 @@ class spell_hun_pet_heart_of_the_phoenix : public SpellScriptLoader          }  }; +// -53234  - Piercing Shots +class spell_hun_piercing_shots : public SpellScriptLoader +{ +public: +    spell_hun_piercing_shots() : SpellScriptLoader("spell_hun_piercing_shots") { } + +    class spell_hun_piercing_shots_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_hun_piercing_shots_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_PIERCING_SHOTS)) +                return false; +            return true; +        } + +        bool CheckProc(ProcEventInfo& eventInfo) +        { +            if (eventInfo.GetActionTarget()) +                return true; +            return false; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); +            Unit* caster = eventInfo.GetActor(); +            Unit* target = eventInfo.GetActionTarget(); + +            if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo()) +            { +                SpellInfo const* piercingShots = sSpellMgr->AssertSpellInfo(SPELL_HUNTER_PIERCING_SHOTS); +                int32 duration = piercingShots->GetMaxDuration(); +                uint32 amplitude = piercingShots->Effects[EFFECT_0].Amplitude; +                uint32 dmg = dmgInfo->GetDamage(); + +                uint32 bp = CalculatePct(int32(dmg), aurEff->GetAmount()) / (duration / int32(amplitude)); +                bp += target->GetRemainingPeriodicAmount(target->GetGUID(), SPELL_HUNTER_PIERCING_SHOTS, SPELL_AURA_PERIODIC_DAMAGE); + +                caster->CastCustomSpell(SPELL_HUNTER_PIERCING_SHOTS, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, aurEff); +            } +        } + +        void Register() override +        { +            DoCheckProc += AuraCheckProcFn(spell_hun_piercing_shots_AuraScript::CheckProc); +            OnEffectProc += AuraEffectProcFn(spell_hun_piercing_shots_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_hun_piercing_shots_AuraScript(); +    } +}; +  // 56654, 58882 - Rapid Recuperation  class spell_hun_rapid_recuperation : public SpellScriptLoader  { @@ -967,6 +1026,51 @@ class spell_hun_target_only_pet_and_owner : public SpellScriptLoader          }  }; +// 67151   - T9 4P Bonus +class spell_hun_t9_4p_bonus : public SpellScriptLoader +{ +public: +    spell_hun_t9_4p_bonus() : SpellScriptLoader("spell_hun_t9_4p_bonus") { } + +    class spell_hun_t9_4p_bonus_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_hun_t9_4p_bonus_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_T9_4P_GREATNESS)) +                return false; +            return true; +        } + +        bool CheckProc(ProcEventInfo& eventInfo) +        { +            if (eventInfo.GetActor()->GetTypeId() == TYPEID_PLAYER && eventInfo.GetActor()->ToPlayer()->GetPet()) +                return true; +            return false; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); +            Unit* caster = eventInfo.GetActor(); + +            caster->CastSpell(caster->ToPlayer()->GetPet(), SPELL_HUNTER_T9_4P_GREATNESS, true, nullptr, aurEff); +        } + +        void Register() override +        { +            DoCheckProc += AuraCheckProcFn(spell_hun_t9_4p_bonus_AuraScript::CheckProc); +            OnEffectProc += AuraEffectProcFn(spell_hun_t9_4p_bonus_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_hun_t9_4p_bonus_AuraScript(); +    } +}; +  // 60144 - Viper Attack Speed  class spell_hun_viper_attack_speed : public SpellScriptLoader  { @@ -1025,11 +1129,13 @@ void AddSC_hunter_spell_scripts()      new spell_hun_misdirection_proc();      new spell_hun_pet_carrion_feeder();      new spell_hun_pet_heart_of_the_phoenix(); +    new spell_hun_piercing_shots();      new spell_hun_rapid_recuperation();      new spell_hun_readiness();      new spell_hun_scatter_shot();      new spell_hun_sniper_training();      new spell_hun_tame_beast();      new spell_hun_target_only_pet_and_owner(); +    new spell_hun_t9_4p_bonus();      new spell_hun_viper_attack_speed();  } diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 84c67bad63b..f7c2cefa202 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -2731,6 +2731,70 @@ public:      }  }; +enum SoulPreserver +{ +    SPELL_SOUL_PRESERVER_DRUID       = 60512, +    SPELL_SOUL_PRESERVER_PALADIN     = 60513, +    SPELL_SOUL_PRESERVER_PRIEST      = 60514, +    SPELL_SOUL_PRESERVER_SHAMAN      = 60515, +}; + +class spell_item_soul_preserver : public SpellScriptLoader +{ +public: +    spell_item_soul_preserver() : SpellScriptLoader("spell_item_soul_preserver") { } + +    class spell_item_soul_preserver_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_item_soul_preserver_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_SOUL_PRESERVER_DRUID) || +                !sSpellMgr->GetSpellInfo(SPELL_SOUL_PRESERVER_PALADIN) || +                !sSpellMgr->GetSpellInfo(SPELL_SOUL_PRESERVER_PRIEST) || +                !sSpellMgr->GetSpellInfo(SPELL_SOUL_PRESERVER_SHAMAN)) +                return false; +            return true; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); + +            Unit* caster = eventInfo.GetActor(); + +            switch (caster->getClass()) +            { +                case CLASS_DRUID: +                    caster->CastSpell(caster, SPELL_SOUL_PRESERVER_DRUID, true, nullptr, aurEff); +                    break; +                case CLASS_PALADIN: +                    caster->CastSpell(caster, SPELL_SOUL_PRESERVER_PALADIN, true, nullptr, aurEff); +                    break; +                case CLASS_PRIEST: +                    caster->CastSpell(caster, SPELL_SOUL_PRESERVER_PRIEST, true, nullptr, aurEff); +                    break; +                case CLASS_SHAMAN: +                    caster->CastSpell(caster, SPELL_SOUL_PRESERVER_SHAMAN, true, nullptr, aurEff); +                    break; +                default: +                    break; +            } +        } + +        void Register() override +        { +            OnEffectProc += AuraEffectProcFn(spell_item_soul_preserver_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_item_soul_preserver_AuraScript(); +    } +}; +  class spell_item_toy_train_set_pulse : public SpellScriptLoader  {  public: @@ -2768,6 +2832,336 @@ public:      }  }; +enum DeathChoiceSpells +{ +    SPELL_DEATH_CHOICE_NORMAL_AURA      = 67702, +    SPELL_DEATH_CHOICE_NORMAL_AGILITY   = 67703, +    SPELL_DEATH_CHOICE_NORMAL_STRENGTH  = 67708, +    SPELL_DEATH_CHOICE_HEROIC_AURA      = 67771, +    SPELL_DEATH_CHOICE_HEROIC_AGILITY   = 67772, +    SPELL_DEATH_CHOICE_HEROIC_STRENGTH  = 67773 +}; + +class spell_item_death_choice : public SpellScriptLoader +{ +public: +    spell_item_death_choice() : SpellScriptLoader("spell_item_death_choice") { } + +    class spell_item_death_choice_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_item_death_choice_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_DEATH_CHOICE_NORMAL_STRENGTH) || +                !sSpellMgr->GetSpellInfo(SPELL_DEATH_CHOICE_NORMAL_AGILITY) || +                !sSpellMgr->GetSpellInfo(SPELL_DEATH_CHOICE_HEROIC_STRENGTH) || +                !sSpellMgr->GetSpellInfo(SPELL_DEATH_CHOICE_HEROIC_AGILITY)) +                return false; +            return true; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); + +            Unit* caster = eventInfo.GetActor(); +            float str = caster->GetStat(STAT_STRENGTH); +            float agi = caster->GetStat(STAT_AGILITY); + +            switch (aurEff->GetId()) +            { +                case SPELL_DEATH_CHOICE_NORMAL_AURA: +                { +                    if (str > agi) +                        caster->CastSpell(caster, SPELL_DEATH_CHOICE_NORMAL_STRENGTH, true, nullptr, aurEff); +                    else +                        caster->CastSpell(caster, SPELL_DEATH_CHOICE_NORMAL_AGILITY, true, nullptr, aurEff); +                    break; +                } +                case SPELL_DEATH_CHOICE_HEROIC_AURA: +                { +                    if (str > agi) +                        caster->CastSpell(caster, SPELL_DEATH_CHOICE_HEROIC_STRENGTH, true, nullptr, aurEff); +                    else +                        caster->CastSpell(caster, SPELL_DEATH_CHOICE_HEROIC_AGILITY, true, nullptr, aurEff); +                    break; +                } +                default: +                    break; +            } +        } + +        void Register() override +        { +            OnEffectProc += AuraEffectProcFn(spell_item_death_choice_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_item_death_choice_AuraScript(); +    } +}; + +enum TrinketStackSpells +{ +    SPELL_LIGHTNING_CAPACITOR_AURA              = 37657,  // Lightning Capacitor +    SPELL_LIGHTNING_CAPACITOR_STACK             = 37658, +    SPELL_LIGHTNING_CAPACITOR_TRIGGER           = 37661, +    SPELL_THUNDER_CAPACITOR_AURA                = 54841,  // Thunder Capacitor +    SPELL_THUNDER_CAPACITOR_STACK               = 54842, +    SPELL_THUNDER_CAPACITOR_TRIGGER             = 54843, +    SPELL_TOC25_CASTER_TRINKET_NORMAL_AURA      = 67712,  // Item - Coliseum 25 Normal Caster Trinket +    SPELL_TOC25_CASTER_TRINKET_NORMAL_STACK     = 67713, +    SPELL_TOC25_CASTER_TRINKET_NORMAL_TRIGGER   = 67714, +    SPELL_TOC25_CASTER_TRINKET_HEROIC_AURA      = 67758,  // Item - Coliseum 25 Heroic Caster Trinket +    SPELL_TOC25_CASTER_TRINKET_HEROIC_STACK     = 67759, +    SPELL_TOC25_CASTER_TRINKET_HEROIC_TRIGGER   = 67760, +}; + +class spell_item_trinket_stack : public SpellScriptLoader +{ +public: +    spell_item_trinket_stack(char const* scriptName, uint32 stackSpell, uint32 triggerSpell) : SpellScriptLoader(scriptName), +        _stackSpell(stackSpell), _triggerSpell(triggerSpell) +    { +    } + +    class spell_item_trinket_stack_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_item_trinket_stack_AuraScript); + +    public: +        spell_item_trinket_stack_AuraScript(uint32 stackSpell, uint32 triggerSpell) : _stackSpell(stackSpell), _triggerSpell(triggerSpell) +        { +        } + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(_stackSpell) || !sSpellMgr->GetSpellInfo(_triggerSpell)) +                return false; +            return true; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); + +            Unit* caster = eventInfo.GetActor(); + +            caster->CastSpell(caster, _stackSpell, true, nullptr, aurEff); // cast the stack + +            Aura* dummy = caster->GetAura(_stackSpell); // retrieve aura + +            //dont do anything if it's not the right amount of stacks; +            if (!dummy || dummy->GetStackAmount() < aurEff->GetAmount()) +                return; + +            // if right amount, remove the aura and cast real trigger +            caster->RemoveAurasDueToSpell(_stackSpell); +            if (Unit* target = eventInfo.GetActionTarget()) +                caster->CastSpell(target, _triggerSpell, true, nullptr, aurEff); +        } + +        void Register() override +        { +            OnEffectProc += AuraEffectProcFn(spell_item_trinket_stack_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } + +    private: +        uint32 _stackSpell; +        uint32 _triggerSpell; +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_item_trinket_stack_AuraScript(_stackSpell, _triggerSpell); +    } + +private: +    uint32 _stackSpell; +    uint32 _triggerSpell; +}; + +// 57345 - Darkmoon Card: Greatness +enum DarkmoonCardSpells +{ +    SPELL_DARKMOON_CARD_STRENGHT        = 60229, +    SPELL_DARKMOON_CARD_AGILITY         = 60233, +    SPELL_DARKMOON_CARD_INTELLECT       = 60234, +    SPELL_DARKMOON_CARD_SPIRIT          = 60235, +}; + +class spell_item_darkmoon_card_greatness : public SpellScriptLoader +{ +public: +    spell_item_darkmoon_card_greatness() : SpellScriptLoader("spell_item_darkmoon_card_greatness") { } + +    class spell_item_darkmoon_card_greatness_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_item_darkmoon_card_greatness_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_DARKMOON_CARD_STRENGHT) || +                !sSpellMgr->GetSpellInfo(SPELL_DARKMOON_CARD_AGILITY) || +                !sSpellMgr->GetSpellInfo(SPELL_DARKMOON_CARD_INTELLECT) || +                !sSpellMgr->GetSpellInfo(SPELL_DARKMOON_CARD_SPIRIT)) +                return false; +            return true; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); + +            Unit* caster = eventInfo.GetActor(); +            float str = caster->GetStat(STAT_STRENGTH); +            float agi = caster->GetStat(STAT_AGILITY); +            float intl = caster->GetStat(STAT_INTELLECT); +            float spi = caster->GetStat(STAT_SPIRIT); +            float stat = 0.0f; + +            uint32 spellTrigger = SPELL_DARKMOON_CARD_STRENGHT; + +           if (str > stat) +           { +               spellTrigger = SPELL_DARKMOON_CARD_STRENGHT; +               stat = str; +           } + +           if (agi > stat) +           { +               spellTrigger = SPELL_DARKMOON_CARD_AGILITY; +               stat = agi; +           } + +           if (intl > stat) +           { +               spellTrigger = SPELL_DARKMOON_CARD_INTELLECT; +               stat = intl; +           } + +           if (spi > stat) +           { +               spellTrigger = SPELL_DARKMOON_CARD_SPIRIT; +               stat = spi; +           } + +           caster->CastSpell(caster, spellTrigger, true, nullptr, aurEff); +        } + +        void Register() override +        { +            OnEffectProc += AuraEffectProcFn(spell_item_darkmoon_card_greatness_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_item_darkmoon_card_greatness_AuraScript(); +    } +}; + +// 43820 - Amani Charm of the Witch Doctor +enum CharmWitchDoctor +{ +    SPELL_CHARM_WITCH_DOCTOR_PROC = 43821 +}; + +class spell_item_charm_witch_doctor : public SpellScriptLoader +{ +public: +    spell_item_charm_witch_doctor() : SpellScriptLoader("spell_item_charm_witch_doctor") { } + +    class spell_item_charm_witch_doctor_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_item_charm_witch_doctor_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_CHARM_WITCH_DOCTOR_PROC)) +                return false; +            return true; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); + +            Unit* caster = eventInfo.GetActor(); +            Unit* target = eventInfo.GetActionTarget(); + +            if (target) +            { +                int32 bp = CalculatePct(target->GetCreateHealth(),aurEff->GetSpellInfo()->Effects[1].CalcValue()); +                caster->CastCustomSpell(target, SPELL_CHARM_WITCH_DOCTOR_PROC, &bp, nullptr, nullptr, true, nullptr, aurEff); +            } +        } + +        void Register() override +        { +            OnEffectProc += AuraEffectProcFn(spell_item_charm_witch_doctor_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_item_charm_witch_doctor_AuraScript(); +    } +}; + +// 27522,40336 - Mana Drain +enum ManaDrainSpells +{ +    SPELL_MANA_DRAIN_ENERGIZE = 29471, +    SPELL_MANA_DRAIN_LEECH    = 27526 +}; + +class spell_item_mana_drain : public SpellScriptLoader +{ +public: +    spell_item_mana_drain() : SpellScriptLoader("spell_item_mana_drain") { } + +    class spell_item_mana_drain_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_item_mana_drain_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_MANA_DRAIN_ENERGIZE) +                || !sSpellMgr->GetSpellInfo(SPELL_MANA_DRAIN_LEECH)) +                return false; +            return true; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); + +            Unit* caster = eventInfo.GetActor(); +            Unit* target = eventInfo.GetActionTarget(); + +            if (caster->IsAlive()) +                caster->CastSpell(caster, SPELL_MANA_DRAIN_ENERGIZE, true, nullptr, aurEff); + +            if (target && target->IsAlive()) +                caster->CastSpell(target, SPELL_MANA_DRAIN_LEECH, true, nullptr, aurEff); +        } + +        void Register() override +        { +            OnEffectProc += AuraEffectProcFn(spell_item_mana_drain_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_item_mana_drain_AuraScript(); +    } +}; +  void AddSC_item_spell_scripts()  {      // 23074 Arcanite Dragonling @@ -2838,5 +3232,14 @@ void AddSC_item_spell_scripts()      new spell_item_chicken_cover();      new spell_item_muisek_vessel();      new spell_item_greatmothers_soulcatcher(); +    new spell_item_soul_preserver();      new spell_item_toy_train_set_pulse(); +    new spell_item_death_choice(); +    new spell_item_trinket_stack("spell_item_lightning_capacitor", SPELL_LIGHTNING_CAPACITOR_STACK, SPELL_LIGHTNING_CAPACITOR_TRIGGER); +    new spell_item_trinket_stack("spell_item_thunder_capacitor", SPELL_THUNDER_CAPACITOR_STACK, SPELL_THUNDER_CAPACITOR_TRIGGER); +    new spell_item_trinket_stack("spell_item_toc25_normal_caster_trinket", SPELL_TOC25_CASTER_TRINKET_NORMAL_STACK, SPELL_TOC25_CASTER_TRINKET_NORMAL_TRIGGER); +    new spell_item_trinket_stack("spell_item_toc25_heroic_caster_trinket", SPELL_TOC25_CASTER_TRINKET_HEROIC_STACK, SPELL_TOC25_CASTER_TRINKET_HEROIC_TRIGGER); +    new spell_item_darkmoon_card_greatness(); +    new spell_item_charm_witch_doctor(); +    new spell_item_mana_drain();  } diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index 2f4e4fa6f44..bacbe31630c 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -29,6 +29,7 @@  enum MageSpells  { +    SPELL_MAGE_BLAZING_SPEED                     = 31643,      SPELL_MAGE_BURNOUT                           = 29077,      SPELL_MAGE_COLD_SNAP                         = 11958,      SPELL_MAGE_FOCUS_MAGIC_PROC                  = 54648, @@ -116,6 +117,42 @@ class spell_mage_blast_wave : public SpellScriptLoader          }  }; +// -31641 - Blazing Speed +class spell_mage_blazing_speed : public SpellScriptLoader +{ +public: +    spell_mage_blazing_speed() : SpellScriptLoader("spell_mage_blazing_speed") { } + +    class spell_mage_blazing_speed_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_mage_blazing_speed_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_BLAZING_SPEED)) +                return false; +            return true; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); +            if (Unit* target = eventInfo.GetActionTarget()) +                target->CastSpell(target, SPELL_MAGE_BLAZING_SPEED, true, nullptr, aurEff); +        } + +        void Register() override +        { +            OnEffectProc += AuraEffectProcFn(spell_mage_blazing_speed_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_mage_blazing_speed_AuraScript(); +    } +}; +  // -44449 - Burnout  class spell_mage_burnout : public SpellScriptLoader  { @@ -647,6 +684,7 @@ class spell_mage_summon_water_elemental : public SpellScriptLoader  void AddSC_mage_spell_scripts()  {      new spell_mage_blast_wave(); +    new spell_mage_blazing_speed();      new spell_mage_burnout();      new spell_mage_cold_snap();      new spell_mage_fire_frost_ward(); diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index d9fd36f5fd4..eed84d4ff6b 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -37,6 +37,7 @@ enum PaladinSpells      SPELL_PALADIN_HOLY_SHOCK_R1                  = 20473,      SPELL_PALADIN_HOLY_SHOCK_R1_DAMAGE           = 25912,      SPELL_PALADIN_HOLY_SHOCK_R1_HEALING          = 25914, +    SPELL_PALADIN_ILLUMINATION_ENERGIZE          = 20272,      SPELL_PALADIN_BLESSING_OF_LOWER_CITY_DRUID   = 37878,      SPELL_PALADIN_BLESSING_OF_LOWER_CITY_PALADIN = 37879, @@ -871,6 +872,61 @@ class spell_pal_holy_shock : public SpellScriptLoader          }  }; +// -20210 - Illumination +class spell_pal_illumination : public SpellScriptLoader +{ +public: +    spell_pal_illumination() : SpellScriptLoader("spell_pal_illumination") { } + +    class spell_pal_illumination_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_pal_illumination_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_HOLY_SHOCK_R1_HEALING) || +                !sSpellMgr->GetSpellInfo(SPELL_PALADIN_ILLUMINATION_ENERGIZE) || +                !sSpellMgr->GetSpellInfo(SPELL_PALADIN_HOLY_SHOCK_R1)) +                return false; +            return true; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); + +            // this script is valid only for the Holy Shock procs of illumination +            if (eventInfo.GetHealInfo() && eventInfo.GetHealInfo()->GetSpellInfo()) +            { +                if (eventInfo.GetHealInfo()->GetSpellInfo()->SpellFamilyFlags[1] & 0x00010000) +                { +                    PreventDefaultAction(); +                    Unit* target = eventInfo.GetActor(); // Paladin is the target of the energize + +                    // proc comes from the Holy Shock heal, need to get mana cost of original spell +                    uint32 originalspellid = sSpellMgr->GetSpellWithRank(SPELL_PALADIN_HOLY_SHOCK_R1, eventInfo.GetHealInfo()->GetSpellInfo()->GetRank()); +                    SpellInfo const* originalSpell = sSpellMgr->GetSpellInfo(originalspellid); +                    if (originalSpell && aurEff->GetSpellInfo()) +                    { +                        uint32 bp = CalculatePct(originalSpell->CalcPowerCost(target, originalSpell->GetSchoolMask()), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()); +                        target->CastCustomSpell(SPELL_PALADIN_ILLUMINATION_ENERGIZE, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, aurEff); +                    } +                } +            } +        } + +        void Register() override +        { +            OnEffectProc += AuraEffectProcFn(spell_pal_illumination_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_pal_illumination_AuraScript(); +    } +}; +  // Maybe this is incorrect  // These spells should always be cast on login, regardless of whether the player has the talent or not @@ -1393,6 +1449,7 @@ void AddSC_paladin_spell_scripts()      new spell_pal_hand_of_sacrifice();      new spell_pal_hand_of_salvation();      new spell_pal_holy_shock(); +    new spell_pal_illumination();      new spell_pal_improved_aura("spell_pal_improved_concentraction_aura", SPELL_PALADIN_IMPROVED_CONCENTRACTION_AURA);      new spell_pal_improved_aura("spell_pal_improved_devotion_aura", SPELL_PALADIN_IMPROVED_DEVOTION_AURA);      new spell_pal_improved_aura("spell_pal_sanctified_retribution", SPELL_PALADIN_SANCTIFIED_RETRIBUTION_AURA); diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 51f03346df1..9e2d265aa9c 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -29,6 +29,7 @@  enum PriestSpells  { +    SPELL_PRIEST_BLESSED_RECOVERY_R1                = 27813,      SPELL_PRIEST_DIVINE_AEGIS                       = 47753,      SPELL_PRIEST_EMPOWERED_RENEW                    = 63544,      SPELL_PRIEST_GLYPH_OF_CIRCLE_OF_HEALING         = 55675, @@ -88,6 +89,50 @@ class RaidCheck          Unit const* _caster;  }; +// -27811 - Blessed Recovery +class spell_pri_blessed_recovery : public SpellScriptLoader +{ +public: +    spell_pri_blessed_recovery() : SpellScriptLoader("spell_pri_blessed_recovery") { } + +    class spell_pri_blessed_recovery_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_pri_blessed_recovery_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_BLESSED_RECOVERY_R1)) +                return false; +            return true; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); +            if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo()) +            { +                if (Unit* target = eventInfo.GetActionTarget()) +                { +                    uint32 triggerSpell = sSpellMgr->GetSpellWithRank(SPELL_PRIEST_BLESSED_RECOVERY_R1, aurEff->GetSpellInfo()->GetRank()); +                    uint32 bp = CalculatePct(int32(dmgInfo->GetDamage()), aurEff->GetAmount()) / 3; +                    bp += target->GetRemainingPeriodicAmount(target->GetGUID(), triggerSpell, SPELL_AURA_PERIODIC_HEAL); +                    target->CastCustomSpell(triggerSpell, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, aurEff); +                } +            } +        } + +        void Register() override +        { +            OnEffectProc += AuraEffectProcFn(spell_pri_blessed_recovery_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_pri_blessed_recovery_AuraScript(); +    } +}; +  // -34861 - Circle of Healing  class spell_pri_circle_of_healing : public SpellScriptLoader  { @@ -869,6 +914,7 @@ class spell_pri_vampiric_touch : public SpellScriptLoader  void AddSC_priest_spell_scripts()  { +    new spell_pri_blessed_recovery();      new spell_pri_circle_of_healing();      new spell_pri_divine_aegis();      new spell_pri_divine_hymn(); diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index affc4d1c26c..1abb6741e0d 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -43,7 +43,8 @@ enum RogueSpells      SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC        = 59628,      SPELL_ROGUE_HONOR_AMONG_THIEVES             = 51698,      SPELL_ROGUE_HONOR_AMONG_THIEVES_PROC        = 52916, -    SPELL_ROGUE_HONOR_AMONG_THIEVES_2           = 51699 +    SPELL_ROGUE_HONOR_AMONG_THIEVES_2           = 51699, +    SPELL_ROGUE_T10_2P_BONUS                    = 70804,  };  // 13877, 33735, (check 51211, 65956) - Blade Flurry @@ -843,6 +844,40 @@ public:      }  }; +// 70805 - Rogue T10 2P Bonus -- THIS SHOULD BE REMOVED WITH NEW PROC SYSTEM. +class spell_rog_t10_2p_bonus : public SpellScriptLoader +{ +public: +    spell_rog_t10_2p_bonus() : SpellScriptLoader("spell_rog_t10_2p_bonus") { } + +    class spell_rog_t10_2p_bonus_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_rog_t10_2p_bonus_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_T10_2P_BONUS)) +                return false; +            return true; +        } + +        bool CheckProc(ProcEventInfo& eventInfo) +        { +            return eventInfo.GetActor() == eventInfo.GetActionTarget(); +        } + +        void Register() override +        { +            DoCheckProc += AuraCheckProcFn(spell_rog_t10_2p_bonus_AuraScript::CheckProc); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_rog_t10_2p_bonus_AuraScript(); +    } +}; +  void AddSC_rogue_spell_scripts()  {      new spell_rog_blade_flurry(); @@ -858,4 +893,5 @@ void AddSC_rogue_spell_scripts()      new spell_rog_tricks_of_the_trade_proc();      new spell_rog_honor_among_thieves();      new spell_rog_honor_among_thieves_proc(); +    new spell_rog_t10_2p_bonus();  } diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index 41e72b1388b..ad65c7c6ec7 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -48,8 +48,10 @@ enum ShamanSpells      SPELL_SHAMAN_ITEM_MANA_SURGE                = 23571,      SPELL_SHAMAN_LAVA_FLOWS_R1                  = 51480,      SPELL_SHAMAN_LAVA_FLOWS_TRIGGERED_R1        = 64694, +    SPELL_SHAMAN_LIGHTNING_SHIELD_R1            = 26364,      SPELL_SHAMAN_MANA_SPRING_TOTEM_ENERGIZE     = 52032,      SPELL_SHAMAN_MANA_TIDE_TOTEM                = 39609, +    SPELL_SHAMAN_NATURE_GUARDIAN                = 31616,      SPELL_SHAMAN_SATED                          = 57724,      SPELL_SHAMAN_STORM_EARTH_AND_FIRE           = 51483,      SPELL_SHAMAN_TOTEM_EARTHBIND_EARTHGRAB      = 64695, @@ -671,7 +673,7 @@ class spell_sha_heroism : public SpellScriptLoader          }  }; -// 23551 - Lightning Shield +// 23551 - Lightning Shield T2 Bonus  class spell_sha_item_lightning_shield : public SpellScriptLoader  {      public: @@ -706,7 +708,7 @@ class spell_sha_item_lightning_shield : public SpellScriptLoader          }  }; -// 23552 - Lightning Shield +// 23552 - Lightning Shield T2 Bonus  class spell_sha_item_lightning_shield_trigger : public SpellScriptLoader  {      public: @@ -718,7 +720,7 @@ class spell_sha_item_lightning_shield_trigger : public SpellScriptLoader              bool Validate(SpellInfo const* /*spellInfo*/) override              { -                if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_ITEM_MANA_SURGE)) +                if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD_DAMAGE))                      return false;                  return true;              } @@ -753,7 +755,7 @@ class spell_sha_item_mana_surge : public SpellScriptLoader              bool Validate(SpellInfo const* /*spellInfo*/) override              { -                if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD_DAMAGE)) +                if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_ITEM_MANA_SURGE))                      return false;                  return true;              } @@ -865,6 +867,51 @@ class spell_sha_lava_lash : public SpellScriptLoader          }  }; +// -324 - Lightning Shield +class spell_sha_lightning_shield : public SpellScriptLoader +{ +public: +    spell_sha_lightning_shield() : SpellScriptLoader("spell_sha_lightning_shield") { } + +    class spell_sha_lightning_shield_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_sha_lightning_shield_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_LIGHTNING_SHIELD_R1)) +                return false; +            return true; +        } + +        bool CheckProc(ProcEventInfo& eventInfo) +        { +            if (eventInfo.GetActionTarget()) +                return true; +            return false; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); +            uint32 triggerSpell = sSpellMgr->GetSpellWithRank(SPELL_SHAMAN_LIGHTNING_SHIELD_R1, aurEff->GetSpellInfo()->GetRank()); + +            eventInfo.GetActionTarget()->CastSpell(eventInfo.GetActor(), triggerSpell, true, nullptr, aurEff); +        } + +        void Register() override +        { +            DoCheckProc += AuraCheckProcFn(spell_sha_lightning_shield_AuraScript::CheckProc); +            OnEffectProc += AuraEffectProcFn(spell_sha_lightning_shield_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_sha_lightning_shield_AuraScript(); +    } +}; +  // 52031, 52033, 52034, 52035, 52036, 58778, 58779, 58780 - Mana Spring Totem  class spell_sha_mana_spring_totem : public SpellScriptLoader  { @@ -924,6 +971,7 @@ class spell_sha_mana_tide_totem : public SpellScriptLoader              void HandleDummy(SpellEffIndex /*effIndex*/)              {                  if (Unit* caster = GetCaster()) +                {                      if (Unit* unitTarget = GetHitUnit())                      {                          if (unitTarget->getPowerType() == POWER_MANA) @@ -938,6 +986,7 @@ class spell_sha_mana_tide_totem : public SpellScriptLoader                              caster->CastCustomSpell(unitTarget, SPELL_SHAMAN_MANA_TIDE_TOTEM, &effBasePoints0, NULL, NULL, true, NULL, NULL, GetOriginalCaster()->GetGUID());                          }                      } +                }              }              void Register() override @@ -952,6 +1001,56 @@ class spell_sha_mana_tide_totem : public SpellScriptLoader          }  }; +// -30881 - Nature's Guardian +class spell_sha_nature_guardian : public SpellScriptLoader +{ +public: +    spell_sha_nature_guardian() : SpellScriptLoader("spell_sha_nature_guardian") { } + +    class spell_sha_nature_guardian_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_sha_nature_guardian_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_NATURE_GUARDIAN)) +                return false; +            return true; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); +            int32 healthpct = aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); // %s2 - the 30% threshold for health + +            if (Unit* target = eventInfo.GetActionTarget()) +            { +                if (target->HealthBelowPctDamaged(healthpct, eventInfo.GetDamageInfo()->GetDamage())) +                { + +                    uint32 bp = CalculatePct(target->GetMaxHealth(), aurEff->GetAmount()); +                    target->CastCustomSpell(SPELL_SHAMAN_NATURE_GUARDIAN, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, aurEff); + +                    // Threat reduction is around 10% confirmed in retail and from wiki +                    Unit* attacker = eventInfo.GetActor(); +                    if (attacker->IsAlive()) +                        attacker->getThreatManager().modifyThreatPercent(target, -10); +                } +            } +        } + +        void Register() override +        { +            OnEffectProc += AuraEffectProcFn(spell_sha_nature_guardian_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_sha_nature_guardian_AuraScript(); +    } +}; +  // 6495 - Sentry Totem  class spell_sha_sentry_totem : public SpellScriptLoader  { @@ -1085,8 +1184,10 @@ void AddSC_shaman_spell_scripts()      new spell_sha_item_mana_surge();      new spell_sha_item_t10_elemental_2p_bonus();      new spell_sha_lava_lash(); +    new spell_sha_lightning_shield();      new spell_sha_mana_spring_totem();      new spell_sha_mana_tide_totem(); +    new spell_sha_nature_guardian();      new spell_sha_sentry_totem();      new spell_sha_thunderstorm();      new spell_sha_totemic_mastery(); diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 1f2ddcfa9c7..5e0074bf9f7 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -50,6 +50,12 @@ enum WarlockSpells      SPELL_WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R2    = 60956,      SPELL_WARLOCK_LIFE_TAP_ENERGIZE                 = 31818,      SPELL_WARLOCK_LIFE_TAP_ENERGIZE_2               = 32553, +    SPELL_WARLOCK_NETHER_PROTECTION_HOLY            = 54370, +    SPELL_WARLOCK_NETHER_PROTECTION_FIRE            = 54371, +    SPELL_WARLOCK_NETHER_PROTECTION_FROST           = 54372, +    SPELL_WARLOCK_NETHER_PROTECTION_ARCANE          = 54373, +    SPELL_WARLOCK_NETHER_PROTECTION_SHADOW          = 54374, +    SPELL_WARLOCK_NETHER_PROTECTION_NATURE          = 54375,      SPELL_WARLOCK_SOULSHATTER                       = 32835,      SPELL_WARLOCK_SIPHON_LIFE_HEAL                  = 63106,      SPELL_WARLOCK_UNSTABLE_AFFLICTION_DISPEL        = 31117 @@ -684,6 +690,95 @@ class spell_warl_life_tap : public SpellScriptLoader          }  }; +// -30299 - Nether Protection +class spell_warl_nether_protection : public SpellScriptLoader +{ +public: +    spell_warl_nether_protection() : SpellScriptLoader("spell_warl_nether_protection") { } + +    class spell_warl_nether_protection_AuraScript : public AuraScript +    { +        PrepareAuraScript(spell_warl_nether_protection_AuraScript); + +        bool Validate(SpellInfo const* /*spellInfo*/) override +        { +            if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_HOLY) || +                !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_FIRE) || +                !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_FROST) || +                !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_ARCANE) || +                !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_SHADOW) || +                !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_NATURE)) +                return false; +            return true; +        } + +        bool CheckProc(ProcEventInfo& eventInfo) +        { +            if (eventInfo.GetDamageInfo()) +            { +                switch (GetFirstSchoolInMask(eventInfo.GetDamageInfo()->GetSchoolMask())) +                { +                    case SPELL_SCHOOL_HOLY: +                    case SPELL_SCHOOL_FIRE: +                    case SPELL_SCHOOL_NATURE: +                    case SPELL_SCHOOL_FROST: +                    case SPELL_SCHOOL_SHADOW: +                    case SPELL_SCHOOL_ARCANE: +                        return true; +                    default: +                        break; +                } +            } + +            return false; +        } + +        void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) +        { +            PreventDefaultAction(); +            uint32 triggerspell = 0; + +            switch (GetFirstSchoolInMask(eventInfo.GetDamageInfo()->GetSchoolMask())) +            { +                case SPELL_SCHOOL_HOLY: +                    triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_HOLY; +                    break; +                case SPELL_SCHOOL_FIRE: +                    triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_FIRE; +                    break; +                case SPELL_SCHOOL_NATURE: +                    triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_NATURE; +                    break; +                case SPELL_SCHOOL_FROST: +                    triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_FROST; +                    break; +                case SPELL_SCHOOL_SHADOW: +                    triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_SHADOW; +                    break; +                case SPELL_SCHOOL_ARCANE: +                    triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_ARCANE; +                    break; +                default: +                    return; +            } + +            if (Unit* target = eventInfo.GetActionTarget()) +                target->CastSpell(target, triggerspell, true, nullptr, aurEff); +        } + +        void Register() override +        { +            DoCheckProc += AuraCheckProcFn(spell_warl_nether_protection_AuraScript::CheckProc); +            OnEffectProc += AuraEffectProcFn(spell_warl_nether_protection_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); +        } +    }; + +    AuraScript* GetAuraScript() const override +    { +        return new spell_warl_nether_protection_AuraScript(); +    } +}; +  // 18541 - Ritual of Doom Effect  class spell_warl_ritual_of_doom_effect : public SpellScriptLoader  { @@ -919,6 +1014,7 @@ void AddSC_warlock_spell_scripts()      new spell_warl_haunt();      new spell_warl_health_funnel();      new spell_warl_life_tap(); +    new spell_warl_nether_protection();      new spell_warl_ritual_of_doom_effect();      new spell_warl_seed_of_corruption();      new spell_warl_shadow_ward();  | 
