aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorccrs <ccrs@users.noreply.github.com>2021-08-20 03:41:49 +0200
committerGitHub <noreply@github.com>2021-08-20 03:41:49 +0200
commit3e886c55611357581ecb69c671d021d29b715e64 (patch)
tree6ce73038b0778656f44617bc7a4cd0a529a151f4 /src
parent1ddd9dc19cc1df1a1ab8c6123283999f9dea6760 (diff)
Scripts/Pet: implement Dance Rune Weapon + minor tweaks to npc_pet_mage_mirror_image script
damage is now halved, years ago it wasn't, so we got that going at least stat scaling missing - the low damage might even come from this instead of the aura periodic auras still unknown
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Globals/ObjectAccessor.cpp3
-rw-r--r--src/server/scripts/Pet/pet_dk.cpp227
-rw-r--r--src/server/scripts/Pet/pet_mage.cpp137
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp177
4 files changed, 409 insertions, 135 deletions
diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp
index 4eec2f6d451..bd7baeb2910 100644
--- a/src/server/game/Globals/ObjectAccessor.cpp
+++ b/src/server/game/Globals/ObjectAccessor.cpp
@@ -186,6 +186,9 @@ DynamicObject* ObjectAccessor::GetDynamicObject(WorldObject const& u, ObjectGuid
Unit* ObjectAccessor::GetUnit(WorldObject const& u, ObjectGuid const& guid)
{
+ if (guid.IsEmpty())
+ return nullptr;
+
if (guid.IsPlayer())
return GetPlayer(u, guid);
diff --git a/src/server/scripts/Pet/pet_dk.cpp b/src/server/scripts/Pet/pet_dk.cpp
index 33d08e8be1c..0e26ff8618b 100644
--- a/src/server/scripts/Pet/pet_dk.cpp
+++ b/src/server/scripts/Pet/pet_dk.cpp
@@ -25,15 +25,27 @@
#include "CellImpl.h"
#include "GridNotifiersImpl.h"
#include "MotionMaster.h"
+#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
enum DeathKnightSpells
{
- SPELL_DK_SUMMON_GARGOYLE_1 = 49206,
- SPELL_DK_SUMMON_GARGOYLE_2 = 50514,
- SPELL_DK_DISMISS_GARGOYLE = 50515,
- SPELL_DK_SANCTUARY = 54661
+ SPELL_DK_SUMMON_GARGOYLE_1 = 49206,
+ SPELL_DK_SUMMON_GARGOYLE_2 = 50514,
+ SPELL_DK_DISMISS_GARGOYLE = 50515,
+ SPELL_DK_SANCTUARY = 54661,
+ SPELL_DK_DANCING_RUNE_WEAPON = 49028,
+ SPELL_COPY_WEAPON = 63416,
+ SPELL_DK_RUNE_WEAPON_MARK = 50474,
+ SPELL_DK_DANCING_RUNE_WEAPON_VISUAL = 53160,
+ SPELL_FAKE_AGGRO_RADIUS_8_YARD = 49812,
+ SPELL_DK_RUNE_WEAPON_SCALING_01 = 51905,
+ SPELL_DK_RUNE_WEAPON_SCALING = 51906,
+ SPELL_PET_SCALING__MASTER_SPELL_06__SPELL_HIT_EXPERTISE_SPELL_PENETRATION = 67561,
+ SPELL_DK_PET_SCALING_03 = 61697,
+ SPELL_AGGRO_8_YD_PBAE = 49813,
+ SPELL_DISMISS_RUNEBLADE = 50707, // Right now despawn is done by its duration
};
struct npc_pet_dk_ebon_gargoyle : CasterAI
@@ -117,32 +129,215 @@ struct npc_pet_dk_guardian : public AggressorAI
}
};
-// 51963 - Gargoyle Strike
-class spell_pet_dk_gargoyle_strike : public SpellScript
+enum DancingRuneWeaponMisc
{
- PrepareSpellScript(spell_pet_dk_gargoyle_strike);
+ TASK_GROUP_COMBAT = 1,
+ DATA_INITIAL_TARGET_GUID = 1,
+};
+
+struct npc_pet_dk_rune_weapon : ScriptedAI
+{
+ npc_pet_dk_rune_weapon(Creature* creature) : ScriptedAI(creature) { }
+
+ void IsSummonedBy(WorldObject* summoner) override
+ {
+ me->SetReactState(REACT_PASSIVE);
+
+ if (summoner->GetTypeId() != TYPEID_UNIT)
+ return;
+
+ Unit* unitSummoner = summoner->ToUnit();
+
+ DoCast(unitSummoner, SPELL_COPY_WEAPON, true);
+ DoCast(unitSummoner, SPELL_DK_RUNE_WEAPON_MARK, true);
+ DoCastSelf(SPELL_DK_DANCING_RUNE_WEAPON_VISUAL, true);
+ DoCastSelf(SPELL_FAKE_AGGRO_RADIUS_8_YARD, true);
+ DoCastSelf(SPELL_DK_RUNE_WEAPON_SCALING_01, true);
+ DoCastSelf(SPELL_DK_RUNE_WEAPON_SCALING, true);
+ DoCastSelf(SPELL_PET_SCALING__MASTER_SPELL_06__SPELL_HIT_EXPERTISE_SPELL_PENETRATION, true);
+ DoCastSelf(SPELL_DK_PET_SCALING_03, true);
+
+ _scheduler.Schedule(500ms, [this](TaskContext /*activate*/)
+ {
+ me->SetReactState(REACT_AGGRESSIVE);
+ if (!_targetGUID.IsEmpty())
+ {
+ if (Unit* target = ObjectAccessor::GetUnit(*me, _targetGUID))
+ me->EngageWithTarget(target);
+ }
+ }).Schedule(6s, [this](TaskContext visual)
+ {
+ // Cast every 6 seconds
+ DoCastSelf(SPELL_DK_DANCING_RUNE_WEAPON_VISUAL, true);
+ visual.Repeat();
+ });
+ }
+
+ void SetGUID(ObjectGuid const& guid, int32 id) override
+ {
+ if (id == DATA_INITIAL_TARGET_GUID)
+ _targetGUID = guid;
+ }
+
+ void JustEnteredCombat(Unit* who) override
+ {
+ ScriptedAI::JustEnteredCombat(who);
+
+ // Investigate further if these casts are done by any owned aura, eitherway SMSG_SPELL_GO is sent every X seconds.
+ _scheduler.Schedule(1s, TASK_GROUP_COMBAT, [this](TaskContext aggro8YD)
+ {
+ // Cast every second
+ if (Unit* victim = me->GetVictim())
+ DoCast(victim, SPELL_AGGRO_8_YD_PBAE, true);
+ aggro8YD.Repeat();
+ });
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ Unit* owner = me->GetOwner();
+ if (!owner)
+ {
+ me->DespawnOrUnsummon();
+ return;
+ }
+
+ _scheduler.Update(diff);
+
+ if (!UpdateRuneWeaponVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+
+ bool CanAIAttack(Unit const* who) const override
+ {
+ Unit* owner = me->GetOwner();
+ return owner && who->IsAlive() && me->IsValidAttackTarget(who) && !who->HasBreakableByDamageCrowdControlAura() && who->IsInCombatWith(owner) && ScriptedAI::CanAIAttack(who);
+ }
- void HandleDamageCalc(SpellEffIndex /*effIndex*/)
+ // Do not reload Creature templates on evade mode enter - prevent visual lost
+ void EnterEvadeMode(EvadeReason /*why*/) override
{
- int32 damage = 60;
- if (Unit* caster = GetCaster())
+ _scheduler.CancelGroup(TASK_GROUP_COMBAT);
+
+ if (!me->IsAlive())
{
- if (caster->GetLevel() >= 60)
- damage += (caster->GetLevel() - 60) * 4;
+ EngagementOver();
+ return;
}
- SetEffectValue(damage);
+ Unit* owner = me->GetCharmerOrOwner();
+
+ me->CombatStop(true);
+ me->SetLootRecipient(nullptr);
+ me->ResetPlayerDamageReq();
+ me->SetLastDamagedTime(0);
+ me->SetCannotReachTarget(false);
+ me->DoNotReacquireSpellFocusTarget();
+ me->SetTarget(ObjectGuid::Empty);
+ EngagementOver();
+
+ if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW))
+ {
+ me->GetMotionMaster()->Clear();
+ me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle());
+ }
}
- void Register() override
+private:
+ // custom UpdateVictim implementation to handle special target selection
+ // we prioritize between things that are in combat with owner based on the owner's threat to them
+ bool UpdateRuneWeaponVictim()
{
- OnEffectLaunchTarget += SpellEffectFn(spell_pet_dk_gargoyle_strike::HandleDamageCalc, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
+ Unit* owner = me->GetOwner();
+ if (!owner)
+ return false;
+
+ if (!me->IsEngaged() && !owner->IsInCombat())
+ return false;
+
+ Unit* currentTarget = me->GetVictim();
+ if (currentTarget && !CanAIAttack(currentTarget))
+ {
+ me->InterruptNonMeleeSpells(true); // do not finish casting on invalid targets
+ me->AttackStop();
+ currentTarget = nullptr;
+ }
+
+ Unit* selectedTarget = nullptr;
+
+ // first, try to get the initial target
+ if (Unit* initialTarget = ObjectAccessor::GetUnit(*me, _targetGUID))
+ {
+ if (CanAIAttack(initialTarget))
+ selectedTarget = initialTarget;
+ }
+ else if (!_targetGUID.IsEmpty())
+ _targetGUID.Clear();
+
+ CombatManager const& mgr = owner->GetCombatManager();
+ if (!selectedTarget)
+ {
+ if (mgr.HasPvPCombat())
+ {
+ // select pvp target
+ float minDistance = 0.f;
+ for (auto const& pair : mgr.GetPvPCombatRefs())
+ {
+ Unit* target = pair.second->GetOther(owner);
+ if (target->GetTypeId() != TYPEID_PLAYER)
+ continue;
+ if (!CanAIAttack(target))
+ continue;
+
+ float dist = owner->GetDistance(target);
+ if (!selectedTarget || dist < minDistance)
+ {
+ selectedTarget = target;
+ minDistance = dist;
+ }
+ }
+ }
+ }
+
+ if (!selectedTarget)
+ {
+ // select pve target
+ float maxThreat = 0.f;
+ for (auto const& pair : mgr.GetPvECombatRefs())
+ {
+ Unit* target = pair.second->GetOther(owner);
+ if (!CanAIAttack(target))
+ continue;
+
+ float threat = target->GetThreatManager().GetThreat(owner);
+ if (threat >= maxThreat)
+ {
+ selectedTarget = target;
+ maxThreat = threat;
+ }
+ }
+ }
+
+ if (!selectedTarget)
+ {
+ EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
+ return false;
+ }
+
+ if (selectedTarget != me->GetVictim())
+ AttackStart(selectedTarget);
+ return true;
}
+
+ TaskScheduler _scheduler;
+ ObjectGuid _targetGUID;
};
void AddSC_deathknight_pet_scripts()
{
RegisterCreatureAI(npc_pet_dk_ebon_gargoyle);
RegisterCreatureAI(npc_pet_dk_guardian);
- RegisterSpellScript(spell_pet_dk_gargoyle_strike);
+ RegisterCreatureAI(npc_pet_dk_rune_weapon);
}
diff --git a/src/server/scripts/Pet/pet_mage.cpp b/src/server/scripts/Pet/pet_mage.cpp
index 06797c4a155..b2d479e4845 100644
--- a/src/server/scripts/Pet/pet_mage.cpp
+++ b/src/server/scripts/Pet/pet_mage.cpp
@@ -28,6 +28,8 @@
#include "Pet.h"
#include "PetAI.h"
#include "ScriptedCreature.h"
+#include "SpellHistory.h"
+#include "Timer.h"
enum MageSpells
{
@@ -46,7 +48,7 @@ struct npc_pet_mage_mirror_image : ScriptedAI
{
const float CHASE_DISTANCE = 35.0f;
- npc_pet_mage_mirror_image(Creature* creature) : ScriptedAI(creature) { }
+ npc_pet_mage_mirror_image(Creature* creature) : ScriptedAI(creature), _fireBlastTimer(0) { }
void InitializeAI() override
{
@@ -60,15 +62,76 @@ struct npc_pet_mage_mirror_image : ScriptedAI
owner->CastSpell(me, SPELL_MAGE_CLONE_ME, true);
}
+ void UpdateAI(uint32 diff) override
+ {
+ Unit* owner = me->GetOwner();
+ if (!owner)
+ {
+ me->DespawnOrUnsummon();
+ return;
+ }
+
+ if (!_fireBlastTimer.Passed())
+ _fireBlastTimer.Update(diff);
+
+ if (!UpdateImageVictim())
+ return;
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ if (_fireBlastTimer.Passed())
+ {
+ DoCastVictim(SPELL_MAGE_FIRE_BLAST);
+ _fireBlastTimer.Reset(TIMER_MIRROR_IMAGE_FIRE_BLAST);
+ }
+ else
+ DoCastVictim(SPELL_MAGE_FROST_BOLT);
+ }
+
+ bool CanAIAttack(Unit const* who) const override
+ {
+ Unit* owner = me->GetOwner();
+ return owner && who->IsAlive() && me->IsValidAttackTarget(who) && !who->HasBreakableByDamageCrowdControlAura() && who->IsInCombatWith(owner) && ScriptedAI::CanAIAttack(who);
+ }
+
+ // Do not reload Creature templates on evade mode enter - prevent visual lost
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ if (!me->IsAlive())
+ {
+ EngagementOver();
+ return;
+ }
+
+ Unit* owner = me->GetCharmerOrOwner();
+
+ me->CombatStop(true);
+ me->SetLootRecipient(nullptr);
+ me->ResetPlayerDamageReq();
+ me->SetLastDamagedTime(0);
+ me->SetCannotReachTarget(false);
+ me->DoNotReacquireSpellFocusTarget();
+ me->SetTarget(ObjectGuid::Empty);
+ EngagementOver();
+
+ if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW))
+ {
+ me->GetMotionMaster()->Clear();
+ me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle());
+ }
+ }
+
+private:
// custom UpdateVictim implementation to handle special target selection
// we prioritize between things that are in combat with owner based on the owner's threat to them
- bool UpdateVictim()
+ bool UpdateImageVictim()
{
Unit* owner = me->GetOwner();
if (!owner)
return false;
- if (!me->HasUnitState(UNIT_STATE_CASTING) && !me->IsInCombat() && !owner->IsInCombat())
+ if (!me->HasUnitState(UNIT_STATE_CASTING) && !me->IsEngaged() && !owner->IsInCombat())
return false;
Unit* currentTarget = me->GetVictim();
@@ -86,8 +149,9 @@ struct npc_pet_mage_mirror_image : ScriptedAI
Unit* selectedTarget = nullptr;
CombatManager const& mgr = owner->GetCombatManager();
if (mgr.HasPvPCombat())
- { // select pvp target
- float minDistance = 0.0f;
+ {
+ // select pvp target
+ float minDistance = 0.f;
for (auto const& pair : mgr.GetPvPCombatRefs())
{
Unit* target = pair.second->GetOther(owner);
@@ -106,8 +170,9 @@ struct npc_pet_mage_mirror_image : ScriptedAI
}
if (!selectedTarget)
- { // select pve target
- float maxThreat = 0.0f;
+ {
+ // select pve target
+ float maxThreat = 0.f;
for (auto const& pair : mgr.GetPvECombatRefs())
{
Unit* target = pair.second->GetOther(owner);
@@ -134,63 +199,7 @@ struct npc_pet_mage_mirror_image : ScriptedAI
return true;
}
- void UpdateAI(uint32 diff) override
- {
- Unit* owner = me->GetOwner();
- if (!owner)
- {
- me->DespawnOrUnsummon();
- return;
- }
-
- if (_fireBlastTimer)
- {
- if (_fireBlastTimer <= diff)
- _fireBlastTimer = 0;
- else
- _fireBlastTimer -= diff;
- }
-
- if (!UpdateVictim())
- return;
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- if (!_fireBlastTimer)
- {
- DoCastVictim(SPELL_MAGE_FIRE_BLAST);
- _fireBlastTimer = TIMER_MIRROR_IMAGE_FIRE_BLAST;
- }
- else
- DoCastVictim(SPELL_MAGE_FROST_BOLT);
- }
-
- bool CanAIAttack(Unit const* who) const override
- {
- Unit* owner = me->GetOwner();
- return owner && who->IsAlive() && me->IsValidAttackTarget(who) &&
- !who->HasBreakableByDamageCrowdControlAura() &&
- who->IsInCombatWith(owner) && ScriptedAI::CanAIAttack(who);
- }
-
- // Do not reload Creature templates on evade mode enter - prevent visual lost
- void EnterEvadeMode(EvadeReason /*why*/) override
- {
- if (me->IsInEvadeMode() || !me->IsAlive())
- return;
-
- Unit* owner = me->GetCharmerOrOwner();
-
- me->CombatStop(true);
- if (owner && !me->HasUnitState(UNIT_STATE_FOLLOW))
- {
- me->GetMotionMaster()->Clear();
- me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle());
- }
- }
-
- uint32 _fireBlastTimer = 0;
+ TimeTracker _fireBlastTimer;
};
void AddSC_mage_pet_scripts()
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp
index ff374b5e6ed..f396c45d8b9 100644
--- a/src/server/scripts/Spells/spell_dk.cpp
+++ b/src/server/scripts/Spells/spell_dk.cpp
@@ -23,6 +23,7 @@
#include "ScriptMgr.h"
#include "Containers.h"
+#include "CreatureAI.h"
#include "DBCStores.h"
#include "Map.h"
#include "ObjectAccessor.h"
@@ -100,7 +101,14 @@ enum DeathKnightSpells
SPELL_DK_RUNIC_RETURN = 61258,
SPELL_DK_WANDERING_PLAGUE_DAMAGE = 50526,
SPELL_DK_DEATH_COIL_R1 = 47541,
- SPELL_DK_DEATH_GRIP_INITIAL = 49576
+ SPELL_DK_DEATH_GRIP_INITIAL = 49576,
+ SPELL_DK_BLOOD_STRIKE = 45902,
+ SPELL_DK_ICY_TOUCH = 45477,
+ SPELL_DK_PLAGUE_STRIKE = 45462,
+ SPELL_DK_DEATH_STRIKE = 49998,
+ SPELL_DK_HEART_STRIKE = 55050,
+ SPELL_DK_OBLITERATE = 49020,
+ SPELL_DK_RUNE_STRIKE = 56815
};
enum DeathKnightSpellIcons
@@ -109,7 +117,7 @@ enum DeathKnightSpellIcons
DK_ICON_ID_IMPROVED_DEATH_STRIKE = 2751
};
-enum Misc
+enum DeathKnightMisc
{
NPC_DK_GHOUL = 26125,
NPC_DK_DANCING_RUNE_WEAPON = 27893,
@@ -619,58 +627,6 @@ class spell_dk_corpse_explosion : public SpellScript
WorldObject* _target = nullptr;
};
-// 49028 - Dancing Rune Weapon
-class spell_dk_dancing_rune_weapon : public AuraScript
-{
- PrepareAuraScript(spell_dk_dancing_rune_weapon);
-
- bool Validate(SpellInfo const* /*spellInfo*/) override
- {
- if (!sObjectMgr->GetCreatureTemplate(NPC_DK_DANCING_RUNE_WEAPON))
- return false;
- return true;
- }
-
- // This is a port of the old switch hack in Unit.cpp, it's not correct
- void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
- {
- PreventDefaultAction();
- Unit* caster = GetCaster();
- if (!caster)
- return;
-
- Unit* drw = nullptr;
- for (Unit* controlled : caster->m_Controlled)
- {
- if (controlled->GetEntry() == NPC_DK_DANCING_RUNE_WEAPON)
- {
- drw = controlled;
- break;
- }
- }
-
- if (!drw || !drw->GetVictim())
- return;
-
- SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
- if (!spellInfo)
- return;
-
- DamageInfo* damageInfo = eventInfo.GetDamageInfo();
- if (!damageInfo || !damageInfo->GetDamage())
- return;
-
- int32 amount = static_cast<int32>(damageInfo->GetDamage()) / 2;
- drw->SendSpellNonMeleeDamageLog(drw->GetVictim(), spellInfo->Id, amount, spellInfo->GetSchoolMask(), 0, 0, false, 0, false);
- Unit::DealDamage(drw, drw->GetVictim(), amount, nullptr, SPELL_DIRECT_DAMAGE, spellInfo->GetSchoolMask(), spellInfo, true);
- }
-
- void Register() override
- {
- OnEffectProc += AuraEffectProcFn(spell_dk_dancing_rune_weapon::HandleProc, EFFECT_1, SPELL_AURA_DUMMY);
- }
-};
-
// -43265 - Death and Decay
class spell_dk_death_and_decay : public AuraScript
{
@@ -2642,6 +2598,116 @@ public:
}
};
+// 51963 - Gargoyle Strike
+class spell_pet_dk_gargoyle_strike : public SpellScript
+{
+ PrepareSpellScript(spell_pet_dk_gargoyle_strike);
+
+ void HandleDamageCalc(SpellEffIndex /*effIndex*/)
+ {
+ int32 damage = 60;
+ if (Unit* caster = GetCaster())
+ {
+ if (caster->GetLevel() >= 60)
+ damage += (caster->GetLevel() - 60) * 4;
+ }
+
+ SetEffectValue(damage);
+ }
+
+ void Register() override
+ {
+ OnEffectLaunchTarget += SpellEffectFn(spell_pet_dk_gargoyle_strike::HandleDamageCalc, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
+ }
+};
+
+enum DancingRuneWeaponMisc
+{
+ DATA_INITIAL_TARGET_GUID = 1,
+};
+
+// 49028 - Dancing Rune Weapon
+class spell_dk_dancing_rune_weapon : public AuraScript
+{
+ PrepareAuraScript(spell_dk_dancing_rune_weapon);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({
+ SPELL_DK_BLOOD_STRIKE,
+ SPELL_DK_ICY_TOUCH,
+ SPELL_DK_PLAGUE_STRIKE,
+ SPELL_DK_DEATH_COIL_DAMAGE,
+ SPELL_DK_DEATH_STRIKE,
+ SPELL_DK_HEART_STRIKE,
+ SPELL_DK_OBLITERATE,
+ SPELL_DK_RUNE_STRIKE
+ });
+ }
+
+ void HandleTarget(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
+
+ std::list<Creature*> runeWeapons;
+ caster->GetAllMinionsByEntry(runeWeapons, NPC_DK_DANCING_RUNE_WEAPON);
+ for (Creature* temp : runeWeapons)
+ {
+ if (temp->IsAIEnabled())
+ temp->AI()->SetGUID(GetTarget()->GetGUID(), DATA_INITIAL_TARGET_GUID);
+ temp->GetThreatManager().RegisterRedirectThreat(GetId(), caster->GetGUID(), 100);
+ }
+ }
+
+ bool CheckProc(ProcEventInfo& eventInfo)
+ {
+ if (SpellInfo const* procSpell = eventInfo.GetSpellInfo())
+ {
+ if (procSpell->IsRankOf(sSpellMgr->GetSpellInfo(SPELL_DK_BLOOD_STRIKE)) ||
+ procSpell->IsRankOf(sSpellMgr->GetSpellInfo(SPELL_DK_ICY_TOUCH)) ||
+ procSpell->IsRankOf(sSpellMgr->GetSpellInfo(SPELL_DK_PLAGUE_STRIKE)) ||
+ procSpell->IsRankOf(sSpellMgr->GetSpellInfo(SPELL_DK_DEATH_COIL_DAMAGE)) ||
+ procSpell->IsRankOf(sSpellMgr->GetSpellInfo(SPELL_DK_DEATH_STRIKE)) ||
+ procSpell->IsRankOf(sSpellMgr->GetSpellInfo(SPELL_DK_HEART_STRIKE)) ||
+ procSpell->IsRankOf(sSpellMgr->GetSpellInfo(SPELL_DK_OBLITERATE)) ||
+ procSpell->IsRankOf(sSpellMgr->GetSpellInfo(SPELL_DK_RUNE_STRIKE)))
+ return true;
+ }
+
+ return false;
+ }
+
+ void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+
+ Unit* owner = GetUnitOwner();
+ if (!owner)
+ return;
+
+ SpellInfo const* procSpell = eventInfo.GetSpellInfo();
+ Unit* runeWeapon = nullptr;
+ for (auto itr = owner->m_Controlled.begin(); itr != owner->m_Controlled.end() && !runeWeapon; itr++)
+ if ((*itr)->GetEntry() == NPC_DK_DANCING_RUNE_WEAPON)
+ runeWeapon = *itr;
+
+ if (!runeWeapon)
+ return;
+
+ if (runeWeapon->IsInCombat() && runeWeapon->GetVictim())
+ runeWeapon->CastSpell(runeWeapon->GetVictim(), procSpell->Id, CastSpellExtraArgs(TriggerCastFlags::TRIGGERED_IGNORE_POWER_AND_REAGENT_COST));
+ }
+
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_dk_dancing_rune_weapon::HandleTarget, EFFECT_2, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ DoCheckProc += AuraCheckProcFn(spell_dk_dancing_rune_weapon::CheckProc);
+ OnEffectProc += AuraEffectProcFn(spell_dk_dancing_rune_weapon::HandleProc, EFFECT_1, SPELL_AURA_DUMMY);
+ }
+};
+
void AddSC_deathknight_spell_scripts()
{
RegisterSpellScript(spell_dk_acclimation);
@@ -2655,7 +2721,6 @@ void AddSC_deathknight_spell_scripts()
RegisterSpellScript(spell_dk_bloodworms);
RegisterSpellScript(spell_dk_butchery);
RegisterSpellScript(spell_dk_corpse_explosion);
- RegisterSpellScript(spell_dk_dancing_rune_weapon);
RegisterSpellScript(spell_dk_death_and_decay);
RegisterSpellScript(spell_dk_death_coil);
RegisterSpellScript(spell_dk_death_gate);
@@ -2699,4 +2764,6 @@ void AddSC_deathknight_spell_scripts()
new spell_dk_raise_ally();
RegisterSpellScript(spell_dk_ghoul_thrash);
new spell_dk_blood_tap();
+ RegisterSpellScript(spell_pet_dk_gargoyle_strike);
+ RegisterSpellScript(spell_dk_dancing_rune_weapon);
}