aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp168
1 files changed, 164 insertions, 4 deletions
diff --git a/src/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp b/src/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp
index 63a2a16634d..ab2c23fd955 100644
--- a/src/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp
+++ b/src/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp
@@ -18,9 +18,9 @@
/* ScriptData
SDName: boss_herald_volazj
-SDAuthor: Tartalo
-SD%Complete: 20
-SDComment: Coded all but Insanity
+SDAuthor: thenecromancer
+SD%Complete: ??
+SDComment: Missing AI for Twisted Visages
SDCategory: Ahn'kahet
EndScriptData */
@@ -31,6 +31,7 @@ enum Spells
{
SPELL_INSANITY = 57496, //Dummy
INSANITY_VISUAL = 57561,
+ SPELL_INSANITY_TARGET = 57508,
SPELL_MIND_FLAY = 57941,
H_SPELL_MIND_FLAY = 59974,
SPELL_SHADOW_BOLT_VOLLEY = 57942,
@@ -39,6 +40,8 @@ enum Spells
H_SPELL_SHIVER = 59978
};
+#define MOB_TWISTED_VISAGE 30625
+
//not in db
enum Yells
{
@@ -58,7 +61,7 @@ enum Achievements
struct TRINITY_DLL_DECL boss_volazjAI : public ScriptedAI
{
- boss_volazjAI(Creature* pCreature) : ScriptedAI(pCreature)
+ boss_volazjAI(Creature* pCreature) : ScriptedAI(pCreature),Summons(m_creature)
{
pInstance = pCreature->GetInstanceData();
}
@@ -69,6 +72,69 @@ struct TRINITY_DLL_DECL boss_volazjAI : public ScriptedAI
uint32 uiShadowBoltVolleyTimer;
uint32 uiShiverTimer;
uint32 uiEncounterTimer;
+ uint32 insanityHandled;
+ SummonList Summons;
+
+ uint32 GetHealthPct(uint32 damage)
+ {
+ if (damage > me->GetHealth())
+ return 0;
+ return 100*(me->GetHealth()-damage)/me->GetMaxHealth();
+ }
+
+ void DamageTaken(Unit *pAttacker, uint32 &damage)
+ {
+ if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
+ damage = 0;
+
+ if ((GetHealthPct(0) >= 66 && GetHealthPct(damage) < 66)||
+ (GetHealthPct(0) >= 33 && GetHealthPct(damage) < 33))
+ {
+ me->InterruptNonMeleeSpells(false);
+ DoCast(me, SPELL_INSANITY, false);
+ }
+ }
+
+ void SpellHitTarget(Unit *pTarget, const SpellEntry *spell)
+ {
+ if (spell->Id == SPELL_INSANITY)
+ {
+ // Not good target or too many players
+ if (pTarget->GetTypeId() != TYPEID_PLAYER || insanityHandled > 4)
+ return;
+ // First target - start channel visual and set self as unnattackable
+ if (!insanityHandled)
+ {
+ // Channel visual
+ DoCast(me, INSANITY_VISUAL, true);
+ // Unattackable
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetControlled(true, UNIT_STAT_STUNNED);
+ }
+ // phase mask
+ pTarget->CastSpell(pTarget, SPELL_INSANITY_TARGET+insanityHandled, true);
+ // summon twisted party members for this target
+ Map::PlayerList const &players = m_creature->GetMap()->GetPlayers();
+ for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
+ {
+ Player *plr = i->getSource();
+ if (!plr || !plr->isAlive())
+ continue;
+ // Summon clone
+ if (Unit *summon = me->SummonCreature(MOB_TWISTED_VISAGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,0))
+ {
+ // required for correct visual
+ // Fixme: allow mirror image query to send other guid to get rid of minion status
+ summon->SetUInt64Value(UNIT_FIELD_CREATEDBY, plr->GetGUID());
+ // clone
+ plr->CastSpell(summon, 57507, true);
+ // set phase
+ summon->SetPhaseMask((1<<(4+insanityHandled)),true);
+ }
+ }
+ ++insanityHandled;
+ }
+ }
void Reset()
{
@@ -79,6 +145,15 @@ struct TRINITY_DLL_DECL boss_volazjAI : public ScriptedAI
if (pInstance)
pInstance->SetData(DATA_HERALD_VOLAZJ, NOT_STARTED);
+
+ // Visible for all players in insanity
+ me->SetPhaseMask((1|16|32|64|128|256),true);
+ // Used for Insanity handling
+ insanityHandled = 0;
+
+ // Cleanup
+ Summons.DespawnAll();
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
void EnterCombat(Unit* who)
@@ -89,12 +164,96 @@ struct TRINITY_DLL_DECL boss_volazjAI : public ScriptedAI
pInstance->SetData(DATA_HERALD_VOLAZJ, IN_PROGRESS);
}
+ void JustSummoned(Creature *summon)
+ {
+ Summons.Summon(summon);
+ }
+
+ uint32 GetSpellForPhaseMask(uint32 phase)
+ {
+ uint32 spell = 0;
+ switch (phase)
+ {
+ case 16:
+ spell = 57508;
+ break;
+ case 32:
+ spell = 57509;
+ break;
+ case 64:
+ spell = 57510;
+ break;
+ case 128:
+ spell = 57511;
+ break;
+ case 256:
+ spell = 57512;
+ break;
+ }
+ return spell;
+ }
+
+ void SummonedCreatureDespawn(Creature *summon)
+ {
+ uint32 phase= summon->GetPhaseMask();
+ uint32 nextPhase = 0;
+ Summons.Despawn(summon);
+
+ // Check if all summons in this phase killed
+ for(SummonList::const_iterator iter = Summons.begin(); iter!=Summons.end(); iter++)
+ {
+ if(Creature *visage = Unit::GetCreature(*m_creature, *iter))
+ {
+ // Not all are dead
+ if (phase == visage->GetPhaseMask())
+ return;
+ else
+ nextPhase = visage->GetPhaseMask();
+ }
+ }
+
+ // Roll Insanity
+ uint32 spell = GetSpellForPhaseMask(phase);
+ uint32 spell2 = GetSpellForPhaseMask(nextPhase);
+ Map* pMap = m_creature->GetMap();
+ if (!pMap)
+ return;
+
+ Map::PlayerList const &PlayerList = pMap->GetPlayers();
+ if (!PlayerList.isEmpty())
+ {
+ for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ {
+ if (Player* pPlayer = i->getSource())
+ {
+ if (pPlayer->HasAura(spell))
+ {
+ pPlayer->RemoveAurasDueToSpell(spell);
+ if (spell2) // if there is still some different mask cast spell for it
+ pPlayer->CastSpell(pPlayer, spell2, true);
+ }
+ }
+ }
+ }
+ }
+
void UpdateAI(const uint32 diff)
{
//Return since we have no target
if (!UpdateVictim())
return;
+ if (insanityHandled)
+ {
+ if (!Summons.empty())
+ return;
+
+ insanityHandled = 0;
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetControlled(false, UNIT_STAT_STUNNED);
+ me->RemoveAurasDueToSpell(INSANITY_VISUAL);
+ }
+
if (uiMindFlayTimer <= diff)
{
DoCast(m_creature->getVictim(), DUNGEON_MODE(SPELL_MIND_FLAY, H_SPELL_MIND_FLAY));
@@ -134,6 +293,7 @@ struct TRINITY_DLL_DECL boss_volazjAI : public ScriptedAI
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
itr->getSource()->CompletedAchievement(AchievQuickDemise);
}
+ Summons.DespawnAll();
}
void KilledUnit(Unit *victim)