aboutsummaryrefslogtreecommitdiff
path: root/src/server/scripts
diff options
context:
space:
mode:
authorVincent-Michael <Vincent_Michael@gmx.de>2014-07-20 03:06:03 +0200
committerVincent-Michael <Vincent_Michael@gmx.de>2014-07-20 03:06:03 +0200
commite68d3b0937e205c94c17d7cb1a53194b6d169fe8 (patch)
tree326d69976375006fe244df6e858bd20e83fcae90 /src/server/scripts
parentabe8dd7abf70b3589ad0cbba19f91bd4f743bf3e (diff)
parent0531f52008cfc4ecb28c0b3cd67504e06452ab75 (diff)
Merge branch 'master' of github.com:TrinityCore/TrinityCore into 4.3.4
Conflicts: src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp src/server/scripts/Northrend/zone_dalaran.cpp src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp
Diffstat (limited to 'src/server/scripts')
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp429
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp24
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h4
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp171
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp4
-rw-r--r--src/server/scripts/Northrend/zone_dalaran.cpp113
6 files changed, 376 insertions, 369 deletions
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp
index d6c0f95f967..d34123c58b2 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* 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
@@ -16,13 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Selin_Fireheart
-SD%Complete: 90
-SDComment: Heroic and Normal Support. Needs further testing.
-SDCategory: Magister's Terrace
-EndScriptData */
-
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "magisters_terrace.h"
@@ -39,321 +31,264 @@ enum Says
enum Spells
{
- //Crystal effect spells
- SPELL_FEL_CRYSTAL_COSMETIC = 44374,
+ // Crystal effect spells
SPELL_FEL_CRYSTAL_DUMMY = 44329,
- SPELL_FEL_CRYSTAL_VISUAL = 44355,
SPELL_MANA_RAGE = 44320, // This spell triggers 44321, which changes scale and regens mana Requires an entry in spell_script_target
- //Selin's spells
+ // Selin's spells
SPELL_DRAIN_LIFE = 44294,
SPELL_FEL_EXPLOSION = 44314,
SPELL_DRAIN_MANA = 46153 // Heroic only
};
+enum Phases
+{
+ PHASE_NORMAL = 1,
+ PHASE_DRAIN = 2
+};
+
+enum Events
+{
+ EVENT_FEL_EXPLOSION = 1,
+ EVENT_DRAIN_CRYSTAL,
+ EVENT_DRAIN_MANA,
+ EVENT_DRAIN_LIFE,
+ EVENT_EMPOWER
+};
+
enum Misc
{
- CRYSTALS_NUMBER = 5,
- DATA_CRYSTALS = 6,
- CREATURE_FEL_CRYSTAL = 24722
+ ACTION_SWITCH_PHASE = 1
};
class boss_selin_fireheart : public CreatureScript
{
-public:
- boss_selin_fireheart() : CreatureScript("boss_selin_fireheart") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_selin_fireheartAI>(creature);
- };
+ public:
+ boss_selin_fireheart() : CreatureScript("boss_selin_fireheart") { }
- struct boss_selin_fireheartAI : public ScriptedAI
- {
- boss_selin_fireheartAI(Creature* creature) : ScriptedAI(creature)
+ struct boss_selin_fireheartAI : public BossAI
{
- instance = creature->GetInstanceScript();
-
- Crystals.clear();
- //GUIDs per instance is static, so we only need to load them once.
- uint32 size = instance->GetData(DATA_FEL_CRYSTAL_SIZE);
- for (uint8 i = 0; i < size; ++i)
+ boss_selin_fireheartAI(Creature* creature) : BossAI(creature, DATA_SELIN)
{
- instance->SetData64(DATA_FEL_CRYSTAL, i);
- uint64 guid = instance->GetData64(DATA_FEL_CRYSTAL);
- TC_LOG_DEBUG("scripts", "Selin: Adding Fel Crystal " UI64FMTD " to list", guid);
- Crystals.push_back(guid);
+ CrystalGUID = 0;
+ _scheduledEvents = false;
}
- }
-
- InstanceScript* instance;
-
- std::list<uint64> Crystals;
- uint32 DrainLifeTimer;
- uint32 DrainManaTimer;
- uint32 FelExplosionTimer;
- uint32 DrainCrystalTimer;
- uint32 EmpowerTimer;
-
- bool IsDraining;
- bool DrainingCrystal;
-
- uint64 CrystalGUID; // This will help us create a pointer to the crystal we are draining. We store GUIDs, never units in case unit is deleted/offline (offline if player of course).
-
- void Reset() override
- {
- //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i)
- for (std::list<uint64>::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr)
+ void Reset() override
{
- //Unit* unit = ObjectAccessor::GetUnit(*me, FelCrystals[i]);
- if (Creature* creature = ObjectAccessor::GetCreature(*me, *itr))
+ Crystals.clear();
+ me->GetCreatureListWithEntryInGrid(Crystals, NPC_FEL_CRYSTAL, 250.0f);
+
+ for (Creature* creature : Crystals)
{
if (!creature->IsAlive())
- creature->Respawn(); // Let the core handle setting death state, etc.
+ creature->Respawn();
- // Only need to set unselectable flag. You can't attack unselectable units so non_attackable flag is not necessary here.
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
- }
- // Set Inst data for encounter
- instance->SetBossState(DATA_SELIN, NOT_STARTED);
-
- DrainLifeTimer = urand(3000, 7000);
- DrainManaTimer = DrainLifeTimer + 5000;
- FelExplosionTimer = 2100;
- if (IsHeroic())
- DrainCrystalTimer = urand(10000, 15000);
- else
- DrainCrystalTimer = urand(20000, 25000);
- EmpowerTimer = 10000;
-
- IsDraining = false;
- DrainingCrystal = false;
- CrystalGUID = 0;
- }
+ _Reset();
+ CrystalGUID = 0;
+ _scheduledEvents = false;
+ }
- void SelectNearestCrystal()
- {
- if (Crystals.empty())
- return;
-
- //float ShortestDistance = 0;
- CrystalGUID = 0;
- Unit* pCrystal = NULL;
- Unit* CrystalChosen = NULL;
- //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i)
- for (std::list<uint64>::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr)
+ void DoAction(int32 action) override
{
- pCrystal = NULL;
- //pCrystal = ObjectAccessor::GetUnit(*me, FelCrystals[i]);
- pCrystal = ObjectAccessor::GetUnit(*me, *itr);
- if (pCrystal && pCrystal->IsAlive())
+ switch (action)
{
- // select nearest
- if (!CrystalChosen || me->GetDistanceOrder(pCrystal, CrystalChosen, false))
- {
- CrystalGUID = pCrystal->GetGUID();
- CrystalChosen = pCrystal; // Store a copy of pCrystal so we don't need to recreate a pointer to closest crystal for the movement and yell.
- }
+ case ACTION_SWITCH_PHASE:
+ events.SetPhase(PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_FEL_EXPLOSION, 2000, 0, PHASE_NORMAL);
+ AttackStart(me->GetVictim());
+ me->GetMotionMaster()->MoveChase(me->GetVictim());
+ break;
+ default:
+ break;
}
}
- if (CrystalChosen)
+
+ void SelectNearestCrystal()
{
- Talk(SAY_ENERGY);
- Talk(EMOTE_CRYSTAL);
+ if (Crystals.empty())
+ return;
- CrystalChosen->CastSpell(CrystalChosen, SPELL_FEL_CRYSTAL_COSMETIC, true);
+ Crystals.sort(Trinity::ObjectDistanceOrderPred(me));
+ if (Creature* CrystalChosen = Crystals.front())
+ {
+ Talk(SAY_ENERGY);
+ Talk(EMOTE_CRYSTAL);
- float x, y, z; // coords that we move to, close to the crystal.
- CrystalChosen->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE);
+ DoCast(CrystalChosen, SPELL_FEL_CRYSTAL_DUMMY);
+ CrystalGUID = CrystalChosen->GetGUID();
+ Crystals.remove(CrystalChosen);
- me->SetWalk(false);
- me->GetMotionMaster()->MovePoint(1, x, y, z);
- DrainingCrystal = true;
- }
- }
+ float x, y, z;
+ CrystalChosen->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE);
- void ShatterRemainingCrystals()
- {
- if (Crystals.empty())
- return;
+ events.SetPhase(PHASE_DRAIN);
+ me->SetWalk(false);
+ me->GetMotionMaster()->MovePoint(1, x, y, z);
+ }
+ }
- //for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i)
- for (std::list<uint64>::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr)
+ void ShatterRemainingCrystals()
{
- //Creature* pCrystal = (ObjectAccessor::GetCreature(*me, FelCrystals[i]));
- Creature* pCrystal = ObjectAccessor::GetCreature(*me, *itr);
- if (pCrystal && pCrystal->IsAlive())
- pCrystal->Kill(pCrystal);
+ if (Crystals.empty())
+ return;
+
+ for (Creature* crystal : Crystals)
+ {
+ if (crystal && crystal->IsAlive())
+ crystal->Kill(crystal);
+ }
}
- }
- void EnterCombat(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
- instance->SetBossState(DATA_SELIN, IN_PROGRESS);
- }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ Talk(SAY_AGGRO);
+ _EnterCombat();
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_KILL);
- }
+ events.SetPhase(PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_FEL_EXPLOSION, 2100, 0, PHASE_NORMAL);
+ }
- void MovementInform(uint32 type, uint32 id) override
- {
- if (type == POINT_MOTION_TYPE && id == 1)
+ void KilledUnit(Unit* victim) override
{
- Unit* CrystalChosen = ObjectAccessor::GetUnit(*me, CrystalGUID);
- if (CrystalChosen && CrystalChosen->IsAlive())
- {
- // Make the crystal attackable
- // We also remove NON_ATTACKABLE in case the database has it set.
- CrystalChosen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
- CrystalChosen->CastSpell(me, SPELL_MANA_RAGE, true);
- IsDraining = true;
- }
- else
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_KILL);
+ }
+
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type == POINT_MOTION_TYPE && id == 1)
{
- // Make an error message in case something weird happened here
- TC_LOG_ERROR("scripts", "Selin Fireheart unable to drain crystal as the crystal is either dead or despawned");
- DrainingCrystal = false;
+ Unit* CrystalChosen = ObjectAccessor::GetUnit(*me, CrystalGUID);
+ if (CrystalChosen && CrystalChosen->IsAlive())
+ {
+ CrystalChosen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ CrystalChosen->CastSpell(me, SPELL_MANA_RAGE, true);
+ events.ScheduleEvent(EVENT_EMPOWER, 10000, PHASE_DRAIN);
+ }
}
}
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- Talk(SAY_DEATH);
- instance->SetBossState(DATA_SELIN, DONE); // Encounter complete!
- ShatterRemainingCrystals();
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ Talk(SAY_DEATH);
+ _JustDied();
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ ShatterRemainingCrystals();
+ }
- if (!DrainingCrystal)
+ void UpdateAI(uint32 diff) override
{
- uint32 maxPowerMana = me->GetMaxPower(POWER_MANA);
- if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10))
- {
- if (DrainLifeTimer <= diff)
- {
- DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_DRAIN_LIFE);
- DrainLifeTimer = 10000;
- } else DrainLifeTimer -= diff;
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
- // Heroic only
- if (IsHeroic())
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- if (DrainManaTimer <= diff)
+ case EVENT_FEL_EXPLOSION:
+ DoCastAOE(SPELL_FEL_EXPLOSION);
+ events.ScheduleEvent(EVENT_FEL_EXPLOSION, 2000, 0, PHASE_NORMAL);
+ break;
+ case EVENT_DRAIN_CRYSTAL:
+ SelectNearestCrystal();
+ _scheduledEvents = false;
+ break;
+ case EVENT_DRAIN_MANA:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true))
+ DoCast(target, SPELL_DRAIN_MANA);
+ events.ScheduleEvent(EVENT_DRAIN_MANA, 10000, 0, PHASE_NORMAL);
+ break;
+ case EVENT_DRAIN_LIFE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20.0f, true))
+ DoCast(target, SPELL_DRAIN_LIFE);
+ events.ScheduleEvent(EVENT_DRAIN_LIFE, 10000, 0, PHASE_NORMAL);
+ break;
+ case EVENT_EMPOWER:
{
- DoCast(SelectTarget(SELECT_TARGET_RANDOM, 1), SPELL_DRAIN_MANA);
- DrainManaTimer = 10000;
- } else DrainManaTimer -= diff;
+ Talk(SAY_EMPOWERED);
+
+ Creature* CrystalChosen = ObjectAccessor::GetCreature(*me, CrystalGUID);
+ if (CrystalChosen && CrystalChosen->IsAlive())
+ CrystalChosen->Kill(CrystalChosen);
+
+ CrystalGUID = 0;
+
+ me->GetMotionMaster()->Clear();
+ me->GetMotionMaster()->MoveChase(me->GetVictim());
+ break;
+ }
+ default:
+ break;
}
}
- if (FelExplosionTimer <= diff)
+ if (me->GetPower(POWER_MANA) * 100 / me->GetMaxPower(POWER_MANA) < 10)
{
- if (!me->IsNonMeleeSpellCast(false))
+ if (events.IsInPhase(PHASE_NORMAL) && !_scheduledEvents)
{
- DoCast(me, SPELL_FEL_EXPLOSION);
- FelExplosionTimer = 2000;
- }
- } else FelExplosionTimer -= diff;
+ _scheduledEvents = true;
+ uint32 timer = urand(3000, 7000);
+ events.ScheduleEvent(EVENT_DRAIN_LIFE, timer, 0, PHASE_NORMAL);
- // If below 10% mana, start recharging
- maxPowerMana = me->GetMaxPower(POWER_MANA);
- if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10))
- {
- if (DrainCrystalTimer <= diff)
- {
- SelectNearestCrystal();
if (IsHeroic())
- DrainCrystalTimer = urand(10000, 15000);
+ {
+ events.ScheduleEvent(EVENT_DRAIN_CRYSTAL, urand(10000, 15000), 0, PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_DRAIN_MANA, timer + 5000, 0, PHASE_NORMAL);
+ }
else
- DrainCrystalTimer = urand(20000, 25000);
- } else DrainCrystalTimer -= diff;
+ events.ScheduleEvent(EVENT_DRAIN_CRYSTAL, urand(20000, 25000), 0, PHASE_NORMAL);
+ }
}
- }else
- {
- if (IsDraining)
- {
- if (EmpowerTimer <= diff)
- {
- IsDraining = false;
- DrainingCrystal = false;
-
- Talk(SAY_EMPOWERED);
-
- Unit* CrystalChosen = ObjectAccessor::GetUnit(*me, CrystalGUID);
- if (CrystalChosen && CrystalChosen->IsAlive())
- // Use Deal Damage to kill it, not setDeathState.
- CrystalChosen->Kill(CrystalChosen);
-
- CrystalGUID = 0;
- me->GetMotionMaster()->Clear();
- me->GetMotionMaster()->MoveChase(me->GetVictim());
- } else EmpowerTimer -= diff;
- }
+ DoMeleeAttackIfReady();
}
- DoMeleeAttackIfReady(); // No need to check if we are draining crystal here, as the spell has a stun.
- }
- };
+ private:
+ std::list<Creature*> Crystals;
+ uint64 CrystalGUID;
+ bool _scheduledEvents;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_selin_fireheartAI>(creature);
+ };
};
class npc_fel_crystal : public CreatureScript
{
-public:
- npc_fel_crystal() : CreatureScript("npc_fel_crystal") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_fel_crystalAI(creature);
- };
+ public:
+ npc_fel_crystal() : CreatureScript("npc_fel_crystal") { }
- struct npc_fel_crystalAI : public ScriptedAI
- {
- npc_fel_crystalAI(Creature* creature) : ScriptedAI(creature) { }
-
- void Reset() override { }
- void EnterCombat(Unit* /*who*/) override { }
- void AttackStart(Unit* /*who*/) override { }
- void MoveInLineOfSight(Unit* /*who*/) override { }
-
- void UpdateAI(uint32 /*diff*/) override { }
-
- void JustDied(Unit* /*killer*/) override
+ struct npc_fel_crystalAI : public ScriptedAI
{
- if (InstanceScript* instance = me->GetInstanceScript())
+ npc_fel_crystalAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void JustDied(Unit* /*killer*/) override
{
- Creature* Selin = (ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SELIN)));
- if (Selin && Selin->IsAlive())
+ if (InstanceScript* instance = me->GetInstanceScript())
{
- if (CAST_AI(boss_selin_fireheart::boss_selin_fireheartAI, Selin->AI())->CrystalGUID == me->GetGUID())
- {
- // Set this to false if we are the Creature that Selin is draining so his AI flows properly
- CAST_AI(boss_selin_fireheart::boss_selin_fireheartAI, Selin->AI())->DrainingCrystal = false;
- CAST_AI(boss_selin_fireheart::boss_selin_fireheartAI, Selin->AI())->IsDraining = false;
- CAST_AI(boss_selin_fireheart::boss_selin_fireheartAI, Selin->AI())->EmpowerTimer = 10000;
- if (Selin->GetVictim())
- {
- Selin->AI()->AttackStart(Selin->GetVictim());
- Selin->GetMotionMaster()->MoveChase(Selin->GetVictim());
- }
- }
+ Creature* Selin = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SELIN));
+ if (Selin && Selin->IsAlive())
+ Selin->AI()->DoAction(ACTION_SWITCH_PHASE);
}
}
- }
- };
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_fel_crystalAI>(creature);
+ };
};
void AddSC_boss_selin_fireheart()
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp
index 950d3c3d8f6..65b3553fd87 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp
@@ -48,13 +48,11 @@ class instance_magisters_terrace : public InstanceMapScript
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
- FelCrystals.clear();
DelrissaDeathCount = 0;
SelinGUID = 0;
DelrissaGUID = 0;
EscapeOrbGUID = 0;
- FelCristalIndex = 0;
memset(KaelStatue, 0, 2 * sizeof(uint64));
}
@@ -65,8 +63,6 @@ class instance_magisters_terrace : public InstanceMapScript
{
case DATA_DELRISSA_DEATH_COUNT:
return DelrissaDeathCount;
- case DATA_FEL_CRYSTAL_SIZE:
- return uint32(FelCrystals.size());
default:
break;
}
@@ -102,9 +98,6 @@ class instance_magisters_terrace : public InstanceMapScript
case NPC_DELRISSA:
DelrissaGUID = creature->GetGUID();
break;
- case NPC_FELCRYSTALS:
- FelCrystals.push_back(creature->GetGUID());
- break;
default:
break;
}
@@ -224,35 +217,18 @@ class instance_magisters_terrace : public InstanceMapScript
return KaelStatue[1];
case DATA_ESCAPE_ORB:
return EscapeOrbGUID;
- case DATA_FEL_CRYSTAL:
- if (FelCrystals.size() < FelCristalIndex)
- {
- TC_LOG_ERROR("scripts", "Magisters Terrace: No Fel Crystals loaded in Inst Data");
- return 0;
- }
-
- return FelCrystals.at(FelCristalIndex);
default:
break;
}
return 0;
}
- void SetData64(uint32 type, uint64 value) override
- {
- if (type == DATA_FEL_CRYSTAL)
- FelCristalIndex = value;
- }
-
protected:
- std::vector<uint64> FelCrystals;
-
uint64 SelinGUID;
uint64 DelrissaGUID;
uint64 KaelStatue[2];
uint64 EscapeOrbGUID;
uint32 DelrissaDeathCount;
- uint8 FelCristalIndex;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h
index d3517dfccf6..8b8d7d5b875 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.h
@@ -28,8 +28,6 @@ enum DataTypes
DATA_DELRISSA,
DATA_KAELTHAS,
- DATA_FEL_CRYSTAL,
- DATA_FEL_CRYSTAL_SIZE,
DATA_KAEL_STATUE_LEFT,
DATA_KAEL_STATUE_RIGHT,
@@ -42,7 +40,7 @@ enum CreatureIds
{
NPC_SELIN = 24723,
NPC_DELRISSA = 24560,
- NPC_FELCRYSTALS = 24722
+ NPC_FEL_CRYSTAL = 24722
};
enum GameObjectIds
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp
index f415eeacc78..d4dc5efb6d5 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp
@@ -17,6 +17,7 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "SpellAuras.h"
#include "SpellScript.h"
#include "ahnkahet.h"
@@ -31,14 +32,16 @@ enum Yells
enum Spells
{
+ // Elder Nadox
SPELL_BROOD_PLAGUE = 56130,
H_SPELL_BROOD_RAGE = 59465,
SPELL_ENRAGE = 26662, // Enraged if too far away from home
SPELL_SUMMON_SWARMERS = 56119, // 2x 30178 -- 2x every 10secs
- SPELL_SUMMON_SWARM_GUARD = 56120, // 1x 30176 -- every 25%
- // Spells Adds
- SPELL_SPRINT = 56354,
- SPELL_GUARDIAN_AURA = 56151
+ SPELL_SUMMON_SWARM_GUARD = 56120, // 1x 30176
+
+ // Adds
+ SPELL_SWARM_BUFF = 56281,
+ SPELL_SPRINT = 56354
};
enum Events
@@ -63,7 +66,7 @@ class boss_elder_nadox : public CreatureScript
void Reset() override
{
_Reset();
- AmountHealthModifier = 1;
+ GuardianSummoned = false;
GuardianDied = false;
}
@@ -128,6 +131,7 @@ class boss_elder_nadox : public CreatureScript
events.ScheduleEvent(EVENT_RAGE, urand(10 * IN_MILLISECONDS, 50 * IN_MILLISECONDS));
break;
case EVENT_SUMMON_SWARMER:
+ /// @todo: summoned by egg
DoCast(me, SPELL_SUMMON_SWARMERS);
if (urand(1, 3) == 3) // 33% chance of dialog
Talk(SAY_EGG_SAC);
@@ -145,19 +149,20 @@ class boss_elder_nadox : public CreatureScript
}
}
- if (me->HealthBelowPct(100 - AmountHealthModifier* 25))
+ if (!GuardianSummoned && me->HealthBelowPct(50))
{
+ /// @todo: summoned by egg
Talk(EMOTE_HATCHES, me);
DoCast(me, SPELL_SUMMON_SWARM_GUARD);
- ++AmountHealthModifier;
+ GuardianSummoned = true;
}
DoMeleeAttackIfReady();
}
private:
+ bool GuardianSummoned;
bool GuardianDied;
- uint8 AmountHealthModifier;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -175,20 +180,10 @@ class npc_ahnkahar_nerubian : public CreatureScript
{
npc_ahnkahar_nerubianAI(Creature* creature) : ScriptedAI(creature) { }
- EventMap events;
-
void Reset() override
{
- if (me->GetEntry() == NPC_AHNKAHAR_GUARDIAN)
- DoCast(me, SPELL_GUARDIAN_AURA, true);
-
- events.ScheduleEvent(EVENT_SPRINT, 13 * IN_MILLISECONDS);
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- if (me->GetEntry() == NPC_AHNKAHAR_GUARDIAN)
- me->RemoveAurasDueToSpell(SPELL_GUARDIAN_AURA);
+ _events.Reset();
+ _events.ScheduleEvent(EVENT_SPRINT, 13 * IN_MILLISECONDS);
}
void UpdateAI(uint32 diff) override
@@ -196,23 +191,27 @@ class npc_ahnkahar_nerubian : public CreatureScript
if (!UpdateVictim())
return;
- events.Update(diff);
+ _events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
- while (uint32 eventId = events.ExecuteEvent())
+ while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
- case EVENT_SPRINT:
- DoCast(me, SPELL_SPRINT);
- events.ScheduleEvent(EVENT_SPRINT, 20 * IN_MILLISECONDS);
- break;
+ case EVENT_SPRINT:
+ DoCast(me, SPELL_SPRINT);
+ _events.ScheduleEvent(EVENT_SPRINT, 20 * IN_MILLISECONDS);
+ break;
}
}
+
DoMeleeAttackIfReady();
}
+
+ private:
+ EventMap _events;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -221,95 +220,81 @@ class npc_ahnkahar_nerubian : public CreatureScript
}
};
-//HACK: No, AI. Replace with proper db content?
-class npc_nadox_eggs : public CreatureScript
+// 56159 - Swarm
+class spell_ahn_kahet_swarm : public SpellScriptLoader
{
-public:
- npc_nadox_eggs() : CreatureScript("npc_nadox_eggs") { }
+ public:
+ spell_ahn_kahet_swarm() : SpellScriptLoader("spell_ahn_kahet_swarm") { }
- struct npc_nadox_eggsAI : public ScriptedAI
- {
- npc_nadox_eggsAI(Creature* creature) : ScriptedAI(creature)
+ class spell_ahn_kahet_swarm_SpellScript : public SpellScript
{
- creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
- }
+ PrepareSpellScript(spell_ahn_kahet_swarm_SpellScript);
- void Reset() override { }
- void EnterCombat(Unit* /*who*/) override { }
- void AttackStart(Unit* /*victim*/) override { }
- void MoveInLineOfSight(Unit* /*who*/) override { }
-
- void UpdateAI(uint32 /*diff*/) override { }
- };
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_SWARM_BUFF))
+ return false;
+ return true;
+ }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_nadox_eggsAI(creature);
- }
-};
+ bool Load() override
+ {
+ _targetCount = 0;
+ return true;
+ }
-class GuardianCheck
-{
-public:
- bool operator()(const WorldObject* target) const
- {
- if (target->GetEntry() == NPC_AHNKAHAR_GUARDIAN)
- return true;
-
- return false;
- }
-};
+ void CountTargets(std::list<WorldObject*>& targets)
+ {
+ _targetCount = targets.size();
+ }
-class spell_elder_nadox_guardian : public SpellScriptLoader
-{
-public:
- spell_elder_nadox_guardian() : SpellScriptLoader("spell_elder_nadox_guardian") { }
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ if (_targetCount)
+ {
+ if (Aura* aura = GetCaster()->GetAura(SPELL_SWARM_BUFF))
+ {
+ aura->SetStackAmount(_targetCount);
+ aura->RefreshDuration();
+ }
+ else
+ GetCaster()->CastCustomSpell(SPELL_SWARM_BUFF, SPELLVALUE_AURA_STACK, _targetCount, GetCaster(), TRIGGERED_FULL_MASK);
+ }
+ else
+ GetCaster()->RemoveAurasDueToSpell(SPELL_SWARM_BUFF);
+ }
- class spell_elder_nadox_guardian_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_elder_nadox_guardian_SpellScript);
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ahn_kahet_swarm_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
+ OnEffectHit += SpellEffectFn(spell_ahn_kahet_swarm_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
- void FilterTargets(std::list<WorldObject*>& targets)
- {
- targets.remove_if (GuardianCheck());
- }
+ private:
+ uint32 _targetCount;
+ };
- void Register() override
+ SpellScript* GetSpellScript() const override
{
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_elder_nadox_guardian_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY);
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_elder_nadox_guardian_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ALLY);
+ return new spell_ahn_kahet_swarm_SpellScript();
}
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_elder_nadox_guardian_SpellScript();
- }
};
class achievement_respect_your_elders : public AchievementCriteriaScript
{
-public:
- achievement_respect_your_elders() : AchievementCriteriaScript("achievement_respect_your_elders") { }
-
- bool OnCheck(Player* /*player*/, Unit* target) override
- {
- if (!target)
- return false;
-
- if (Creature* Nadox = target->ToCreature())
- if (Nadox->AI()->GetData(DATA_RESPECT_YOUR_ELDERS))
- return true;
+ public:
+ achievement_respect_your_elders() : AchievementCriteriaScript("achievement_respect_your_elders") { }
- return false;
- }
+ bool OnCheck(Player* /*player*/, Unit* target) override
+ {
+ return target && target->GetAI()->GetData(DATA_RESPECT_YOUR_ELDERS);
+ }
};
void AddSC_boss_elder_nadox()
{
new boss_elder_nadox();
new npc_ahnkahar_nerubian();
- new npc_nadox_eggs();
- new spell_elder_nadox_guardian();
+ new spell_ahn_kahet_swarm();
new achievement_respect_your_elders();
}
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index 022c43f4395..d0ad42d38e1 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -961,9 +961,11 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript
if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
{
+ me->CastSpell(lichking, SPELL_TAUNT_ARTHAS, true);
+ lichking->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
+ lichking->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
AttackStart(lichking);
lichking->AI()->AttackStart(me);
- me->CastSpell(lichking, SPELL_TAUNT_ARTHAS, true);
}
me->SetHealth(JAINA_SYLVANAS_MAX_HEALTH);
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
diff --git a/src/server/scripts/Northrend/zone_dalaran.cpp b/src/server/scripts/Northrend/zone_dalaran.cpp
index 2d5028bac05..0897131eaf8 100644
--- a/src/server/scripts/Northrend/zone_dalaran.cpp
+++ b/src/server/scripts/Northrend/zone_dalaran.cpp
@@ -128,7 +128,118 @@ public:
}
};
+enum MinigobData
+{
+ ZONE_DALARAN = 4395,
+
+ SPELL_MANABONKED = 61834,
+ SPELL_TELEPORT_VISUAL = 51347,
+ SPELL_IMPROVED_BLINK = 61995,
+
+ EVENT_SELECT_TARGET = 1,
+ EVENT_BLINK = 2,
+ EVENT_DESPAWN_VISUAL = 3,
+ EVENT_DESPAWN = 4,
+
+ MAIL_MINIGOB_ENTRY = 264,
+ MAIL_DELIVER_DELAY_MIN = 5*MINUTE,
+ MAIL_DELIVER_DELAY_MAX = 15*MINUTE
+};
+
+class npc_minigob_manabonk : public CreatureScript
+{
+ public:
+ npc_minigob_manabonk() : CreatureScript("npc_minigob_manabonk") {}
+
+ struct npc_minigob_manabonkAI : public ScriptedAI
+ {
+ npc_minigob_manabonkAI(Creature* creature) : ScriptedAI(creature)
+ {
+ me->setActive(true);
+ }
+
+ void Reset()
+ {
+ me->SetVisible(false);
+ events.ScheduleEvent(EVENT_SELECT_TARGET, IN_MILLISECONDS);
+ }
+
+ Player* SelectTargetInDalaran()
+ {
+ std::list<Player*> PlayerInDalaranList;
+ PlayerInDalaranList.clear();
+
+ Map::PlayerList const &players = me->GetMap()->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player* player = itr->GetSource()->ToPlayer())
+ if (player->GetZoneId() == ZONE_DALARAN && !player->IsFlying() && !player->IsMounted() && !player->IsGameMaster())
+ PlayerInDalaranList.push_back(player);
+
+ if (PlayerInDalaranList.empty())
+ return NULL;
+ return Trinity::Containers::SelectRandomContainerElement(PlayerInDalaranList);
+ }
+
+ void SendMailToPlayer(Player* player)
+ {
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ int16 deliverDelay = irand(MAIL_DELIVER_DELAY_MIN, MAIL_DELIVER_DELAY_MAX);
+ MailDraft(MAIL_MINIGOB_ENTRY, true).SendMailTo(trans, MailReceiver(player), MailSender(MAIL_CREATURE, me->GetEntry()), MAIL_CHECK_MASK_NONE, deliverDelay);
+ CharacterDatabase.CommitTransaction(trans);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SELECT_TARGET:
+ me->SetVisible(true);
+ DoCast(me, SPELL_TELEPORT_VISUAL);
+ if (Player* player = SelectTargetInDalaran())
+ {
+ me->NearTeleportTo(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), 0.0f);
+ DoCast(player, SPELL_MANABONKED);
+ SendMailToPlayer(player);
+ }
+ events.ScheduleEvent(EVENT_BLINK, 3*IN_MILLISECONDS);
+ break;
+ case EVENT_BLINK:
+ {
+ DoCast(me, SPELL_IMPROVED_BLINK);
+ Position pos = me->GetRandomNearPosition(frand(15, 40));
+ me->GetMotionMaster()->MovePoint(0, pos.m_positionX, pos.m_positionY, pos.m_positionZ);
+ events.ScheduleEvent(EVENT_DESPAWN, 3 * IN_MILLISECONDS);
+ events.ScheduleEvent(EVENT_DESPAWN_VISUAL, 2.5*IN_MILLISECONDS);
+ break;
+ }
+ case EVENT_DESPAWN_VISUAL:
+ DoCast(me, SPELL_TELEPORT_VISUAL);
+ break;
+ case EVENT_DESPAWN:
+ me->DespawnOrUnsummon();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_minigob_manabonkAI(creature);
+ }
+};
+
void AddSC_dalaran()
{
- new npc_mageguard_dalaran;
+ new npc_mageguard_dalaran();
+ new npc_minigob_manabonk();
}