diff options
-rw-r--r-- | src/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp | 168 |
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) |