289 lines
9.5 KiB
C#
289 lines
9.5 KiB
C#
/*
|
|
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
|
*
|
|
* 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 3 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/>.
|
|
*/
|
|
|
|
using Framework.Constants;
|
|
using Game.AI;
|
|
using Game.Entities;
|
|
using Game.Maps;
|
|
using Game.Scripting;
|
|
using Game.Spells;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Scripts.Northrend.AzjolNerub.Ahnkahet.HeraldVolazj
|
|
{
|
|
struct SpellIds
|
|
{
|
|
public const uint Insanity = 57496; //Dummy
|
|
public const uint InsanityVisual = 57561;
|
|
public const uint InsanityTarget = 57508;
|
|
public const uint MindFlay = 57941;
|
|
public const uint ShadowBoltVolley = 57942;
|
|
public const uint Shiver = 57949;
|
|
public const uint ClonePlayer = 57507; //Cast On Player During Insanity
|
|
public const uint InsanityPhasing1 = 57508;
|
|
public const uint InsanityPhasing2 = 57509;
|
|
public const uint InsanityPhasing3 = 57510;
|
|
public const uint InsanityPhasing4 = 57511;
|
|
public const uint InsanityPhasing5 = 57512;
|
|
}
|
|
|
|
struct TextIds
|
|
{
|
|
public const uint SayAggro = 0;
|
|
public const uint SaySlay = 1;
|
|
public const uint SayDeath = 2;
|
|
public const uint SayPhase = 3;
|
|
}
|
|
|
|
struct Misc
|
|
{
|
|
public const uint AchievQuickDemiseStartEvent = 20382;
|
|
}
|
|
|
|
[Script]
|
|
class boss_volazj : ScriptedAI
|
|
{
|
|
public boss_volazj(Creature creature) : base(creature)
|
|
{
|
|
Summons = new SummonList(me);
|
|
|
|
Initialize();
|
|
instance = creature.GetInstanceScript();
|
|
}
|
|
|
|
void Initialize()
|
|
{
|
|
uiMindFlayTimer = 8 * Time.InMilliseconds;
|
|
uiShadowBoltVolleyTimer = 5 * Time.InMilliseconds;
|
|
uiShiverTimer = 15 * Time.InMilliseconds;
|
|
// Used for Insanity handling
|
|
insanityHandled = 0;
|
|
}
|
|
|
|
// returns the percentage of health after taking the given damage.
|
|
uint GetHealthPct(uint damage)
|
|
{
|
|
if (damage > me.GetHealth())
|
|
return 0;
|
|
return (uint)(100 * (me.GetHealth() - damage) / me.GetMaxHealth());
|
|
}
|
|
|
|
public override void DamageTaken(Unit pAttacker, ref uint damage)
|
|
{
|
|
if (me.HasFlag(UnitFields.Flags, UnitFlags.NotSelectable))
|
|
damage = 0;
|
|
|
|
if ((GetHealthPct(0) >= 66 && GetHealthPct(damage) < 66) ||
|
|
(GetHealthPct(0) >= 33 && GetHealthPct(damage) < 33))
|
|
{
|
|
me.InterruptNonMeleeSpells(false);
|
|
DoCast(me, SpellIds.Insanity, false);
|
|
}
|
|
}
|
|
|
|
public override void SpellHitTarget(Unit target, SpellInfo spell)
|
|
{
|
|
if (spell.Id == SpellIds.Insanity)
|
|
{
|
|
// Not good target or too many players
|
|
if (target.GetTypeId() != TypeId.Player || insanityHandled > 4)
|
|
return;
|
|
// First target - start channel visual and set self as unnattackable
|
|
if (insanityHandled == 0)
|
|
{
|
|
// Channel visual
|
|
DoCast(me, SpellIds.InsanityVisual, true);
|
|
// Unattackable
|
|
me.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
|
me.SetControlled(true, UnitState.Stunned);
|
|
}
|
|
|
|
// phase the player
|
|
target.CastSpell(target, SpellIds.InsanityTarget + insanityHandled, true);
|
|
|
|
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(SpellIds.InsanityTarget + insanityHandled);
|
|
if (spellInfo == null)
|
|
return;
|
|
|
|
// summon twisted party members for this target
|
|
var players = me.GetMap().GetPlayers();
|
|
foreach (var player in players)
|
|
{
|
|
if (!player || !player.IsAlive())
|
|
continue;
|
|
// Summon clone
|
|
Unit summon = me.SummonCreature(AKCreatureIds.TwistedVisage, me.GetPositionX(), me.GetPositionY(), me.GetPositionZ(), me.GetOrientation(), TempSummonType.CorpseDespawn, 0);
|
|
if (summon)
|
|
{
|
|
// clone
|
|
player.CastSpell(summon, SpellIds.ClonePlayer, true);
|
|
// phase the summon
|
|
summon.SetInPhase((uint)spellInfo.GetEffect(0).MiscValueB, true, true);
|
|
}
|
|
}
|
|
++insanityHandled;
|
|
}
|
|
}
|
|
|
|
void ResetPlayersPhase()
|
|
{
|
|
var players = me.GetMap().GetPlayers();
|
|
foreach (var player in players)
|
|
{
|
|
for (uint index = 0; index <= 4; ++index)
|
|
player.RemoveAurasDueToSpell(SpellIds.InsanityTarget + index);
|
|
}
|
|
}
|
|
|
|
public override void Reset()
|
|
{
|
|
Initialize();
|
|
|
|
instance.SetBossState(DataTypes.HeraldVolazj, EncounterState.NotStarted);
|
|
instance.DoStopCriteriaTimer(CriteriaTimedTypes.Event, Misc.AchievQuickDemiseStartEvent);
|
|
|
|
// Visible for all players in insanity
|
|
me.SetInPhase(169, true, true);
|
|
for (uint i = 173; i <= 177; ++i)
|
|
me.SetInPhase(i, true, true);
|
|
|
|
ResetPlayersPhase();
|
|
|
|
// Cleanup
|
|
Summons.DespawnAll();
|
|
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
|
me.SetControlled(false, UnitState.Stunned);
|
|
}
|
|
|
|
public override void EnterCombat(Unit who)
|
|
{
|
|
Talk(TextIds.SayAggro);
|
|
|
|
instance.SetBossState(DataTypes.HeraldVolazj, EncounterState.InProgress);
|
|
instance.DoStartCriteriaTimer(CriteriaTimedTypes.Event, Misc.AchievQuickDemiseStartEvent);
|
|
}
|
|
|
|
public override void JustSummoned(Creature summon)
|
|
{
|
|
Summons.Summon(summon);
|
|
}
|
|
|
|
public override void SummonedCreatureDespawn(Creature summon)
|
|
{
|
|
uint nextPhase = 0;
|
|
Summons.Despawn(summon);
|
|
|
|
// Check if all summons in this phase killed
|
|
foreach (var guid in Summons)
|
|
{
|
|
Creature visage = ObjectAccessor.GetCreature(me, guid);
|
|
if (visage)
|
|
{
|
|
// Not all are dead
|
|
if (visage.IsInPhase(summon))
|
|
return;
|
|
else
|
|
{
|
|
nextPhase = visage.GetPhases().First();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Roll Insanity
|
|
var players = me.GetMap().GetPlayers();
|
|
foreach (var player in players)
|
|
{
|
|
if (player)
|
|
{
|
|
for (uint index = 0; index <= 4; ++index)
|
|
player.RemoveAurasDueToSpell(SpellIds.InsanityTarget + index);
|
|
player.CastSpell(player, SpellIds.InsanityTarget + nextPhase - 173, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void UpdateAI(uint diff)
|
|
{
|
|
//Return since we have no target
|
|
if (!UpdateVictim())
|
|
return;
|
|
|
|
if (insanityHandled != 0)
|
|
{
|
|
if (!Summons.Empty())
|
|
return;
|
|
|
|
insanityHandled = 0;
|
|
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
|
me.SetControlled(false, UnitState.Stunned);
|
|
me.RemoveAurasDueToSpell(SpellIds.InsanityVisual);
|
|
}
|
|
|
|
if (uiMindFlayTimer <= diff)
|
|
{
|
|
DoCastVictim(SpellIds.MindFlay);
|
|
uiMindFlayTimer = 20 * Time.InMilliseconds;
|
|
}
|
|
else uiMindFlayTimer -= diff;
|
|
|
|
if (uiShadowBoltVolleyTimer <= diff)
|
|
{
|
|
DoCastVictim(SpellIds.ShadowBoltVolley);
|
|
uiShadowBoltVolleyTimer = 5 * Time.InMilliseconds;
|
|
}
|
|
else uiShadowBoltVolleyTimer -= diff;
|
|
|
|
if (uiShiverTimer <= diff)
|
|
{
|
|
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
|
if (target)
|
|
DoCast(target, SpellIds.Shiver);
|
|
uiShiverTimer = 15 * Time.InMilliseconds;
|
|
}
|
|
else uiShiverTimer -= diff;
|
|
|
|
DoMeleeAttackIfReady();
|
|
}
|
|
|
|
public override void JustDied(Unit killer)
|
|
{
|
|
Talk(TextIds.SayDeath);
|
|
|
|
instance.SetBossState(DataTypes.HeraldVolazj, EncounterState.Done);
|
|
|
|
Summons.DespawnAll();
|
|
ResetPlayersPhase();
|
|
}
|
|
|
|
public override void KilledUnit(Unit who)
|
|
{
|
|
if (who.IsTypeId(TypeId.Player))
|
|
Talk(TextIds.SaySlay);
|
|
}
|
|
|
|
InstanceScript instance;
|
|
|
|
uint uiMindFlayTimer;
|
|
uint uiShadowBoltVolleyTimer;
|
|
uint uiShiverTimer;
|
|
uint insanityHandled;
|
|
SummonList Summons;
|
|
}
|
|
}
|