aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp7
-rwxr-xr-xsrc/server/game/Scripting/ScriptLoader.cpp2
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp26
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.cpp6
-rw-r--r--src/server/scripts/Northrend/CMakeLists.txt1
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp4
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp576
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp3
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp14
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h43
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp62
11 files changed, 704 insertions, 40 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index b5658267d6b..b88021cbb50 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -5758,6 +5758,13 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
triggered_spell_id = 70701;
break;
}
+ case 70871:
+ {
+ target = this;
+ triggered_spell_id = 70872;
+ basepoints0 = int32(damage) * triggerAmount / 100;
+ break;
+ }
}
break;
}
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 65a22002534..d2b1cfc6bdb 100755
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -470,6 +470,7 @@ void AddSC_boss_festergut();
void AddSC_boss_rotface();
void AddSC_boss_professor_putricide();
void AddSC_boss_blood_prince_council();
+void AddSC_boss_blood_queen_lana_thel();
void AddSC_icecrown_citadel_teleport();
void AddSC_instance_icecrown_citadel();
@@ -1155,6 +1156,7 @@ void AddNorthrendScripts()
AddSC_boss_rotface();
AddSC_boss_professor_putricide();
AddSC_boss_blood_prince_council();
+ AddSC_boss_blood_queen_lana_thel();
AddSC_icecrown_citadel_teleport();
AddSC_instance_icecrown_citadel();
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index a8d1a44528a..9bff6b85ab1 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -2800,6 +2800,32 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur)
++itr;
}
break;
+ case 71390: // Pact of the Darkfallen
+ {
+ for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end();)
+ {
+ if (!(*itr)->HasAura(71340))
+ itr = unitList.erase(itr);
+ else
+ ++itr;
+ }
+ bool remove = true;
+ // we can do this, unitList is MAX 4 in size
+ for (std::list<Unit*>::const_iterator itr = unitList.begin(); itr != unitList.end() && remove; ++itr)
+ {
+ if (!m_caster->IsWithinDist(*itr, 5.0f, false))
+ remove = false;
+
+ for (std::list<Unit*>::const_iterator itr2 = unitList.begin(); itr2 != unitList.end() && remove; ++itr2)
+ if (itr != itr2 && !(*itr2)->IsWithinDist(*itr, 5.0f, false))
+ remove = false;
+ }
+
+ if (remove)
+ for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
+ (*itr)->RemoveAura(71340);
+ break;
+ }
}
// Death Pact
if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00080000)
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 1fa668bd18d..fe2d1dbe28c 100755
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3624,6 +3624,8 @@ void SpellMgr::LoadSpellCustomAttr()
case 69782: case 69796: // Ooze Flood
case 69798: case 69801: // Ooze Flood
case 69538: case 69553: case 69610: // Ooze Combine
+ case 71447: case 71481: // Bloodbolt Splash
+ case 71482: case 71483: // Bloodbolt Splash
mSpellCustomAttr[i] |= SPELL_ATTR_CU_EXCLUDE_SELF;
count++;
break;
@@ -3951,6 +3953,10 @@ void SpellMgr::LoadSpellCustomAttr()
spellInfo->AttributesEx3 |= SPELL_ATTR_EX3_NO_DONE_BONUS;
count++;
break;
+ case 71340: // Pact of the Darkfallen
+ spellInfo->DurationIndex = 21;
+ count++;
+ break;
default:
break;
}
diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt
index 6de8a63ff1c..cad76883781 100644
--- a/src/server/scripts/Northrend/CMakeLists.txt
+++ b/src/server/scripts/Northrend/CMakeLists.txt
@@ -152,6 +152,7 @@ set(scripts_STAT_SRCS
Northrend/IcecrownCitadel/boss_rotface.cpp
Northrend/IcecrownCitadel/boss_professor_putricide.cpp
Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
+ Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
Northrend/zuldrak.cpp
Northrend/icecrown.cpp
Northrend/Gundrak/boss_slad_ran.cpp
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
index 00545783ec0..65254996eca 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
@@ -299,10 +299,12 @@ class boss_blood_council_controller : public CreatureScript
}
if (newPrince)
+ {
newPrince->SetHealth(me->GetHealth());
+ newPrince->AI()->Talk(invocationOrder[invocationStage].textId);
+ }
DoCast(me, invocationOrder[invocationStage].spellId);
- Talk(invocationOrder[invocationStage].textId);
events.ScheduleEvent(EVENT_INVOCATION_OF_BLOOD, 30000);
break;
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
new file mode 100644
index 00000000000..4b45ad1643e
--- /dev/null
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "Spell.h"
+#include "SpellAuraEffects.h"
+#include "icecrown_citadel.h"
+
+enum eTexts
+{
+ SAY_AGGRO = 0,
+ SAY_VAMPIRIC_BITE = 1,
+ SAY_MIND_CONTROL = 2,
+ EMOTE_BLOODTHIRST = 3,
+ SAY_SWARMING_SHADOWS = 4,
+ EMOTE_SWARMING_SHADOWS = 5,
+ SAY_PACT_OF_THE_DARKFALLEN = 6,
+ SAY_AIR_PHASE = 7,
+ SAY_KILL = 8,
+ SAY_WIPE = 9,
+ SAY_BERSERK = 10,
+ SAY_DEATH = 11,
+};
+
+enum eSpells
+{
+ SPELL_SHROUD_OF_SORROW = 70986,
+ SPELL_FRENZIED_BLOODTHIRST_VISUAL = 71949,
+ SPELL_VAMPIRIC_BITE = 71726,
+ SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR = 70879,
+ SPELL_FRENZIED_BLOODTHIRST = 70877,
+ SPELL_UNCONTROLLABLE_FRENZY = 70923,
+ SPELL_PRESENCE_OF_THE_DARKFALLEN = 71952,
+ SPELL_BLOOD_MIRROR_DAMAGE = 70821,
+ SPELL_BLOOD_MIRROR_VISUAL = 71510,
+ SPELL_BLOOD_MIRROR_DUMMY = 70838,
+ SPELL_DELIRIOUS_SLASH = 71623,
+ SPELL_PACT_OF_THE_DARKFALLEN_TARGET = 71336,
+ SPELL_PACT_OF_THE_DARKFALLEN = 71340,
+ SPELL_SWARMING_SHADOWS = 71264,
+ SPELL_TWILIGHT_BLOODBOLT_TARGET = 71445,
+ SPELL_TWILIGHT_BLOODBOLT = 71446,
+ SPELL_INCITE_TERROR = 73070,
+ SPELL_BLOODBOLT_WHIRL = 71772,
+};
+
+static const uint32 vampireAuras[3][MAX_DIFFICULTY] =
+{
+ {70867, 71473, 71532, 71533},
+ {70879, 71525, 71530, 71531},
+ {70877, 71474, 70877, 71474},
+};
+
+#define ESSENCE_OF_BLOOD_QUEEN RAID_MODE<uint32>(70867,71473,71532,71533)
+#define ESSENCE_OF_BLOOD_QUEEN_PLR RAID_MODE<uint32>(70879,71525,71530,71531)
+#define FRENZIED_BLOODTHIRST RAID_MODE<uint32>(70877,71474,70877,71474)
+
+enum eEvents
+{
+ EVENT_BERSERK = 1,
+ EVENT_VAMPIRIC_BITE = 2,
+ EVENT_BLOOD_MIRROR = 3,
+ EVENT_DELIRIOUS_SLASH = 4,
+ EVENT_PACT_OF_THE_DARKFALLEN = 5,
+ EVENT_SWARMING_SHADOWS = 6,
+ EVENT_TWILIGHT_BLOODBOLT = 7,
+ EVENT_AIR_PHASE = 8,
+ EVENT_AIR_START_FLYING = 9,
+ EVENT_AIR_FLY_DOWN = 10,
+
+ EVENT_GROUP_NORMAL = 1,
+ EVENT_GROUP_CANCELLABLE = 2,
+};
+
+#define GUID_VAMPIRE 1
+
+enum ePoints
+{
+ POINT_CENTER = 1,
+ POINT_AIR = 2,
+ POINT_GROUND = 3,
+};
+
+static const Position centerPos = {4595.7090f, 2769.4190f, 400.6368f, 0.0000f};
+static const Position airPos = {4595.7090f, 2769.4190f, 422.3893f, 0.0000f};
+
+bool IsVampire(Unit const* unit)
+{
+ for (uint8 i = 0; i < 3; ++i)
+ if (unit->HasAura(vampireAuras[i][unit->GetMap()->GetSpawnMode()]))
+ return true;
+ return false;
+}
+
+class VampiricBiteTargetSelector : public std::unary_function<Unit*, bool>
+{
+ public:
+ VampiricBiteTargetSelector() { }
+
+ bool operator() (Unit const* target)
+ {
+ if (!target)
+ return false;
+
+ if (target->GetTypeId() != TYPEID_PLAYER)
+ return false;
+
+ if (IsVampire(target))
+ return false;
+
+ return true;
+ }
+};
+
+class boss_blood_queen_lana_thel : public CreatureScript
+{
+ public:
+ boss_blood_queen_lana_thel() : CreatureScript("boss_blood_queen_lana_thel") { }
+
+ struct boss_blood_queen_lana_thelAI : public BossAI
+ {
+ boss_blood_queen_lana_thelAI(Creature* creature) : BossAI(creature, DATA_BLOOD_QUEEN_LANA_THEL)
+ {
+ }
+
+ void InitializeAI()
+ {
+ if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != GetScriptId(ICCScriptName))
+ me->IsAIEnabled = false;
+ else if (!me->isDead())
+ Reset();
+ }
+
+ void Reset()
+ {
+ events.Reset();
+ events.ScheduleEvent(EVENT_BERSERK, 330000);
+ events.ScheduleEvent(EVENT_VAMPIRIC_BITE, 15000);
+ events.ScheduleEvent(EVENT_BLOOD_MIRROR, 2500, EVENT_GROUP_CANCELLABLE);
+ events.ScheduleEvent(EVENT_DELIRIOUS_SLASH, urand(20000, 24000), EVENT_GROUP_NORMAL);
+ events.ScheduleEvent(EVENT_PACT_OF_THE_DARKFALLEN, 15000, EVENT_GROUP_NORMAL);
+ events.ScheduleEvent(EVENT_SWARMING_SHADOWS, 30500, EVENT_GROUP_NORMAL);
+ events.ScheduleEvent(EVENT_TWILIGHT_BLOODBOLT, urand(20000, 25000), EVENT_GROUP_NORMAL);
+ events.ScheduleEvent(EVENT_AIR_PHASE, 124000 + (Is25ManRaid() ? 3000 : 0));
+ me->SetSpeed(MOVE_FLIGHT, 0.642857f, true);
+ offtank = NULL;
+ vampires.clear();
+
+ instance->SetBossState(DATA_BLOOD_QUEEN_LANA_THEL, NOT_STARTED);
+ }
+
+ void EnterCombat(Unit* /*who*/)
+ {
+ DoZoneInCombat();
+ Talk(SAY_AGGRO);
+ instance->SetBossState(DATA_BLOOD_QUEEN_LANA_THEL, IN_PROGRESS);
+
+ DoCast(me, SPELL_SHROUD_OF_SORROW, true);
+ DoCast(me, SPELL_FRENZIED_BLOODTHIRST_VISUAL, true);
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ Talk(SAY_DEATH);
+ instance->DoRemoveAurasDueToSpellOnPlayers(ESSENCE_OF_BLOOD_QUEEN);
+ instance->DoRemoveAurasDueToSpellOnPlayers(ESSENCE_OF_BLOOD_QUEEN_PLR);
+ instance->DoRemoveAurasDueToSpellOnPlayers(FRENZIED_BLOODTHIRST);
+ instance->SetBossState(DATA_BLOOD_QUEEN_LANA_THEL, DONE);
+ }
+
+ void JustReachedHome()
+ {
+ Talk(SAY_WIPE);
+ instance->SetBossState(DATA_BLOOD_QUEEN_LANA_THEL, FAIL);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_KILL);
+ }
+
+ void SetGUID(const uint64& guid, int32 type = 0)
+ {
+ if (type == GUID_VAMPIRE)
+ vampires.insert(guid);
+ }
+
+ void MovementInform(uint32 type, uint32 id)
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ switch (id)
+ {
+ case POINT_CENTER:
+ DoCast(me, SPELL_INCITE_TERROR);
+ events.ScheduleEvent(EVENT_AIR_PHASE, 100000 + (Is25ManRaid() ? 0 : 20000));
+ events.RescheduleEvent(EVENT_SWARMING_SHADOWS, 30500, EVENT_GROUP_NORMAL);
+ events.RescheduleEvent(EVENT_PACT_OF_THE_DARKFALLEN, 25500, EVENT_GROUP_NORMAL);
+ events.ScheduleEvent(EVENT_AIR_START_FLYING, 5000);
+ break;
+ case POINT_AIR:
+ DoCast(me, SPELL_BLOODBOLT_WHIRL);
+ Talk(SAY_AIR_PHASE);
+ events.ScheduleEvent(EVENT_AIR_FLY_DOWN, 10000);
+ break;
+ case POINT_GROUND:
+ me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, 0x01);
+ me->SetFlying(false);
+ me->SetReactState(REACT_AGGRESSIVE);
+ AttackStart(me->getVictim());
+ events.ScheduleEvent(EVENT_BLOOD_MIRROR, 2500, EVENT_GROUP_CANCELLABLE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim() || !CheckInRoom())
+ return;
+
+ events.Update(diff);
+
+ if (me->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_BERSERK:
+ DoScriptText(EMOTE_GENERIC_BERSERK_RAID, me);
+ Talk(SAY_BERSERK);
+ DoCast(me, SPELL_BERSERK);
+ break;
+ case EVENT_VAMPIRIC_BITE:
+ if (Player* target = SelectRandomTarget(false))
+ {
+ DoCast(target, SPELL_VAMPIRIC_BITE);
+ Talk(SAY_VAMPIRIC_BITE);
+ vampires.insert(target->GetGUID());
+ }
+ break;
+ case EVENT_BLOOD_MIRROR:
+ {
+ Player* newOfftank = SelectRandomTarget(true);
+ if (offtank != newOfftank)
+ {
+ offtank = newOfftank;
+ offtank->CastSpell(me->getVictim(), SPELL_BLOOD_MIRROR_DAMAGE, true);
+ me->getVictim()->CastSpell(offtank, SPELL_BLOOD_MIRROR_DUMMY, true);
+ DoCastVictim(SPELL_BLOOD_MIRROR_VISUAL);
+ }
+ events.ScheduleEvent(EVENT_BLOOD_MIRROR, 2500, EVENT_GROUP_CANCELLABLE);
+ break;
+ }
+ case EVENT_DELIRIOUS_SLASH:
+ if (offtank && !me->HasByteFlag(UNIT_FIELD_BYTES_1, 3, 0x03))
+ DoCast(offtank, SPELL_DELIRIOUS_SLASH);
+ events.ScheduleEvent(EVENT_DELIRIOUS_SLASH, urand(20000, 24000), EVENT_GROUP_NORMAL);
+ break;
+ case EVENT_PACT_OF_THE_DARKFALLEN:
+ {
+ std::list<Player*> targets;
+ SelectRandomTarget(false, &targets);
+ uint32 targetCount = 2;
+ if (IsHeroic())
+ ++targetCount;
+ if (Is25ManRaid())
+ ++targetCount;
+ Trinity::RandomResizeList<Player*>(targets, targetCount);
+ if (targets.size() > 1)
+ {
+ Talk(SAY_PACT_OF_THE_DARKFALLEN);
+ for (std::list<Player*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ DoCast(*itr, SPELL_PACT_OF_THE_DARKFALLEN);
+ }
+ events.ScheduleEvent(EVENT_PACT_OF_THE_DARKFALLEN, 30500, EVENT_GROUP_NORMAL);
+ break;
+ }
+ case EVENT_SWARMING_SHADOWS:
+ if (Player* target = SelectRandomTarget(false))
+ {
+ Talk(EMOTE_SWARMING_SHADOWS, target->GetGUID());
+ Talk(SAY_SWARMING_SHADOWS);
+ DoCast(target, SPELL_SWARMING_SHADOWS);
+ }
+ events.ScheduleEvent(EVENT_SWARMING_SHADOWS, 30500, EVENT_GROUP_NORMAL);
+ break;
+ case EVENT_TWILIGHT_BLOODBOLT:
+ {
+ std::list<Player*> targets;
+ SelectRandomTarget(false, &targets);
+ Trinity::RandomResizeList<Player*>(targets, Is25ManRaid() ? 4 : 2);
+ for (std::list<Player*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
+ DoCast(*itr, SPELL_TWILIGHT_BLOODBOLT);
+ DoCast(me, SPELL_TWILIGHT_BLOODBOLT_TARGET);
+ events.ScheduleEvent(EVENT_TWILIGHT_BLOODBOLT, urand(10000, 15000), EVENT_GROUP_NORMAL);
+ break;
+ }
+ case EVENT_AIR_PHASE:
+ DoStopAttack();
+ me->SetReactState(REACT_PASSIVE);
+ events.DelayEvents(7000, EVENT_GROUP_NORMAL);
+ events.CancelEventsByGCD(EVENT_GROUP_CANCELLABLE);
+ me->GetMotionMaster()->MovePoint(POINT_CENTER, centerPos);
+ break;
+ case EVENT_AIR_START_FLYING:
+ me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
+ me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0x01);
+ me->SetFlying(true);
+ me->GetMotionMaster()->MovePoint(POINT_AIR, airPos);
+ break;
+ case EVENT_AIR_FLY_DOWN:
+ me->GetMotionMaster()->MovePoint(POINT_GROUND, centerPos);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ bool WasVampire(uint64 guid)
+ {
+ return vampires.count(guid) != 0;
+ }
+
+ private:
+ // offtank for this encounter is the player standing closest to main tank
+ Player* SelectRandomTarget(bool includeOfftank, std::list<Player*>* targetList = NULL)
+ {
+ const std::list<HostileReference*> &threatlist = me->getThreatManager().getThreatList();
+ std::list<Player*> tempTargets;
+
+ if (threatlist.empty())
+ return NULL;
+
+ for (std::list<HostileReference*>::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
+ if (Unit* refTarget = (*itr)->getTarget())
+ if (refTarget != me->getVictim() && refTarget->GetTypeId() == TYPEID_PLAYER && (includeOfftank ? true : (refTarget != offtank)))
+ tempTargets.push_back(refTarget->ToPlayer());
+
+ if (tempTargets.empty())
+ return NULL;
+
+ if (targetList)
+ {
+ *targetList = tempTargets;
+ return NULL;
+ }
+
+ if (includeOfftank)
+ {
+ tempTargets.sort(Trinity::ObjectDistanceOrderPred(me->getVictim()));
+ return tempTargets.front();
+ }
+
+ std::list<Player*>::iterator itr = tempTargets.begin();
+ std::advance(itr, urand(1, tempTargets.size()-1));
+ return *itr;
+ }
+
+ Player* offtank;
+ std::set<uint64> vampires;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new boss_blood_queen_lana_thelAI(creature);
+ }
+};
+
+// helper for shortened code
+typedef boss_blood_queen_lana_thel::boss_blood_queen_lana_thelAI LanaThelAI;
+
+class spell_blood_queen_vampiric_bite : public SpellScriptLoader
+{
+ public:
+ spell_blood_queen_vampiric_bite() : SpellScriptLoader("spell_blood_queen_vampiric_bite") { }
+
+ class spell_blood_queen_vampiric_bite_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_blood_queen_vampiric_bite_SpellScript);
+
+ bool Validate(SpellEntry const* /*spell*/)
+ {
+ if (!sSpellStore.LookupEntry(SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR))
+ return false;
+ if (!sSpellStore.LookupEntry(SPELL_FRENZIED_BLOODTHIRST))
+ return false;
+ if (!sSpellStore.LookupEntry(SPELL_PRESENCE_OF_THE_DARKFALLEN))
+ return false;
+ return true;
+ }
+
+ void OnCast()
+ {
+ if (GetCaster()->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (IsVampire(GetHitUnit()))
+ {
+ PreventHitDamage();
+ PreventHitDefaultEffect(EFFECT_1);
+ Spell::SendCastResult(GetCaster()->ToPlayer(), GetSpellInfo(), 0, SPELL_FAILED_BAD_TARGETS);
+ return;
+ }
+
+ SpellEntry const* spell = sSpellStore.LookupEntry(SPELL_FRENZIED_BLOODTHIRST);
+ spell = sSpellMgr.GetSpellForDifficultyFromSpell(spell, GetCaster());
+ GetCaster()->RemoveAura(spell->Id, 0, 0, AURA_REMOVE_BY_ENEMY_SPELL);
+ GetCaster()->CastSpell(GetCaster(), SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR, true);
+ if (GetCaster()->GetMap()->IsHeroic())
+ GetCaster()->CastSpell(GetCaster(), SPELL_PRESENCE_OF_THE_DARKFALLEN, true);
+ if (InstanceScript* instance = GetCaster()->GetInstanceScript())
+ if (Creature* bloodQueen = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_BLOOD_QUEEN_LANA_THEL)))
+ bloodQueen->AI()->SetGUID(GetHitUnit()->GetGUID(), GUID_VAMPIRE);
+ }
+
+ void Register()
+ {
+ BeforeHit += SpellHitFn(spell_blood_queen_vampiric_bite_SpellScript::OnCast);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_blood_queen_vampiric_bite_SpellScript();
+ }
+};
+
+class spell_blood_queen_frenzied_bloodthirst : public SpellScriptLoader
+{
+ public:
+ spell_blood_queen_frenzied_bloodthirst() : SpellScriptLoader("spell_blood_queen_frenzied_bloodthirst") { }
+
+ class spell_blood_queen_frenzied_bloodthirst_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_blood_queen_frenzied_bloodthirst_AuraScript);
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraApplication const* aurApp, AuraEffectHandleModes /*mode*/)
+ {
+ if (InstanceScript* instance = aurApp->GetTarget()->GetInstanceScript())
+ if (Creature* bloodQueen = ObjectAccessor::GetCreature(*aurApp->GetTarget(), instance->GetData64(DATA_BLOOD_QUEEN_LANA_THEL)))
+ bloodQueen->AI()->Talk(EMOTE_BLOODTHIRST);
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraApplication const* aurApp, AuraEffectHandleModes /*mode*/)
+ {
+ if (!aurApp)
+ return;
+
+ Unit* target = aurApp->GetTarget();
+ if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
+ if (InstanceScript* instance = target->GetInstanceScript())
+ if (Creature* bloodQueen = ObjectAccessor::GetCreature(*target, instance->GetData64(DATA_BLOOD_QUEEN_LANA_THEL)))
+ {
+ // this needs to be done BEFORE charm aura or we hit an assert in Unit::SetCharmedBy
+ if (target->GetVehicleKit())
+ target->RemoveVehicleKit();
+
+ bloodQueen->AI()->Talk(SAY_MIND_CONTROL);
+ bloodQueen->CastSpell(target, SPELL_UNCONTROLLABLE_FRENZY, true);
+ }
+ }
+
+ void Register()
+ {
+ OnEffectRemove += AuraEffectRemoveFn(spell_blood_queen_frenzied_bloodthirst_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_OVERRIDE_SPELLS, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_blood_queen_frenzied_bloodthirst_AuraScript();
+ }
+};
+
+class spell_blood_queen_bloodbolt : public SpellScriptLoader
+{
+ public:
+ spell_blood_queen_bloodbolt() : SpellScriptLoader("spell_blood_queen_bloodbolt") { }
+
+ class spell_blood_queen_bloodbolt_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_blood_queen_bloodbolt_SpellScript);
+
+ bool Validate(SpellEntry const* /*spell*/)
+ {
+ if (!sSpellStore.LookupEntry(SPELL_TWILIGHT_BLOODBOLT))
+ return false;
+ return true;
+ }
+
+ void HandleDummy()
+ {
+ if (GetHitUnit()->GetTypeId() == TYPEID_PLAYER)
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_TWILIGHT_BLOODBOLT, true);
+ }
+
+ void Register()
+ {
+ AfterHit += SpellHitFn(spell_blood_queen_bloodbolt_SpellScript::HandleDummy);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_blood_queen_bloodbolt_SpellScript();
+ }
+};
+
+class achievement_once_bitten_twice_shy_n : public AchievementCriteriaScript
+{
+ public:
+ achievement_once_bitten_twice_shy_n() : AchievementCriteriaScript("achievement_once_bitten_twice_shy_n") { }
+
+ bool OnCheck(Player* source, Unit* target)
+ {
+ if (!target)
+ return false;
+
+ if (LanaThelAI* lanaThelAI = CAST_AI(LanaThelAI, target->GetAI()))
+ return !lanaThelAI->WasVampire(source->GetGUID());
+ return false;
+ }
+};
+
+class achievement_once_bitten_twice_shy_v : public AchievementCriteriaScript
+{
+ public:
+ achievement_once_bitten_twice_shy_v() : AchievementCriteriaScript("achievement_once_bitten_twice_shy_v") { }
+
+ bool OnCheck(Player* source, Unit* target)
+ {
+ if (!target)
+ return false;
+
+ if (LanaThelAI* lanaThelAI = CAST_AI(LanaThelAI, target->GetAI()))
+ return lanaThelAI->WasVampire(source->GetGUID());
+ return false;
+ }
+};
+
+void AddSC_boss_blood_queen_lana_thel()
+{
+ new boss_blood_queen_lana_thel();
+ new spell_blood_queen_vampiric_bite();
+ new spell_blood_queen_frenzied_bloodthirst();
+ new spell_blood_queen_bloodbolt();
+ new achievement_once_bitten_twice_shy_n();
+ new achievement_once_bitten_twice_shy_v();
+}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
index ff406537c93..f607977340c 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
@@ -180,7 +180,6 @@ class boss_lady_deathwhisper : public CreatureScript
void Reset()
{
- me->SetReactState(REACT_DEFENSIVE);
me->SetPower(POWER_MANA, me->GetMaxPower(POWER_MANA));
me->SetLastManaUse(0xFFFFFFFF); // hacky, but no other way atm to prevent mana regen
events.Reset();
@@ -211,8 +210,6 @@ class boss_lady_deathwhisper : public CreatureScript
events.ScheduleEvent(EVENT_INTRO_7, 58000, 0, PHASE_INTRO);
events.ScheduleEvent(EVENT_INTRO_FINISH, 76000, 0, PHASE_INTRO);
}
-
- BossAI::MoveInLineOfSight(who);
}
void AttackStart(Unit* victim)
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
index 154da5c9192..51cffb4442d 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
@@ -367,6 +367,12 @@ class npc_bone_spike : public CreatureScript
trappedGUID = 0;
}
+ void KilledUnit(Unit* victim)
+ {
+ if (TempSummon* summ = me->ToTempSummon())
+ summ->UnSummon();
+ }
+
void IsSummonedBy(Unit* summoner)
{
trappedGUID = summoner->GetGUID();
@@ -375,11 +381,13 @@ class npc_bone_spike : public CreatureScript
events.ScheduleEvent(EVENT_FAIL_BONED, 8000);
}
- void UpdateAI(const uint32 /*diff*/)
+ void UpdateAI(const uint32 diff)
{
if (!trappedGUID)
return;
+ events.Update(diff);
+
if (events.ExecuteEvent() == EVENT_FAIL_BONED)
if (InstanceScript* instance = me->GetInstanceScript())
instance->SetData(DATA_BONED_ACHIEVEMENT, uint32(false));
@@ -439,7 +447,7 @@ class spell_marrowgar_bone_spike_graveyard : public SpellScriptLoader
{
PrepareSpellScript(spell_marrowgar_bone_spike_graveyard_SpellScript);
- void HandleScript(SpellEffIndex effIndex)
+ void HandleSpikes(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
if (Creature* marrowgar = GetCaster()->ToCreature())
@@ -466,7 +474,7 @@ class spell_marrowgar_bone_spike_graveyard : public SpellScriptLoader
void Register()
{
- OnEffect += SpellEffectFn(spell_marrowgar_bone_spike_graveyard_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnEffect += SpellEffectFn(spell_marrowgar_bone_spike_graveyard_SpellScript::HandleSpikes, EFFECT_1, SPELL_EFFECT_APPLY_AURA);
}
};
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
index 0b5a120fe24..14c4bfa6d06 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
@@ -136,6 +136,9 @@ enum eCreatures
NPC_KINETIC_BOMB_TARGET = 38458,
NPC_KINETIC_BOMB = 38454,
NPC_SHOCK_VORTEX = 38422,
+
+ // Blood-Queen Lana'thel
+ NPC_BLOOD_QUEEN_LANA_THEL = 37955,
};
enum eGameobjects
@@ -190,28 +193,36 @@ enum eGameobjects
enum eAchievementCriteria
{
// Lord Marrowgar
- CRITERIA_BONED_10N = 12775,
- CRITERIA_BONED_25N = 12962,
- CRITERIA_BONED_10H = 13393,
- CRITERIA_BONED_25H = 13394,
+ CRITERIA_BONED_10N = 12775,
+ CRITERIA_BONED_25N = 12962,
+ CRITERIA_BONED_10H = 13393,
+ CRITERIA_BONED_25H = 13394,
// Rotface
- CRITERIA_DANCES_WITH_OOZES_10N = 12984,
- CRITERIA_DANCES_WITH_OOZES_25N = 12966,
- CRITERIA_DANCES_WITH_OOZES_10H = 12985,
- CRITERIA_DANCES_WITH_OOZES_25H = 12983,
+ CRITERIA_DANCES_WITH_OOZES_10N = 12984,
+ CRITERIA_DANCES_WITH_OOZES_25N = 12966,
+ CRITERIA_DANCES_WITH_OOZES_10H = 12985,
+ CRITERIA_DANCES_WITH_OOZES_25H = 12983,
// Professor Putricide
- CRITERIA_NAUSEA_10N = 12987,
- CRITERIA_NAUSEA_25N = 12968,
- CRITERIA_NAUSEA_10H = 12988,
- CRITERIA_NAUSEA_25H = 12981,
+ CRITERIA_NAUSEA_10N = 12987,
+ CRITERIA_NAUSEA_25N = 12968,
+ CRITERIA_NAUSEA_10H = 12988,
+ CRITERIA_NAUSEA_25H = 12981,
// Blood Prince Council
- CRITERIA_ORB_WHISPERER_10N = 13033,
- CRITERIA_ORB_WHISPERER_25N = 12969,
- CRITERIA_ORB_WHISPERER_10H = 13034,
- CRITERIA_ORB_WHISPERER_25H = 13032,
+ CRITERIA_ORB_WHISPERER_10N = 13033,
+ CRITERIA_ORB_WHISPERER_25N = 12969,
+ CRITERIA_ORB_WHISPERER_10H = 13034,
+ CRITERIA_ORB_WHISPERER_25H = 13032,
+
+ // Blood-Queen Lana'thel
+ CRITERIA_KILL_LANA_THEL_10M = 13340,
+ CRITERIA_KILL_LANA_THEL_25M = 13360,
+ CRITERIA_ONCE_BITTEN_TWICE_SHY_10N = 12780,
+ CRITERIA_ONCE_BITTEN_TWICE_SHY_25N = 13012,
+ CRITERIA_ONCE_BITTEN_TWICE_SHY_10V = 13011,
+ CRITERIA_ONCE_BITTEN_TWICE_SHY_25V = 13013,
};
enum eSharedActions
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
index f92bff6b9dc..a0ad03265d9 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
@@ -18,6 +18,8 @@
#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "InstanceScript.h"
+#include "ScriptedCreature.h"
+#include "Map.h"
#include "icecrown_citadel.h"
static const DoorData doorData[] =
@@ -53,6 +55,7 @@ class instance_icecrown_citadel : public InstanceMapScript
{
SetBossNumber(MAX_ENCOUNTER);
LoadDoorData(doorData);
+ teamInInstance = 0;
ladyDeathwisperElevator = 0;
deathbringerSaurfang = 0;
saurfangDoor = 0;
@@ -68,73 +71,82 @@ class instance_icecrown_citadel : public InstanceMapScript
putricideTable = 0;
memset(bloodCouncil, 0, 3*sizeof(uint64));
bloodCouncilController = 0;
+ bloodQueenLanaThel = 0;
isBonedEligible = true;
isOozeDanceEligible = true;
isNauseaEligible = true;
isOrbWhispererEligible = true;
}
- void OnCreatureCreate(Creature* creature, bool /*add*/)
+ void OnPlayerEnter(Player* player)
{
- Map::PlayerList const &players = instance->GetPlayers();
- uint32 TeamInInstance = 0;
+ if (!teamInInstance)
+ teamInInstance = player->GetTeam();
+ }
+
+ void OnCreatureCreate(Creature* creature, bool add)
+ {
+ if (!add)
+ return;
- if (!players.isEmpty())
+ if (!teamInInstance)
{
- if (Player* pPlayer = players.begin()->getSource())
- TeamInInstance = pPlayer->GetTeam();
+ Map::PlayerList const &players = instance->GetPlayers();
+ if (!players.isEmpty())
+ if (Player* player = players.begin()->getSource())
+ teamInInstance = player->GetTeam();
}
switch (creature->GetEntry())
{
case NPC_KOR_KRON_GENERAL:
- if (TeamInInstance == ALLIANCE)
+ if (teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_ALLIANCE_COMMANDER, ALLIANCE);
break;
case NPC_KOR_KRON_LIEUTENANT:
- if (TeamInInstance == ALLIANCE)
+ if (teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_SKYBREAKER_LIEUTENANT, ALLIANCE);
break;
case NPC_TORTUNOK:
- if (TeamInInstance == ALLIANCE)
+ if (teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_ALANA_MOONSTRIKE, ALLIANCE);
break;
case NPC_GERARDO_THE_SUAVE:
- if (TeamInInstance == ALLIANCE)
+ if (teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_TALAN_MOONSTRIKE, ALLIANCE);
break;
case NPC_UVLUS_BANEFIRE:
- if (TeamInInstance == ALLIANCE)
+ if (teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_MALFUS_GRIMFROST, ALLIANCE);
break;
case NPC_IKFIRUS_THE_VILE:
- if (TeamInInstance == ALLIANCE)
+ if (teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_YILI, ALLIANCE);
break;
case NPC_VOL_GUK:
- if (TeamInInstance == ALLIANCE)
+ if (teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_JEDEBIA, ALLIANCE);
break;
case NPC_HARAGG_THE_UNSEEN:
- if (TeamInInstance == ALLIANCE)
+ if (teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_NIBY_THE_ALMIGHTY, ALLIANCE);
break;
case NPC_GARROSH_HELLSCREAM:
- if (TeamInInstance == ALLIANCE)
+ if (teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_KING_VARIAN_WRYNN, ALLIANCE);
break;
case NPC_DEATHBRINGER_SAURFANG:
deathbringerSaurfang = creature->GetGUID();
break;
case NPC_SE_HIGH_OVERLORD_SAURFANG:
- if (TeamInInstance == ALLIANCE)
+ if (teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_SE_MURADIN_BRONZEBEARD, ALLIANCE);
case NPC_SE_MURADIN_BRONZEBEARD:
saurfangEventNPC = creature->GetGUID();
creature->LastUsedScriptID = creature->GetScriptId();
break;
case NPC_SE_KOR_KRON_REAVER:
- if (TeamInInstance == ALLIANCE)
+ if (teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_SE_SKYBREAKER_MARINE, ALLIANCE);
break;
case NPC_FESTERGUT:
@@ -158,6 +170,9 @@ class instance_icecrown_citadel : public InstanceMapScript
case NPC_BLOOD_ORB_CONTROLLER:
bloodCouncilController = creature->GetGUID();
break;
+ case NPC_BLOOD_QUEEN_LANA_THEL:
+ bloodQueenLanaThel = creature->GetGUID();
+ break;
default:
break;
}
@@ -271,6 +286,8 @@ class instance_icecrown_citadel : public InstanceMapScript
return bloodCouncil[2];
case DATA_BLOOD_PRINCES_CONTROL:
return bloodCouncilController;
+ case DATA_BLOOD_QUEEN_LANA_THEL:
+ return bloodQueenLanaThel;
default:
break;
}
@@ -400,6 +417,15 @@ class instance_icecrown_citadel : public InstanceMapScript
case CRITERIA_ORB_WHISPERER_10H:
case CRITERIA_ORB_WHISPERER_25H:
return isOrbWhispererEligible;
+ // Only one criteria for both modes, need to do it like this
+ case CRITERIA_KILL_LANA_THEL_10M:
+ case CRITERIA_ONCE_BITTEN_TWICE_SHY_10N:
+ case CRITERIA_ONCE_BITTEN_TWICE_SHY_10V:
+ return CAST_INST(InstanceMap, instance)->GetMaxPlayers() == 10;
+ case CRITERIA_KILL_LANA_THEL_25M:
+ case CRITERIA_ONCE_BITTEN_TWICE_SHY_25N:
+ case CRITERIA_ONCE_BITTEN_TWICE_SHY_25V:
+ return CAST_INST(InstanceMap, instance)->GetMaxPlayers() == 25;
default:
break;
}
@@ -449,6 +475,7 @@ class instance_icecrown_citadel : public InstanceMapScript
}
private:
+ uint32 teamInInstance;
uint64 ladyDeathwisperElevator;
uint64 deathbringerSaurfang;
uint64 saurfangDoor;
@@ -464,6 +491,7 @@ class instance_icecrown_citadel : public InstanceMapScript
uint64 putricideTable;
uint64 bloodCouncil[3];
uint64 bloodCouncilController;
+ uint64 bloodQueenLanaThel;
bool isBonedEligible;
bool isOozeDanceEligible;
bool isNauseaEligible;