aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/Utilities/Containers.h9
-rw-r--r--src/server/database/Database/Implementation/WorldDatabase.cpp4
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp28
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.h2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp2
-rw-r--r--src/server/game/Accounts/RBAC.h2
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp2
-rw-r--r--src/server/game/DataStores/M2Stores.cpp2
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp2
-rw-r--r--src/server/game/Entities/Creature/Creature.h10
-rw-r--r--src/server/game/Entities/Object/Object.cpp40
-rw-r--r--src/server/game/Entities/Object/Object.h2
-rw-r--r--src/server/game/Entities/Player/CinematicMgr.cpp3
-rw-r--r--src/server/game/Entities/Player/Player.cpp8
-rw-r--r--src/server/game/Entities/Player/Player.h14
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp645
-rw-r--r--src/server/game/Entities/Unit/Unit.h14
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp24
-rw-r--r--src/server/game/Loot/LootMgr.cpp2
-rw-r--r--src/server/game/Maps/MapManager.h8
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h66
-rw-r--r--src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp5
-rw-r--r--src/server/game/Spells/Auras/SpellAuraDefines.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp2
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp24
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h10
-rw-r--r--src/server/game/Spells/Spell.cpp41
-rw-r--r--src/server/game/Spells/SpellEffects.cpp8
-rw-r--r--src/server/game/Spells/SpellInfo.cpp6
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp28
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp38
-rw-r--r--src/server/scripts/Northrend/zone_grizzly_hills.cpp6
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp192
-rw-r--r--src/server/scripts/Spells/spell_druid.cpp231
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp56
-rw-r--r--src/server/scripts/Spells/spell_hunter.cpp106
-rw-r--r--src/server/scripts/Spells/spell_item.cpp403
-rw-r--r--src/server/scripts/Spells/spell_mage.cpp38
-rw-r--r--src/server/scripts/Spells/spell_paladin.cpp57
-rw-r--r--src/server/scripts/Spells/spell_priest.cpp46
-rw-r--r--src/server/scripts/Spells/spell_rogue.cpp38
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp109
-rw-r--r--src/server/scripts/Spells/spell_warlock.cpp96
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();